Fastest sin(x) in dos batch

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

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

Re: Fastest sin(x) in dos batch

#31 Post by foxidrive » 14 Mar 2016 15:21

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: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Fastest sin(x) in dos batch

#32 Post by einstein1969 » 14 Oct 2016 08:25

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

Image


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
Image
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: 47
Joined: 01 May 2012 12:18

Re: Fastest sin(x) in dos batch

#33 Post by neorobin » 14 Oct 2016 11:39

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: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Fastest sin(x) in dos batch

#34 Post by einstein1969 » 19 Oct 2016 08:08

very clever!

Thanks neorobin

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

Re: Fastest sin(x) in dos batch

#35 Post by foxidrive » 20 Oct 2016 04:43

einstein1969 wrote:
neorobin wrote:Hi einstein1969

I made another implementation
...
spiral
Image


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

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

Re: Fastest sin(x) in dos batch

#36 Post by Aacini » 23 Oct 2016 23:45

I completed the "Spiral in color" modification:

ImageImage

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: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Fastest sin(x) in dos batch

#37 Post by einstein1969 » 24 Oct 2016 04:15

thanks Antonio for colorized version!

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

Re: Fastest sin(x) in dos batch

#38 Post by einstein1969 » 30 Mar 2023 04:22

Hi,

I recalculated the times for all the various versions of sin(x) made and then I put here the most' fast. I checked and made further optimizations to make it as fast as possible.

the fastest is the one developed by neorobin, I added the control for negative angles and the mode developed by Aacini and some small optimizations.

Code: Select all

    set "SIN(x)=(a=((x*31416/180)%%62832)+(((x*31416/180)%%62832)>>31&62832), b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),a-a*a/1875*a/320000+a*a/1875*a/15625*a/16000*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"
   
    set /A "sx=%SIN(x):x=45%"
einstein1969 aka Francesco Poscetti

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

Re: Fastest sin(x) in dos batch

#39 Post by einstein1969 » 30 Mar 2023 04:35

I add all versions and times measured on my pc.

Code: Select all

rem first version
    set /a "PI=(35500000/113+5)/10, PI_div_2=(35500000/113/2+5)/10, PIx2=2*PI, PI32=PI+PI_div_2"
    set "SIN=(a-a*a/1920*a/312500+a*a/1920*a/15625*a/15625*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"

    %= 112-113 micro =%
    set /a "a=(45*31416/180) %% %PIx2%, b=(a>>31|1)*a"
    if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, a=%SIN%")  else (
      if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, a=%SIN%") else set /a "a=%SIN%")

    set /A sx=a

rem second by Aacini

    set "_SIN=a-a*a/1920*a/312500+a*a/1920*a/15625*a/15625*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000"

    REM APA mod
    REM http://www.dostips.com/forum/viewtopic.php?f=3&t=6744
    REM                                  if !c! gtr 47124   (set /a "a=a-(a>>31|1)*62832") else if !c! gtr 15708  set /a "a=(a>>31|1)*31416-a"
    set "SIN(x)=(a=(x)%%62832, c=(a>>31|1)*a, t=((c-47125)>>31)+1, a-=t*((a>>31|1)*62832)  +  ^^^!t*( (((c-15709)>>31)+1)*(-(a>>31|1)*31416+2*a)  ), %_SIN%)"
    set "_SIN="

    %= 58-60 micro =%
    set /A "sx=%SIN(x):x=45*31416/180%"

