Well, so much for CS.
I adapted both Atkin and the standard Sieve so that I could run them with
array sizes between 1k and 10GByte, with the following results:
Standard Sieve:
n runtime (ms) primes
1,000 0 302
10,000 0 2,261
100,000 0 17,983
1,000,000 3 148,932
10,000,000 29 1,270,606
100,000,000 962 11,078,936
1,000,000,000 12695 98,222,286
10,000,000,000 149099 882,206,715
Atkin Sieve
n runtime (ms) primes
1,000 0 168
10,000 0 1,229
100,000 0 9,592
1,000,000 4 78,498
10,000,000 60 664,579
100,000,000 1728 5,761,455
1,000,000,000 20900 50,847,534
10,000,000,000 301417 455,052,511
Atkin is about 4 times slower than the Standard Sieve (50% of the
results in twice the time). It might slowly increase for even larger
sieves, but with 20 GBytes there is not much evidence for that yet.
Maybe somebody with a TB of RAM has more luck.
The jump in runtime between 0.1GB and 1GB might have something to do
with the working-set default of a Windows program (I see no evidence
of disk-activity but ALLOCATE takes noticeably longer).
Here is the final SieveOfAtkin. I fixed a bug that had to do with Python's
logic operators apparently taking shortcuts without being told.
(*
* LANGUAGE : ANS Forth with extensions
* PROJECT : Forth Environments
* DESCRIPTION : Sieve of Atkin, fastest Sieve O(n)
* CATEGORY : Example
* AUTHOR : Marcel Hendrix
* LAST CHANGE : Saturday, May 21, 2022, 9:54 AM, mhx;
*)
NEEDS -miscutil
REVISION -sieveofatkin "--- Sieve of Atkin Version 0.04 ---"
PRIVATES
DOC
(*
n runtime (ms) primes
1,000 0 168
10,000 0 1,229
100,000 0 9,592
1,000,000 4 78,498
10,000,000 60 664,579
100,000,000 1728 5,761,455
1,000,000,000 20900 50,847,534
10,000,000,000 301417 455,052,511
*)
ENDDOC
DEPTH 0= [IF] CR .( Stack Empty) ABORT [THEN]
( #16384 ) =: limit PRIVATE
#1 =: #times PRIVATE
limit SQRT 2+ =: SQRT(limit+2) PRIVATE
limit SQRT 1+ =: SQRT(limit+1) PRIVATE
limit 1+ ALLOCATE ?ALLOCATE =: sieve PRIVATE
limit 1+ ALLOCATE ?ALLOCATE =: mods PRIVATE
: set# ( -- ) limit 2+ 0 DO I #12 MOD mods I + C! LOOP ; PRIVATE set#
: init ( -- ) sieve limit 1+ ERASE ( set# ) ; PRIVATE
: flip ( ix -- ) sieve + DUP C@ NOT SWAP C! ; PRIVATE
: fi1 ( I J -- u ) SQR 4 * SWAP SQR + ; PRIVATE
: fi2 ( I J -- u ) SQR 3 * SWAP SQR + ; PRIVATE
: fi3 ( I J -- u ) SQR 3 * SWAP SQR - ; PRIVATE
: #MOD ( s -- u ) mods + C@ ; PRIVATE
: test1 ( s -- ) DUP limit > IF DROP ELSE >S S #MOD DUP 1 = SWAP 5 = OR IF S flip ENDIF -S ENDIF ; PRIVATE
: test2 ( s -- ) DUP limit > IF DROP ELSE >S S #MOD 7 = IF S flip ENDIF -S ENDIF ; PRIVATE
: +test3 ( s ? -- ) OVER limit > OR IF DROP ELSE >S S #MOD #11 = IF S flip ENDIF -S ENDIF ; PRIVATE
: no-p^2 ( -- ) SQRT(limit+1) 5 DO sieve I + C@ IF limit 2+ I SQR DO sieve I + C0! J SQR +LOOP ENDIF LOOP ; PRIVATE
: cnt ( -- u ) 2 ( 2 and 3 ) limit 1+ 5 DO sieve I + C@ 1 AND + LOOP ; PRIVATE
: SieveOfAtkin ( -- u )
init
SQRT(limit+2)
1 DO SQRT(limit+2)
1 DO I J fi1 test1
I J fi2 test2
I J fi3 J I <= +test3