einstein1969 wrote:This version is not fully optimized. If anyone has suggestions for improvement are well accepted
Einstein1969
I am afraid that you still don't understand that if you want us to help you, you must help us to understand your code!
You made several modifications in your code compared with the last version, but there is not a single explanation about the changes; this point force us to replicate all your changes in order to reach the point where we can go further and optimize that code. If you would explained your changes, we would understand them in a couple minutes instead of spend more than a couple hours in this matter!
For example, you didn't explained that you made algebraic modifications in the equations in order to perform less operations in the inner most loop, although the resulting equations seems more complex than the originals, nor that you have replicated these calculations four times in each SET /A command in order to simultaneously calculate and draw four points per cycle, etc. I still think that you should started this thread with a short explanation, like this one: "The purpose of this topic is to draw the projection of the 3D-surface given by the equation F(X,Y) = (X^2+Y^2)^5 - ((X^2-Y^2)8XY)^2 on Z=0 plane, from (-2,2) to (2,-2) coordinates..." (like I did in
this post) "... and rotate it in the fastest possible animation" (forget the "raytracing" and "multi-process" stuff).
There is a single point that deserve special mention. We all know that if a large number of variables are defined, the processing of a Batch file slow down; what we didn't know is the large amount this point affect the speed of a program when there are few variables. If there are just 40-50 variables with values around 20-60 characters each (that is, the normal environment contents), the addition of just 10-15 short variables slow down the program in a major grade! This means that the only way to run a Batch file at its maximum possible speed is via
deleting ALL variables from the environment and try to keep the working variables to the minimum. Even the inclusion of a single short variable (like "SET T2=!TIME!") affects the elapsed time in a measurable amount!
It is faster to store the value in a disk file ("ECHO !TIME! > TEMPFILE.TXT"), later read it ("SET /P T2=< TEMPFILE.TXT") and delete the variable after it was used (with all the involved overhead) that just keep the variable in the environment while other calculations are performed. einstein1969: this point is
very important, why you didn't posted it? (I did it!
)
The Batch file below is an optimized version of your last code; it takes an optional parameter that specify the number of simultaneous points that are calculated in each SET /A command. If this parameter is not given, the program uses the largest factor (maximum 26) of the number of columns in the drawing, although this does not assure that this factor produce the fastest animation when the program run in a given computer. If the number of columns have not a factor less or equal 26, the program show an error message. The code is listed here as you like it: with no explanations!
Code: Select all
@echo off
setlocal DisableDelayedExpansion
set bang=!
setlocal EnableDelayedExpansion
rem Graph dimensions:
set /a cols=32, lines=34
set "Num=%~1"
if not defined Num (
for /L %%i in (1,1,26) do (
set /A mod=cols%%%%i
if !mod! equ 0 set Num=%%i
)
)
if not defined Num echo %cols% columns have not factors less or equal 26 & goto :EOF
set /A mod=cols%%Num
if %mod% neq 0 echo %Num% is not a factor of %cols% columns & goto :EOF
set /a scrCols=cols*2+4, scrLines=lines+4, colsDiv2=cols/2, linesDiv2=lines/2, lastPoint=cols-Num+1, F=0
set "expr="
set "tokens="
set "points="
set "letter=0ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for /L %%h in (1,1,%Num%) do (
set "expr=!expr!, b=((x-%colsDiv2%)*100/8)*cos/100-i, e=((x-%colsDiv2%)*100/8)*sin/100+j, d=b*b/100+e*e/100, e=(b*b/100-e*e/100)*8*b/100*e/100, h%%h=((d*d/100*d/100*d/100*d/100-e*e/100)>>31)&1, x+=1"
set "tokens=!tokens! !bang!h%%h!bang!"
set "points=!points!!bang!O:~%%!letter:~%%h,1!,1!bang!"
)
mode con cols=%scrCols% lines=%scrLines%
For /L %%i in (1,1,500) do (
for %%a in ("F=!F!") do (
for /F "delims==" %%v in ('set') do set "%%v="
set %%a
)
echo !time: =0!> "%tmp%\t2.txt"
rem rotate 15 degree each frame
set /a "angle=%%i*150000%%450000"
if !angle! geq 0 (
set /a x=607252935, angle=angle*1000-450000000, y=x
) else (
set /a x=607252935, angle=angle*1000+450000000, y=-x
)
set i=0
for %%a in (265650512 140362435 71250163 35763344 17899106 8951737
4476142 2238105 1119057 559529 279765 139882 69941 34971
17485 8743 4371 2186 1093 546 273 137 68 34 17 9 4 2 1
) do (
if !angle! lss 0 (
set /a "angle+=%%a, i+=1, dx=x/(1<<i), x+=y/(1<<i), y-=dx"
) else (
set /a "angle-=%%a, i+=1, dx=x/(1<<i), x-=y/(1<<i), y+=dx"
)
)
set /a sin=y/10000000, cos=x/10000000
for %%v in (angle i x y dx) do set "%%v="
set "O= *"
(for /L %%y in (1,1,%lines%) do (
set "line="
set /a "i=((%%y-%linesDiv2%)*100/8)*sin/100, j=((%%y-%linesDiv2%)*100/8)*cos/100"
for /L %%x in (1,%Num%,%lastPoint%) do (
set /a "x=%%x %expr%"
for /F "tokens=1-%Num%" %%A in ("%tokens%") do set "line=!line!%points%"
)
echo/ !line! !line!
)) > "%tmp%\frame.txt"
cls
type "%tmp%\frame.txt"
set /P "t2=" < "%tmp%\t2.txt"
for /F "tokens=1-8 delims=:.," %%a in ("!t2!:!time: =0!") do set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31)&8640000"
if %%i leq 15 (
echo Calibrating, please wait...
) else (
set /A "F+=10000/a, FPS=F/(%%i-15)"
echo Num=%Num%, FPS=!FPS:~0,-2!.!FPS:~-2! [!a!cs]
)
)
The Batch file below is a modified version that calculate the sin and cos values via a simpler method (direct table access), so it run faster.
Code: Select all
@echo off
setlocal DisableDelayedExpansion
set bang=!
setlocal EnableDelayedExpansion
rem Graph dimensions:
set /a cols=32, lines=34
set "Num=%~1"
if not defined Num (
for /L %%i in (1,1,26) do (
set /A mod=cols%%%%i
if !mod! equ 0 set Num=%%i
)
)
if not defined Num echo %cols% columns have not factors less or equal 26 & goto :EOF
set /A mod=cols%%Num
if %mod% neq 0 echo %Num% is not a factor of %cols% columns & goto :EOF
set /a scrCols=cols*2+4, scrLines=lines+4, colsDiv2=cols/2, linesDiv2=lines/2, lastPoint=cols-Num+1, F=0
set "expr="
set "tokens="
set "points="
set "letter=0ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for /L %%h in (1,1,%Num%) do (
set "expr=!expr!, b=((x-%colsDiv2%)*100/8)*cos/65536-i, e=((x-%colsDiv2%)*100/8)*sin/65536+j, d=b*b/100+e*e/100, e=(b*b/100-e*e/100)*8*b/100*e/100, h%%h=((d*d/100*d/100*d/100*d/100-e*e/100)>>31)&1, x+=1"
set "tokens=!tokens! !bang!h%%h!bang!"
set "points=!points!!bang!O:~%%!letter:~%%h,1!,1!bang!"
)
mode con cols=%scrCols% lines=%scrLines%
For /L %%i in (1,1,500) do (
for %%a in ("F=!F!") do (
for /F "delims==" %%v in ('set') do set "%%v="
set %%a
)
echo !time: =0!> "%tmp%\t2.txt"
rem rotate 15 degree each frame
set /a "angle=%%i*15%%45, s=angle*6, c=(44-angle)*6"
set "sin= 0 1144 2287 3430 4572 5712 6850 7987 9121 10252 11380 12505 13626 14742 15855 16962 18064 19161 20252 21336 22415 23486 24550 25607 26656 27697 28729 29753 30767 31772 32768 33754 34729 35693 36647 37590 38521 39441 40348 41243 42126 42995 43852 44695 45525"
set "cos= 47143 47930 48703 49461 50203 50931 51643 52339 53020 53684 54332 54963 55578 56175 56756 57319 57865 58393 58903 59396 59870 60326 60764 61183 61584 61966 62328 62672 62997 63303 63589 63856 64104 64332 64540 64729 64898 65048 65177 65287 65376 65446 65496 65526 65536"
for /F "tokens=1,2" %%a in ("!s! !c!") do set /A "sin=!sin:~%%a,6!, cos=!cos:~%%b,6!"
for %%v in (angle s c) do set "%%v="
set "O= *"
(for /L %%y in (1,1,%lines%) do (
set "line="
set /a "i=((%%y-%linesDiv2%)*100/8)*sin/65536, j=((%%y-%linesDiv2%)*100/8)*cos/65536"
for /L %%x in (1,%Num%,%lastPoint%) do (
set /a "x=%%x %expr%"
for /F "tokens=1-%Num%" %%A in ("%tokens%") do set "line=!line!%points%"
)
echo/ !line! !line!
)) > "%tmp%\frame.txt"
cls
type "%tmp%\frame.txt"
set /P "t2=" < "%tmp%\t2.txt"
for /F "tokens=1-8 delims=:.," %%a in ("!t2!:!time: =0!") do set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31)&8640000"
if %%i leq 20 (
echo Calibrating, please wait...
) else (
set /A "F+=10000/a, FPS=F/(%%i-20)"
echo Num=%Num%, FPS=!FPS:~0,-2!.!FPS:~-2! [!a!cs]
)
)
Antonio