rem AAcini optimized !t=(1-t) if t={0,1}

    set "_SIN=a-a*a/1920*a/312500+a*a/1920*a/15625*a/15625*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000"
    rem set "SIN(x)=(a=(x)%%62832, c=(a>>31|1)*a, t=((c-47125)>>31)+1, a-=t*((a>>31|1)*62832)  +  ^^^!t*( (((c-15709)>>31)+1)*(-(a>>31|1)*31416+2*a)  ), %_SIN%)"
    rem set "SIN(x)=(a=(x)%%62832, c=(a>>31|1)*a, a-=(((c-47125)>>31)+1)*((a>>31|1)*62832)  +  ( 1 - (((c-47125)>>31)+1) )*( (((c-15709)>>31)+1)*(-(a>>31|1)*31416+2*a)  ), %_SIN%)"
    rem set "SIN(x)=(a=(x)%%62832, c=(a>>31|1)*a, a-=(((c-47125)>>31)+1)*((a>>31|1)*62832)  +  ( 1 -  ((c-47125)>>31)-1  )*( (((c-15709)>>31)+1)*(-(a>>31|1)*31416+2*a)  ), %_SIN%)"

    set "SIN(x)=(a=(x)%%62832, c=(a>>31|1)*a, a-=(((c-47125)>>31)+1)*((a>>31|1)*62832)  +  (-((c-47125)>>31))*( (((c-15709)>>31)+1)*(-(a>>31|1)*31416+2*a)  ), %_SIN%)"
    set "_SIN="

    %= 56-57 micro =%
    set /A "sx=%SIN(x):x=45*31416/180%"

rem by neorobin

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

	rem angle t in [0,2pi)

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


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

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


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

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

    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 /a "p=31416, p2=62832, pn2=-62832, p#2=15708, p3#2=47124, p3#2_=p3#2-1"

    rem 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%"

    %= 58-59 micro =%
    set /a "t=(45*31416/180) %% %p2%,s1=(t-%p#2%^t-%p3#2%)>>31, s3=%p3#2_%-t>>31, t=(-t&s1)+(t&~s1)+(%p%&s1)+(%pn2%&s3), sx=%SIN%"

    rem little optimization
    set "SIN=(a-a*a/1875*a/320000+a*a/1875*a/15625*a/16000*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"
    set /a "p=31416, p2=62832, pn2=-62832, p#2=15708, p3#2=47124, p3#2_=p3#2-1"

    rem set /a "a%%=p2,s1=(a-p#2^a-p3#2)>>31, s3=p3#2_-a>>31, a=(-a&s1)+(a&~s1)+(p&s1)+(pn2&s3), r1=%SIN%"

    %= 55-56 micro =%
    set /a "a=(45*31416/180) %% %p2%,s1=(a-%p#2%^a-%p3#2%)>>31, s3=%p3#2_%-a>>31, a=(-a&s1)+(a&~s1)+(%p%&s1)+(%pn2%&s3), sx=%SIN%"

rem map negative angle and little opt + AAcini mode
rem t %%= p2, t += t>>31&p2

    set "SIN(x)=(a=(x*31416/180)%%62832,a+=a>>31&62832, b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),%SIN%)"

    %= 54-55 micro =%
    set /A "sx=%SIN(x):x=45%"

    set "SIN(x)=(a=((x*31416/180)%%62832)+(((x*31416/180)%%62832)>>31&62832), b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),%SIN%)"
   
    %= 52-54 micro =%
    set /A "sx=%SIN(x):x=45%"
and this is the code for calculate timing plus some commented passages of the following optimizations

Code: Select all

@echo off

setlocal DisableDelayedExpansion

Echo Close any application, browser, and suspend process that use CPU.
Echo You can use Resource Monitor under Task Manager , select a process and right click to suspend.
Echo Close Task Manager and Resource Monitor.
Pause 

