The remaining functions contain loops or are not called till the end of the program.
It uses the formula:
π = 48*arctan(1/18) + 32*arctan(1/57) - 20*arctan(1/239)
and calculates pi to 108 decimal places.
Time trials on my Win7 laptop (64 bit Intel dual core i3 @ 2.10 GHz):
Function Version Average(8): 5.81375 secs
Macros not loaded Avg time: 4.65125 secs
. Difference: 1.16250 secs
Macros loaded Average time: 4.63625 secs
. Difference: 0.015 secs
I didn't see much baggage to loading the macros at routine startup vs pre loading in this case.
Pi.bat will accept an optional Arg1 to load the result into, then all display is suppressed.
Macro version has a 'load' option to run once and put macros into environment for future runs.
Code: Select all
::pi_function_version.bat
@echo off
setlocal EnableDelayedExpansion
if not [%1]==[] (set GNL=^>nul) else (set GNL=)
echo.pi.bat - By Don Cross - http://cosinekitty.com%GNL%
set /a NumQuads = 30
set /a MaxQuadIndex = NumQuads - 1
echo.%GNL%
echo.%time% - started%GNL%
echo.%GNL%
call :PiEngine 48 18 32 57 -20 239 tempi
::call :PiEngine 16 5 -4 239 tempi
endlocal&if not [%1]==[] call set "%1=3%%%tempi%%%"
exit /b 0
:PiEngine
call :SetToInteger Pi 0
set Formula=
:PiTermLoop
if "%1" == "tempi" (
call :Print pi %1
echo.%GNL%
echo.!time! - finished !Formula!%GNL%
echo.%GNL%
goto :EOF
)
call :ArctanRecip PiTerm %2
set /a PiEngineFactor=%1
if !PiEngineFactor! lss 0 (
set /a PiEngineFactor *= -1
set Formula=!Formula!
call :MultiplyByInteger PiTerm !PiEngineFactor!
call :Subtract Pi PiTerm
set Operator=-
) else (
call :MultiplyByInteger PiTerm %1
call :Add Pi PiTerm
set Operator=+
)
if defined Formula (
set Formula=!Formula! !Operator! !PiEngineFactor!*arctan^(1/%2^)
) else (
set Formula=ã = %1*arctan^(1/%2^)
)
shift
shift
goto PiTermLoop
:SetToInteger
for /L %%i in (0, 1, !MaxQuadIndex!) do (
set /a %1_%%i = 0
)
set /a %1_!MaxQuadIndex! = %2
goto :EOF
:Print
set PrintBuffer=x
REM Omit a couple of least significant quads, because they will have roundoff errors.
if defined PiDebug (
set /a PrintMinQuadIndex=0
) else (
set /a PrintMinQuadIndex=2
)
set /a PrintMaxQuadIndex = MaxQuadIndex - 1
for /L %%i in (!PrintMinQuadIndex!, 1, !PrintMaxQuadIndex!) do (
set PrintDigit=!%1_%%i!
if !PrintDigit! lss 1000 (
if !PrintDigit! lss 100 (
if !PrintDigit! lss 10 (
set PrintDigit=000!PrintDigit!
) else (
set PrintDigit=00!PrintDigit!
)
) else (
set PrintDigit=0!PrintDigit!
)
)
set PrintBuffer=!PrintDigit!!PrintBuffer!
)
set PrintBuffer=!%1_%MaxQuadIndex%!.!PrintBuffer:x=!
echo.|(set /p=ã = )%GNL%&echo.!PrintBuffer! %GNL%
set "%2=!PrintBuffer!"
goto :EOF
:DivideByInteger
if defined PiDebug echo.DivideByInteger %1 %2
set /a DBI_Carry = 0
for /L %%i in (!MaxQuadIndex!, -1, 0) do (
set /a DBI_Digit = DBI_Carry*10000 + %1_%%i
set /a DBI_Carry = DBI_Digit %% %2
set /a %1_%%i = DBI_Digit / %2
)
goto :EOF
:MultiplyByInteger
if defined PiDebug echo.MultiplyByInteger %1 %2
set /a MBI_Carry = 0
for /L %%i in (0, 1, !MaxQuadIndex!) do (
set /a MBI_Digit = %1_%%i * %2 + MBI_Carry
set /a %1_%%i = MBI_Digit %% 10000
set /a MBI_Carry = MBI_Digit / 10000
)
goto :EOF
:ArctanRecip
if defined PiDebug echo.ArctanRecip %1 %2
call :SetToInteger %1 1
call :DivideByInteger %1 %2
call :CopyValue AR_Recip %1
set /a AR_Toggle = -1
set /a AR_K = 3
:ArctanLoop
if defined PiDebug (
echo.
echo.ArctanRecip AR_K=!AR_K! ---------------------------------------------------------
)
call :DivideByInteger AR_Recip %2
call :DivideByInteger AR_Recip %2
call :CopyValue AR_Term AR_Recip
call :DivideByInteger AR_Term !AR_K!
call :CopyValue AR_PrevSum %1
if !AR_Toggle! lss 0 (
call :Subtract %1 AR_Term
) else (
call :Add %1 AR_Term
)
call :Compare AR_EqualFlag %1 AR_PrevSum
if !AR_EqualFlag! == true goto :EOF
set /a AR_K += 2
set /a AR_Toggle *= -1
goto ArctanLoop
:CopyValue
if defined PiDebug echo.CopyValue %1 %2
for /L %%i in (0, 1, !MaxQuadIndex!) do (
set /a %1_%%i = %2_%%i
)
goto :EOF
:Add
if defined PiDebug echo.Add %1 %2
if defined PiDebug call :Print %1
if defined PiDebug call :Print %2
set /a Add_Carry = 0
for /L %%i in (0, 1, !MaxQuadIndex!) do (
set /a Add_Digit = Add_Carry + %1_%%i + %2_%%i
set /a %1_%%i = Add_Digit %% 10000
set /a Add_Carry = Add_Digit / 10000
)
goto :EOF
:Subtract
if defined PiDebug echo.Subtract %1 %2
if defined PiDebug call :Print %1
if defined PiDebug call :Print %2
set /a Subtract_Borrow = 0
for /L %%i in (0, 1, !MaxQuadIndex!) do (
set /a Subtract_Digit = %1_%%i - %2_%%i - Subtract_Borrow
if !Subtract_Digit! lss 0 (
set /a Subtract_Digit += 10000
set /a Subtract_Borrow = 1
) else (
set /a Subtract_Borrow = 0
)
set /a %1_%%i = Subtract_Digit
)
goto :EOF
:Compare
if defined PiDebug echo.Compare %1 %2 %3
if defined PiDebug call :Print %2
if defined PiDebug call :Print %3
set /a Compare_Index = 0
set %1=true
:CompareLoop
if not !%2_%Compare_Index%! == !%3_%Compare_Index%! (
if defined PiDebug echo.!%2_%Compare_Index%! neq !%3_%Compare_Index%!
set %1=false
goto :EOF
)
set /a Compare_Index += 1
if !Compare_Index! gtr !MaxQuadIndex! (
if defined PiDebug echo.Compare equal
goto :EOF
)
goto CompareLoop
REM $Log: pi.bat,v $
REM Revision 1.2 2007/09/06 21:49:15 Don.Cross
REM Added time stamps and display of formula.
REM
REM Revision 1.1 2007/09/06 21:12:36 Don.Cross
REM Batch file for calculating pi
REM
Here is the macro version:
Code: Select all
::pi_macro_version.bat
@echo off
if /i "%~1" equ "load" goto :Pi_Macros
setlocal DisableDelayedExpansion
if not defined Pi_Macros_Loaded call :Pi_Macros
setlocal EnableDelayedExpansion
if not [%1]==[] (set GNL=^>nul) else (set GNL=)
echo.pi.bat - By Don Cross - http://cosinekitty.com%GNL%
echo.%GNL%
echo.%time% - started%GNL%
echo.%GNL%
set pidebug=
set /a NumQuads = 30
set /a MaxQuadIndex = NumQuads - 1
call :PiEngine 48 18 32 57 -20 239 tempi
::call :PiEngine 16 5 -4 239 tempi
endlocal&endlocal&if not [%1]==[] call set "%1=3%%%tempi%%%"
exit /b 0
:PiEngine
%SetToInteger% Pi 0 MaxQuadIndex
set Formula=
:PiTermLoop
if "%1" == "tempi" (
call :Print pi %1
echo.%GNL%
echo.!time! - finished !Formula!%GNL%
echo.%GNL%
goto :EOF
)
call :ArctanRecip PiTerm %2
set /a PiEngineFactor=%1
if !PiEngineFactor! lss 0 (
set /a PiEngineFactor *= -1
set Formula=!Formula!
%MultiplyByInteger% PiTerm !PiEngineFactor! MaxQuadIndex
%Subtract% Pi PiTerm MaxQuadIndex
set Operator=-
) else (
%MultiplyByInteger% PiTerm %1 MaxQuadIndex
%Add% Pi PiTerm MaxQuadIndex
set Operator=+
)
if defined Formula (
set Formula=!Formula! !Operator! !PiEngineFactor!*arctan^(1/%2^)
) else (
set Formula=ã = %1*arctan^(1/%2^)
)
shift
shift
goto PiTermLoop
:ArctanRecip
if defined PiDebug echo.ArctanRecip %1 %2
%SetToInteger% %1 1 MaxQuadIndex
%DivideByInteger% %1 %2 MaxQuadIndex
%CopyValue% AR_Recip %1 MaxQuadIndex
set /a AR_Toggle = -1
set /a AR_K = 3
:ArctanLoop
if defined PiDebug (
echo.
echo.ArctanRecip AR_K=!AR_K! ---------------------------------------------------------
)
%DivideByInteger% AR_Recip %2 MaxQuadIndex
%DivideByInteger% AR_Recip %2 MaxQuadIndex
%CopyValue% AR_Term AR_Recip MaxQuadIndex
%DivideByInteger% AR_Term !AR_K! MaxQuadIndex
%CopyValue% AR_PrevSum %1 MaxQuadIndex
if !AR_Toggle! lss 0 (
%Subtract% %1 AR_Term MaxQuadIndex
) else (
%Add% %1 AR_Term MaxQuadIndex
)
call :Compare AR_EqualFlag %1 AR_PrevSum
if !AR_EqualFlag! == true goto :EOF
set /a AR_K += 2
set /a AR_Toggle *= -1
goto ArctanLoop
:Compare
if defined PiDebug echo.Compare %1 %2 %3
if defined PiDebug call :Print %2
if defined PiDebug call :Print %3
set /a Compare_Index = 0
set %1=true
:CompareLoop
if not !%2_%Compare_Index%! == !%3_%Compare_Index%! (
if defined PiDebug echo.!%2_%Compare_Index%! neq !%3_%Compare_Index%!
set %1=false
goto :EOF
)
set /a Compare_Index += 1
if !Compare_Index! gtr !MaxQuadIndex! (
if defined PiDebug echo.Compare equal
goto :EOF
)
goto CompareLoop
:Print
set PrintBuffer=x
REM Omit a couple of least significant quads, because they will have roundoff errors.
if defined PiDebug (
set /a PrintMinQuadIndex=0
) else (
set /a PrintMinQuadIndex=2
)
set /a PrintMaxQuadIndex = MaxQuadIndex - 1
for /L %%i in (!PrintMinQuadIndex!, 1, !PrintMaxQuadIndex!) do (
set PrintDigit=!%1_%%i!
if !PrintDigit! lss 1000 (
if !PrintDigit! lss 100 (
if !PrintDigit! lss 10 (
set PrintDigit=000!PrintDigit!
) else (
set PrintDigit=00!PrintDigit!
)
) else (
set PrintDigit=0!PrintDigit!
)
)
set PrintBuffer=!PrintDigit!!PrintBuffer!
)
set PrintBuffer=!%1_%MaxQuadIndex%!.!PrintBuffer:x=!
echo.|(set /p=ã = )%GNL%&echo.!PrintBuffer! %GNL%
set "%2=!PrintBuffer!"
goto :EOF
REM $Log: pi.bat,v $
REM Revision 1.2 2007/09/06 21:49:15 Don.Cross
REM Added time stamps and display of formula.
REM
REM Revision 1.1 2007/09/06 21:12:36 Don.Cross
REM Batch file for calculating pi
REM
:Pi_Macros
:: Pi Macros
::
:: Define a Carriage Return string, only useable as !#CR!
for /f %%a in ('copy /Z "%~dpf0" nul') do set "#CR=%%a"
:: Define a Line Feed (newline) string (normally only used as !#LF!)
set #LF=^
:: Above 2 blank lines are required - do not remove
:: Define a newline with line continuation
set ^"\n=^^^%#LF%%#LF%^%#LF%%#LF%^^"
:MultiplyByInteger
set MultiplyByInteger=for %%n in (1 2) do if %%n==2 (%\n%
for /F "tokens=1,2,3 delims=, " %%1 in ("!args!") do (%\n%
set /a "MBI_Carry = 0"%\n%
for /L %%i in (0, 1, !%%~3!) do (%\n%
set /a "MBI_Digit = %%~1_%%i * %%~2 + MBI_Carry"%\n%
set /a "%%~1_%%i = MBI_Digit %% 10000"%\n%
set /a "MBI_Carry = MBI_Digit / 10000"%\n%
)%\n%
)%\n%
) else set args=,
:Subtract %1 %2 MaxQuadIndex
set Subtract=for %%n in (1 2) do if %%n==2 (%\n%
for /F "tokens=1,2,3 delims=, " %%1 in ("!args!") do (%\n%
set /a "Subtract_Borrow = 0"%\n%
for /L %%i in (0, 1, !%%~3!) do (%\n%
set /a "Subtract_Digit = %%~1_%%i - %%~2_%%i - Subtract_Borrow"%\n%
if !Subtract_Digit! lss 0 (%\n%
set /a "Subtract_Digit += 10000"%\n%
set /a "Subtract_Borrow = 1"%\n%
) else set /a "Subtract_Borrow = 0"%\n%
set /a "%%~1_%%i = Subtract_Digit"%\n%
)%\n%
)%\n%
) else set args=,
:Add %1 %2 MaxQuadIndex
set Add=for %%n in (1 2) do if %%n==2 (%\n%
for /F "tokens=1,2,3 delims=, " %%1 in ("!args!") do (%\n%
set /a "Add_Carry = 0"%\n%
for /L %%i in (0, 1, !%%~3!) do (%\n%
set /a "Add_Digit = Add_Carry + %%~1_%%i + %%~2_%%i"%\n%
set /a "%%~1_%%i = Add_Digit %% 10000"%\n%
set /a "Add_Carry = Add_Digit / 10000"%\n%
)%\n%
)%\n%
) else set args=,
:DivideByInteger %1 %2 MaxQuadIndex
set DivideByInteger=for %%n in (1 2) do if %%n==2 (%\n%
for /F "tokens=1,2,3 delims=, " %%1 in ("!args!") do (%\n%
set /a "DBI_Carry = 0"%\n%
for /L %%i in (!%%~3!, -1, 0) do (%\n%
set /a "DBI_Digit = DBI_Carry*10000 + %%~1_%%i"%\n%
set /a "DBI_Carry = DBI_Digit %% %%~2"%\n%
set /a "%%~1_%%i = DBI_Digit / %%~2"%\n%
)%\n%
)%\n%
) else set args=,
:SetToInteger %1 %2 MaxQuadIndex
set SetToInteger=for %%n in (1 2) do if %%n==2 (%\n%
for /F "tokens=1,2,3 delims=, " %%1 in ("!args!") do (%\n%
for /L %%i in (0, 1, !%%~3!) do (%\n%
set /a "%%~1_%%i = 0"%\n%
)%\n%
set /a "%%~1_!%%~3! = %%~2"%\n%
)%\n%
) else set args=,
:CopyValue %1 %2 MaxQuadIndex
set CopyValue=for %%n in (1 2) do if %%n==2 (%\n%
for /F "tokens=1,2,3 delims=, " %%1 in ("!args!") do (%\n%
for /L %%i in (0, 1, !%%~3!) do (%\n%
set /a "%%~1_%%i = %%~2_%%i"%\n%
)%\n%
)%\n%
) else set args=,
set/a Pi_Macros_Loaded=1
exit/b 0
I actually thought the macro version would be faster than it turned out and I am a bit surprised that preloading the macros didn't shave off much time on my pc.
Carl