## Fastest sin(x) in dos batch

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
foxidrive
Expert
Posts: 6033
Joined: 10 Feb 2012 02:20

### Re: Fastest sin(x) in dos batch

Here are the new results.

Code: Select all

FPS=13333.33 [75.0 µs] [#601-1400]
FPS=13338.89 [74.9 µs] [#1400-2200]
FPS=13245.03 [75.5 µs] [#2200-2994]

Code: Select all

FPS=20996.37 [47.6 µs] [#1359-2618]
FPS=21159.66 [47.2 µs] [#2618-3887]
FPS=21009.93 [47.5 µs] [#3887-5147]

For comparison this PC has an Intel i7-2600 CPU 3.7 GHz

einstein1969
Expert
Posts: 779
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

### Re: Fastest sin(x) in dos batch

Hi,

I have found this new implementation by user neorobin. I thinks that this version of SIN is faster, but I have not done TEST.

@neorobin
can you explain this part?

Code: Select all

s1=(t-p#2^t-p3#2)>>31

why that XOR?

neorobin wrote:Hi einstein1969

I made another implementation, origin from 3D Sphere viewtopic.php?f=3&t=5594

map rule: [0,2pi) to [-pi/2, pi/2]

Code: Select all

angle t in [0,2pi)

0 <= t < pi/2       t -> t          in [-pi/2, 0)
not need map

pi/2 <= t < 3pi/2   t -> pi-t       in (-pi/2, pi/2]

sin(t) = sin(pi-t),    cos(t) = -cos(pi-t)

3pi/2 <= t < 2pi    t -> -2pi+t     in [-pi/2, 0)

sin(t) = sin(-2pi+t),  cos(t) = cos(-2pi+t)

my test code

Code: Select all

@echo off
mode 100
set "SIN=(t-t*t/1875*t/320000+t*t/1875*t/15625*t/16000*t/2560000-t*t/1875*t/15360*t/15625*t/15625*t/16000*t/44800000)"
set "COS=(10000-t*t/20000+t*t/1875*t/15625*t/819200-t*t/1875*t/15360*t/15625*t/15625*t/10240000+t*t/1875*t/15360*t/15625*t/15625*t/16000*t/15625*t/229376000)"

REM 15 test angles in [0, 2Pi) step by Pi/8
set "List=0,3927,7854,11781,15708,19635,23562,27489,31416,35343,39270,43197,47124,51051,54978,58905"
set /a "p=31416, p2=62832, pn2=-62832, p#2=15708, p3#2=47124, p3#2_=p3#2-1"
set R_Sin=
set R_Cos=

for %%a in (%List%) do (
set /a "t=%%a"
set /a "t%%=p2,s1=(t-p#2^t-p3#2)>>31, s3=p3#2_-t>>31, t=(-t&s1)+(t&~s1)+(p&s1)+(pn2&s3), r1=%SIN%"
set /a "t=%COS%, r2=(-t&s1)+(t&~s1)"
setlocal EnableDelayedExpansion
set R_Sin=!R_Sin!!r1!,
set R_Cos=!R_Cos!!r2!,
)
set R_
pause

test result

Code: Select all

R_Cos=10000,9238,7071,3826,0,-3826,-7071,-9238,-10000,-9238,-7071,-3826,0,3826,7071,9238,
R_Sin=0,3827,7071,9239,9999,9239,7071,3827,0,-3827,-7071,-9239,-9999,-9239,-7071,-3827,

Two usage examples: tested on WIN7 64bit and XP 32bit

Please edit the code, replace the ★ to a real TAB character (ASCII 0x9).

spiral

Code: Select all

@echo off & setlocal enabledelayedexpansion

set "TAB=★" & for /F %%a in ('"prompt \$h&for %%b in (1) do rem"')do Set "BS=%%a"

set /a "ZM=10000, p=31416, p2=62832, pn2=-62832, p#2=15708, p3#2=47124, p3#2_=p3#2-1, DEG=31416/180"
set "SIN=(t-t*t/1875*t/320000+t*t/1875*t/15625*t/16000*t/2560000-t*t/1875*t/15360*t/15625*t/15625*t/16000*t/44800000)"
set "COS=(10000-t*t/20000+t*t/1875*t/15625*t/819200-t*t/1875*t/15360*t/15625*t/15625*t/10240000+t*t/1875*t/15360*t/15625*t/15625*t/16000*t/15625*t/229376000)"

set /a "wid=75, hei=75, iMax=wid*hei, wid_div_2 = wid / 2 - 3"
color 0c & mode !wid!,!hei!

(for /l %%i in (1 1 !iMax!) do set "scr= !scr!") & set "emp=!scr!"

set /a "buffwid = wid, linesWantBackAbove = hei - 1, cntBS = 2 + (buffwid + 7) / 8 * linesWantBackAbove"

set "BSs=" & for /L %%a in (1 1 !cntBS!) do set "BSs=!BSs!%BS%"
set "aLineBS=" & for /L %%a in (1 1 !wid!) do set "aLineBS=!aLineBS!%BS%"

set /a "XC = wid/2, YC = hei/2, DEG_unit = 3, ddu=1, th0=!random! %% 360 * DEG"

for /L %%i in (5000 -1 0) do (

set /a "th=th0+p2+DEG*%%i, DEG_unit+=ddu, DEG_unit= DEG_unit %% 360"

for /l %%a in (0 1 !wid_div_2!) do (
set /a "th+=p2+DEG * DEG_unit, th %%= p2, th += th>>31&p2, t=th, s1=(t-p#2^t-p3#2)>>31, s3=p3#2_-t>>31, t=(-t&s1)+(t&~s1)+(p&s1)+(pn2&s3), SINt=%SIN%, t=%COS%, COSt=(-t&s1)+(t&~s1)"

set /a "r=%%a, x=(XC*10000 + r * COSt)/10000, y=(YC*10000 + r * SINt)/10000, inScr=(x-0^x-wid)&(y-0^y-hei)"

REM if !inScr! lss 0 (
set /a "ind=x+y*wid+1, lenL=ind-1"
for /f "tokens=1,2" %%a in ("!lenL! !ind!") do (set scr=!scr:~0,%%a!*!scr:~%%b!)
REM )
)

<nul set /p "=!aLineBS!" & (2>nul echo;%TAB%!BSs!) & <nul set /p "=%BS%"
<nul set /p "=%BS%!scr:~0,-1!" & set "scr=!emp!" & title %%i / 5000
)
>nul pause
exit

3D Torus Vortex

Please edit the code, replace the ★ to a real TAB character (ASCII 0x9).

Code: Select all

@echo off & setlocal enabledelayedexpansion & chcp 437 & title 3D Torus Vortex

set "Path=%SystemRoot%\system32" & for /f "delims==" %%a in ('set') do if /i "%%a" neq "Path" set "%%a="
set "SIN=(t-t*t/1875*t/320000+t*t/1875*t/15625*t/16000*t/2560000-t*t/1875*t/15360*t/15625*t/15625*t/16000*t/44800000)"
set "COS=(10000-t*t/20000+t*t/1875*t/15625*t/819200-t*t/1875*t/15360*t/15625*t/15625*t/10240000+t*t/1875*t/15360*t/15625*t/15625*t/16000*t/15625*t/229376000)"
set /a "ZM=10000, p=31416, p2=62832, pn2=-62832, p#2=15708, p3#2=47124, p3#2_=p3#2-1, DEG=31416/180"

set /a "Cols=wid=330, lines=hei=130, lines_plus_1=lines+1"
mode !Cols!,!lines_plus_1!

set "TAB=★" & for /F %%a in ('"prompt \$h&for %%b in (1) do rem"')do Set "BS=%%a"
set /a "buffwid = wid, linesWantBackAbove = hei - 1 + 1, cntBS = 2 + (buffwid + 7) / 8 * linesWantBackAbove"
set "BSs=" & for /L %%a in (1 1 !cntBS!) do set "BSs=!BSs!%BS%"
set "aLineBS=" & for /L %%a in (1 1 !wid!) do set "aLineBS=!aLineBS!%BS%"

set "LN0=" & for /L %%C in (1 1 !Cols!) do set "LN0= !LN0!"
for /L %%L in (1 1 !lines!) do set "LN%%L=!LN0!"

set /a "pixel_h=6, pixel_w=4" & rem Fontsize 4X6
rem zscr: screen Z coor, zeye: eye point Z coor
set /a "XC = Cols/2, YC = lines/2, zscr = 128, zeye = 400, zs2e=zscr-zeye"

set /a "R1 = 68, r2 = 60, TH1 = 0, th2 = 0, cntRings=120, cntRings_1=cntRings-1, cntDotPerRing=20, cntDotPerRing_1=cntDotPerRing-1"
set /a "sumDots=cntDotPerRing*cntRings"
set /a "dth2base=(P2+P2/cntRings)/cntDotPerRing, offsClose=p2-(dth2base*cntDotPerRing-p2)*cntRings"
set "offsClose=!offsClose!/!sumDots!"
set /a "dTH1base=p2/cntRings, offsCloseBigCircle=p2-dTH1base*cntRings"
set "offsCloseBigCircle=!offsCloseBigCircle!/!cntRings!"
set /a "Z_cut_ZM=999*ZM" & rem The cutting plane parallel to plane xoy, Cut the front. When this value is large enough, there is no cutting effect

for /l %%i in (0 1 !cntRings_1!) do (

for /l %%j in (0 1 !cntDotPerRing_1!) do (

set /a "TH1=%%i*dTH1base+ %%i * %offsCloseBigCircle%, TH1 %%= p2, TH1 += TH1>>31&p2, t=TH1, s1=(t-p#2^t-p3#2)>>31, s3=p3#2_-t>>31, t=(-t&s1)+(t&~s1)+(p&s1)+(pn2&s3), SIN_TH1=%SIN%, t=%COS%, COS_TH1=(-t&s1)+(t&~s1)"

set /a "t=%%i*cntDotPerRing+%%j,th2=t*dth2base+t*%offsClose%, th2 %%= p2, th2 += th2>>31&p2, t=th2, s1=(t-p#2^t-p3#2)>>31, s3=p3#2_-t>>31, t=(-t&s1)+(t&~s1)+(p&s1)+(pn2&s3), SIN_th2=%SIN%, t=%COS%, COS_th2=(-t&s1)+(t&~s1)"

title 3D Torus Vortex  %%i/!cntRings_1! %%j/!cntDotPerRing_1!  TH1: !TH1! th2: !th2!

set /a "z_ZM=(R1*ZM + r2*COS_th2)/ZM * SIN_TH1, z_t2eye_ZM=z_ZM -zeye*ZM, x=XC + (R1*ZM + r2*COS_th2)/ZM * COS_TH1 *zs2e* pixel_h /(z_t2eye_ZM * pixel_w), y=YC + r2 * SIN_th2 *zs2e/z_t2eye_ZM, inScr=(x-0^x-wid)&(y-0^y-hei)"

set /a "inner=(th2-p#2^th2-p3#2)" & rem distance to the y-axis < big circle radius

if !z_ZM! LSS !Z_cut_ZM! (

set /a "ind=x+1, lenL=ind-1"
for /f "tokens=1-3" %%a in ("!lenL! !ind! !y!") do (
if !TH1! LSS !p! (
if !inner! LSS 0 (  set "LN%%c=!LN%%c:~0,%%a!#!LN%%c:~%%b!"
) else (            set "LN%%c=!LN%%c:~0,%%a!o!LN%%c:~%%b!"
)
) else (
if !inner! LSS 0 (  rem set "LN%%c=!LN%%c:~0,%%a!*!LN%%c:~%%b!" & Blank the behind half of the inner hole
) else (            set "LN%%c=!LN%%c:~0,%%a!.!LN%%c:~%%b!"
)
)
)
)

<nul set /p "=!aLineBS!" & (2>nul echo;%TAB%!BSs!) & <nul set /p "=%BS%"
for /L %%d in (1 1 !lines!) do <nul set /p "=%BS%!LN%%d!"
)
)
>nul pause
exit

neorobin
Posts: 48
Joined: 01 May 2012 12:18

### Re: Fastest sin(x) in dos batch

einstein1969 wrote:@neorobin
can you explain this part?

Code: Select all

s1=(t-p#2^t-p3#2)>>31

why that XOR?

Hi, einstein1969

I used this test to determine whether the value of t is in this range [Pi / 2, 3 * Pi / 2)

This is a general method for test a value t in [a, b) (a <= b)

set da=t-a, db=t-b

When t is less than a, the MSB (Most significant bit) of da is 1, otherwise (t >= a) it is 0

The MSB of ((t-a)^(t-b)) is 1,
Only in these conditions:

the MSB of da is 1, the MSB of db is 0 (Because the condition a <= b is defined, so THIS SITUATION CAN NOT HAPPEN)
OR
the MSB of da is 0, the MSB of db is 1

Both of these 2 conditions above satisfy this: the MSB of da is DIFFERENT (so use XOR) from the MSB of db

All other possible scenarios are:

the MSB of da is 1, the MSB of db is 1 ..... t < a and t < b
OR
the MSB of da is 0, the MSB of db is 0 ..... t >= a and t >= b

ps:

To ensure that an angle t is non-negative:

Code: Select all

t %%= p2, t += t>>31&p2  .....  p2 is Pi * 2

A sample code for find the numbers in range [3, 7)

Code: Select all

@echo off & setlocal enableDelayedExpansion

REM find the numbers: 3 <= t and t < 7

set /a "a = 3, b = 7" & rem a <= b

for /L %%t in (-4 1 9) do (

set /a "t=%%t, r=t-a^t-b, da=t-a, db=t-b"

if !da! lss 0 (echo;%%t ^< %a%) else (echo;%%t ^>= %a%)

if !db! lss 0 (echo;%%t ^< %b%) else (echo;%%t ^>= %b%)

if !r! lss 0 (echo;%a% ^<= %%t and %%t ^< %b%) else (echo;No intersection)

echo;
)
pause
exit /b

result

Code: Select all

-4 < 3
-4 < 7
No intersection

-3 < 3
-3 < 7
No intersection

-2 < 3
-2 < 7
No intersection

-1 < 3
-1 < 7
No intersection

0 < 3
0 < 7
No intersection

1 < 3
1 < 7
No intersection

2 < 3
2 < 7
No intersection

3 >= 3
3 < 7
3 <= 3 and 3 < 7

4 >= 3
4 < 7
3 <= 4 and 4 < 7

5 >= 3
5 < 7
3 <= 5 and 5 < 7

6 >= 3
6 < 7
3 <= 6 and 6 < 7

7 >= 3
7 >= 7
No intersection

8 >= 3
8 >= 7
No intersection

9 >= 3
9 >= 7
No intersection

einstein1969
Expert
Posts: 779
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

### Re: Fastest sin(x) in dos batch

very clever!

Thanks neorobin

foxidrive
Expert
Posts: 6033
Joined: 10 Feb 2012 02:20

### Re: Fastest sin(x) in dos batch

einstein1969 wrote:
neorobin wrote:Hi einstein1969

I made another implementation
...
spiral

That's so simple in motion but it really appeals to me. Very nice!

Aacini
Expert
Posts: 1695
Joined: 06 Dec 2011 22:15
Location: México City, México

### Re: Fastest sin(x) in dos batch

I completed the "Spiral in color" modification:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

if "%~1" neq "" goto %1

rem Original code written by neorobin
rem http://www.dostips.com/forum/viewtopic.php?f=3&t=7153&p=49643#p49643

rem This "Lines in color" version created by Antonio Perez Ayala, aka Aacini
rem Use PowerShell to move cursor and show text in color as described at:
rem http://www.dostips.com/forum/viewtopic.php?f=3&t=6936&p=46206#p46206

rem Screen size
set /a "wid=75, hei=75"
mode %wid%,%hei%
cls

echo/
echo   Û   Û   ÛÛÛÛÛ   ÛÛÛ   ÛÛÛÛÛ
echo   Û   Û   Û   Û    Û      Û
echo   Û Û Û   ÛÛÛÛÛ    Û      Û
echo   ÛÛ ÛÛ   Û   Û    Û      Û
echo   Û   Û   Û   Û   ÛÛÛ     Û    Û   Û   Û

"%~F0" Main  |  "%~F0" Output
goto :EOF

:Main

(
for /f "delims==" %%a in ('set') do set "%%a="
set /A "wid=%wid%, hei=%hei%"
)

REM APA Define the number of branches (colors) in the spiral as function of the angle in degrees:
REM APA Center:   60       72       90        120       (180)       240        270        288        300        330
REM APA 0-29=1, 30-65=6, 66-80=5, 81-104=4, 105-149=3, 150-210=2, 211-255=3, 256-279=4, 280-294=5, 295-330=6, 331-360=1
set n=0
for %%a in (30:6 66:5 81:4 105:3 150:2 211:3 256:4 280:5 295:6 331:1) do for /F "tokens=1,2 delims=:" %%x in ("%%a") do (
set "deg!n!=%%x"
set "cols!n!=%%y"
set /A n+=1
)
set /A "c=0, cols=1"

REM APA mod                                    Original: DEG=174, Modified: DEG=17453 (DEG * 100)
set /a "p=31416, p2=62832, pn2=-62832, p#2=15708, p3#2=47124, p3#2_=p3#2-1, DEG=3141593/180"
set "SIN=(t-(t2=t*t/1875)*t/320000+(t3=t2*t/15625)*t/16000*t/2560000-(t4=t3*t/15625*t/15360)*t/16000*t/44800000)"
set "COS=(10000-t*t/20000+t3*t/819200-t4*t/10240000+t4*t/16000*t/15625*t/229376000)"

set /a "wid_div_2 = wid / 2 - 3"

REM APA randomize:
for /L %%i in (1,1,%time:~-1%) do set /A !random!

set /a "XC = wid/2*10000, YC = hei/2*10000, DEG_unit = -1, th0=%random% %% 360 * DEG"

REM APA  The screen is managed via these 3 variables:
REM APA  scr2 - New points that needs to be displayed on the screen
REM APA  scr0 - Old points that needs to be cleared from the screen
REM APA  scr1 - Auxiliary buffer: it always contain the points that currently appears on the screen
set "scr1= "

for /L %%# in () do (

set "scr0=!scr1!"
set "scr2="

set /a "th0 += DEG, th = th0, DEG_unit= (DEG_unit+1) %% 360,  chg=^!(DEG_unit-deg!c!), col=-1"
if !chg! equ 1 set /A "cols=cols!c!, c=(c+1) %% n"

for /L %%r in (0 1 %wid_div_2%) do (
set /a "th+=DEG * DEG_unit, t= th/100 %% p2, s1=(t-p#2^t-p3#2)>>31, s3=p3#2_-t>>31, t=(-t&s1)+(t&~s1)+(p&s1)+(pn2&s3), SINt=%SIN%, t=%COS%, COSt=(-t&s1)+(t&~s1)"
set /a "x=(XC + %%r * COSt)/10000, y=(YC + %%r * SINt)/10000, inScr=(x-0^x-wid)&(y-0^y-hei),  col=(col+1) %% cols, co=15-col"

if !inScr! lss 0 (
for /F "tokens=1,2" %%x in ("!x! !y!") do (
if "!scr1: %%x:%%y:0=!" equ "!scr1!" (
set "scr1=!scr1! %%x:%%y:0"
set "scr2=!scr2! %%x:%%y:!co!"
)
set "scr0=!scr0: %%x:%%y:0=!"
)
)

)

if "!scr0!" neq " " (
for %%a in (!scr0!) do set "scr1=!scr1: %%a=!"
echo !scr0:~2!
)
echo !scr2:~1!

)
exit

:Output

rem The parameters received via lines read have this form:
rem Series of points, coordinates and color: X1:Y1:C1 X2:Y2:C2 ...

PowerShell  ^
cls;  ^
\$console = \$Host.UI.RawUI;  ^
\$console.WindowTitle = 'Spiral in color';  ^
\$console.CursorSize = 0;  ^
\$coords = \$console.CursorPosition;  ^
foreach ( \$line in \$input ) {  ^
\$point,\$line = \$line.Split(' ');  ^
while ( \$point ) {  ^
[int]\$X,[int]\$Y,[int]\$Color = \$point.Split(':');  ^
\$coords.X = \$X;  \$coords.Y = \$Y;  \$console.CursorPosition = \$coords;  ^
Write-Host -ForegroundColor \$Color -NoNewLine 'Û';  ^
\$point,\$line = \$line;  ^
}  ^
}
%End PowerShell%
exit /B

IMPORTANT: you must manually adjust the font type and size in the cmd.exe window and then adjust the values of the "Screen size variables": wid and hei accordingly; it is unlikely that the code as is may show a pleasant animation in your computer...

Antonio

einstein1969
Expert
Posts: 779
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

### Re: Fastest sin(x) in dos batch

thanks Antonio for colorized version!