set FPS=if   %%\ geq !\!  (set "FPS_t1=1!time:~-5,-3!!time:~-2!" ^& ((set /p "FPS_old_counter=" ^& set /p "FPS_t0=")^<%tmp%\FPS.$$$.dat.txt) ^& set /a "FPS_dt=FPS_t1-FPS_t0, FPS_check=FPS_dt-1>>31, FPS_rapp=FPS_dt/(FPS_dt+(FPS_check&1)), FPS=(%%\-FPS_old_counter)*10000*100/(FPS_dt+(FPS_check&6000)), \=%%\+8*FPS/100/100+(1-FPS_rapp)*100, FPS_micro=1000000000/(FPS+(FPS-1>>31&1))" ^& Echo FPS=!FPS:~0,-2!.!FPS:~-2! [!FPS_micro:~0,-1!.!FPS_micro:~-1! æs] [#%%\-!\!] ^&set FPS_t1=^&set FPS_old_counter=^&set FPS_t0=^&set FPS_dt=^&set FPS_check=^&set FPS_rapp=^&set FPS=^&set FPS_micro=^& ( (echo %%\)^>%tmp%\FPS.$$$.dat.txt ^& (echo 1!time:~-5,-3!!time:~-2!)^>^>%tmp%\FPS.$$$.dat.txt) )
set INIT_FPS=set \=0^&(echo 0^&echo 1%time:~-5,-3%%time:~-2%)^>%tmp%\FPS.$$$.dat.txt

setlocal EnableDelayedExpansion

%= Put here definition of macro or initialize value =%

    rem little optimization neorobin
    rem set "SIN=(a-a*a/1875*a/320000+a*a/1875*a/15625*a/16000*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"
    
	rem set /a "p=31416, p2=62832, pn2=-62832, p#2=15708, p3#2=47124, p3#2_=p3#2-1"
	rem set "sin(x)=( a=(x*31416/180) %% %p2%,s1=(a-%p#2%^a-%p3#2%)>>31, s3=%p3#2_%-a>>31, a=(-a&s1)+(a&~s1)+(%p%&s1)+(%pn2%&s3), sx=%SIN% ) "
	rem set "SIN(x)=(a=(x*31416/180)%% 62832,s1=(a-%p#2%^a-%p3#2%)>>31, s3=%p3#2_%-a>>31, a=(-a&s1)+(a&~s1)+(%p%&s1)+(%pn2%&s3), %SIN% )"

    rem set "SIN(x)=(a=(x*31416/180)%% 62832,s1=(a-15708^a-47124)>>31, s3=47123-a>>31, a=(-a&s1)+(a&~s1)+(31416&s1)+(-62832&s3), %SIN% )"
    rem set "SIN(x)=(a=(x*31416/180)%%62832,b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),%SIN%)"

rem map negative angle
rem t %%= p2, t += t>>31&p2

    rem set "SIN(x)=(a=(x*31416/180)%%62832,a+=a>>31&62832, b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),%SIN%)"
    rem set "SIN(x)=(a=((x*31416/180)%%62832)+(((x*31416/180)%%62832)>>31&62832), b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),%SIN%)"
    set "SIN(x)=(a=((x*31416/180)%%62832)+(((x*31416/180)%%62832)>>31&62832), b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),a-a*a/1875*a/320000+a*a/1875*a/15625*a/16000*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"

      rem this is slow
      rem set "SIN(x)=(a=(x*31416/180)%% 62832, a=(-a&((a-15708^a-47124)>>31))+(a&~((a-15708^a-47124)>>31))+(31416&((a-15708^a-47124)>>31))+(-62832&(47123-a>>31)), %SIN% )"
      rem set "SIN(x)=(a=(x*31416/180)%% 62832, a=(-a&(a-15708^a-47124)>>31)+(a&~((a-15708^a-47124)>>31))+(31416&((a-15708^a-47124)>>31))+(-62832&(47123-a>>31)), %SIN% )"
      rem set "SIN(x)=(a=(x*31416/180)%% 62832, a=(-a&(a-15708^a-47124)>>31)+(a&~(a-15708^a-47124)>>31)+(31416&((a-15708^a-47124)>>31))+(-62832&(47123-a>>31)), %SIN% )"
      rem set "SIN(x)=(a=(x*31416/180)%%62832,a=(-a&(a-15708^a-47124)>>31)+(a&~(a-15708^a-47124)>>31)+(31416&(a-15708^a-47124)>>31)+(-62832&(47123-a>>31)),%SIN%)"

rem functional test

    set /a "PI=(35500000/113+5)/10, PI_div_2=(35500000/113/2+5)/10, PIx2=2*PI, PI32=PI+PI_div_2"
    set "SINo=(a-a*a/1920*a/312500+a*a/1920*a/15625*a/15625*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"

For /L %%L in (-720,1,720) do (

    set /a "aa=%%L"

    rem new method
    set /A "sx=%SIN(x):x=aa%"

    rem old method
    set /a "a=(aa*31416/180) %% %PIx2%, b=(a>>31|1)*a"
    if !b! gtr %PI32% (
        set /a "a=a-(a>>31|1)*%PIx2%, a=%SINo%"
    )  else (
        if !b! gtr %PI_div_2% (
		set /a "a=(a>>31|1)*%PI%-a, a=%SINo%"
	) else (set /a "a=%SINo%"
	)
    )

    set /A sx1=a

    if !sx! neq !sx1! echo !aa! !sx!, !sx1! ERROR

)
pause

rem Performance test

::BURST MODE ON
(setlocal & for /F "Tokens=1 delims==" %%v in ('set') do set "%%v="

  rem preallocate env. sometimes it works sometimes not. Remove rem for try. 
  rem (for /L %%\ in (1,1,2000) do (set z=!z!0000&set z1=!z1!0000)) & set z=&set z1=  

(%INIT_FPS%)
For /L %%\ in (1,1,1600000) do (( For /L %%? in (0,1,99) do (

    %= Insert here the code to timing =%

    %= 52-54 micro =%
    set /A "sx=%SIN(x):x=45%"
    set /A "sx=%SIN(x):x=45%"
    set /A "sx=%SIN(x):x=45%"
    set /A "sx=%SIN(x):x=45%"
    set /A "sx=%SIN(x):x=45%"
    set /A "sx=%SIN(x):x=45%"
    set /A "sx=%SIN(x):x=45%"
    set /A "sx=%SIN(x):x=45%"
    set /A "sx=%SIN(x):x=45%"
    set /A "sx=%SIN(x):x=45%"

  ))
  %FPS%
  title !sx!
)

endlocal)
::BURST MODE OFF

goto :eof

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Fastest sin(x) in dos batch

#40 Post by IcarusLives » 30 Mar 2023 11:01

Works great here on Win10! Over 1000 iterations, I saved a combined 10seconds! Worth the switch :) Is it possible to achieve atan in this fashion??

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

Re: Fastest sin(x) in dos batch

#41 Post by einstein1969 » 30 Mar 2023 12:17

https://en.wikipedia.org/wiki/Inverse_t ... _functions

Code: Select all

set z=500 & set /A atan=z-z*z/1000*z/3000+z*z/1000*z/1000*z/1000*z/5000-z*z/1000*z/1000*z/1000*z/1000*z/1000*z/7000
with z in [-1000,1000]

this is arctan(0.5)=0.46

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Fastest sin(x) in dos batch

#42 Post by IcarusLives » 30 Mar 2023 12:54

That was fast! I've been trying to understand how to do that for so long I gave up :oops: I'm so grateful for this!

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

Re: Fastest sin(x) in dos batch

#43 Post by einstein1969 » 30 Mar 2023 13:28

it's a first implementation but it will take much longer to finish it.

The series in question converges very slowly and therefore the error is still high.

I'm working on it

PS If you have some code to develop that uses atan it would be nicer and more addictive. To be able to test the function together.

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

Re: Fastest sin(x) in dos batch

#44 Post by einstein1969 » 30 Mar 2023 17:33

I found this atan?

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Fastest sin(x) in dos batch

#45 Post by IcarusLives » 30 Mar 2023 18:44

Oh yes! Is it possible to macro this line sin(x)?

Post Reply