バッチファイルでProject Euler(27)

Problem 10


Miller-Rabin法を実装してみましたが、さらに時間がかかりました。しかも自乗でオーバーフローする問題に対処できていません。

@echo off

call :start_time
set /a N = 2000
set /a N_1 = %N% - 1
set /a s1 = 5
set /a s2 = 0
for /L %%k in (5, 2, %N_1%) do call :sum_primes %%k
set /a s1 += 100000000
echo %s2%%s1:~1%
call :check_time
exit /b 0

:sum_primes
    call :Miller_Rabin %1
    if %ERRORLEVEL% == 0 exit /b 0
    set /a s1 += %1
    set /a s2 += %s1% / 100000000
    set /a s1 %%= 100000000
    exit /b 0

:Miller_Rabin
    setlocal
    set /a r = %1 %% 3
    if %r% == 0 exit /b 0
    
    set /a n = %1
    set /a n_1 = %n% - 1
    call :Miller_Rabin_core1 %n_1% 2
    if %ERRORLEVEL% == 0 exit /b 0
    call :Miller_Rabin_core1 %n_1% 3
    exit /b %ERRORLEVEL%

:Miller_Rabin_core1
    setlocal
    set /a next_d = %1 / 2
    call :Miller_Rabin_core2 %next_d% %2
    if %ERRORLEVEL% == %n% exit /b 1
    exit /b 0

:Miller_Rabin_core2
    setlocal
    set /a next_d = %1 / 2
    set /a r = %1 %% 2
    set /a mode = %r% + 2
    call :Miller_Rabin_core%mode% %next_d% %2
    set /a m = %ERRORLEVEL%
    if %r% == 1 (
        set /a s = %m% * %m% * %2 %% %n%
    ) else (
        set /a s = %m% * %m% %% %n%
    )
    
    if %r% == 1 (
        if %s% == %n_1% exit /b %n%
        if %s% == 1 exit /b %n%
        exit /b %s%
    ) else (
        if %m% == %n% exit /b %n%
        if %s% == %n_1% exit /b %n%
        exit /b %s%
    )

:Miller_Rabin_core3
    setlocal
    if %1 == 0 exit /b 1
    set /a next_d = %1 / 2
    call :Miller_Rabin_core3 %next_d% %2
    set /a m = %ERRORLEVEL%
    set /a r = %1 %% 2
    if %r% == 1 (
        set /a s = %m% * %m% * %2 %% %n%
    ) else (
        set /a s = %m% * %m% %% %n%
    )
    exit /b %s%

:start_time
    call :get_time
    set /a __t0 = %ERRORLEVEL%
    exit /b 0

:check_time
    setlocal
    call :get_time
    set /a t = %ERRORLEVEL% - %__t0%
    if %t% LSS 10 (
        echo 0.0%t%s
    ) else (
        if %t% LSS 100 (
            echo 0.%t%s
        ) else (
            echo %t:~0,-2%.%t:~-2%s
        )
    )
    exit /b 0

:get_time
    setlocal
    set t=%TIME%
    set /a h = %t:~0,2%
    set /a m = 1%t:~3,2% %% 100
    set /a s = 1%t:~6,2% %% 100
    set /a ss = 1%t:~-2% %% 100
    set /a ret = ((%h% * 60 + %m%) * 60 + %s%) * 100 + %ss%
    exit /b %ret%