Sieve of Eratosthenes: Difference between revisions
Content deleted Content added
No edit summary |
|||
(130 intermediate revisions by 58 users not shown) | |||
Line 33:
{{trans|Python}}
<
V is_prime = [0B]*2 [+] [1B]*(limit - 1)
L(n) 0 .< Int(limit ^ 0.5 + 1.5)
Line 41:
R enumerate(is_prime).filter((i, prime) -> prime).map((i, prime) -> i)
print(primes_upto(100))</
{{out}}
Line 50:
=={{header|360 Assembly}}==
For maximum compatibility, this program uses only the basic instruction set.
<
ERATOST CSECT
USING ERATOST,R12
Line 120:
CRIBLE DC 100000X'01'
YREGS
END ERATOST</
{{out}}
<pre style="height:20ex">
Line 168:
=={{header|6502 Assembly}}==
If this subroutine is called with the value of <i>n</i> in the accumulator, it will store an array of the primes less than <i>n</i> beginning at address 1000 hex and return the number of primes it has found in the accumulator.
<
LDA #$00
LDX #$00
Line 206:
JMP COPY
COPIED: TYA ; how many found
RTS</
=={{header|68000 Assembly}}==
Line 215:
Some of the macro code is derived from the examples included with EASy68K.
See 68000 "100 Doors" listing for additional information.
<
* Title : BitSieve
* Written by : G. A. Tippery
Line 469:
Summary2: DC.B ' prime numbers found.',CR,LF,$00
END START ; last line of source</
=={{header|8086 Assembly}}==
<
cpu 8086
bits 16
Line 531:
numbuf: db 13,10,'$'
section .bss
sieve: resb MAXPRM</
{{out}}
Line 545:
4993
4999
</pre>
=={{header|8th}}==
<syntaxhighlight lang="8th">
with: n
\ create a new buffer which will function as a bit vector
: bit-vec SED: n -- b
dup 3 shr swap 7 band if 1+ then b:new b:clear ;
\ given a buffer, sieving prime, and limit, cross off multiples
\ of the sieving prime.
: +composites SED: b n n -- b
>r dup sqr rot \ want: -- n index b
repeat
over 1- true b:bit!
>r over + r>
over r@ > until!
rdrop nip nip ;
\ SoE algorithm proper
: make-sieve SED: n -- b
dup>r bit-vec 2
repeat
tuck 1- b:bit@ not
if
over r@ +composites
then swap 1+
dup sqr r@ < while!
rdrop drop ;
\ traverse the final buffer, creating an array of primes
: sieve>a SED: b n -- a
>r a:new swap
( 1- b:bit@ not if >r I a:push r> then ) 2 r> loop drop ;
;with
: sieve SED: n -- a
dup make-sieve swap sieve>a ;
</syntaxhighlight>
{{Out}}
<pre>
ok> 100 sieve .
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
ok> 1_000_000 sieve a:len . \ count primes up to 1,000,000
78498
ok> -1 a:@ . \ largest prime < 1,000,000
999983
</pre>
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits}}
<syntaxhighlight lang="aarch64 assembly">
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program cribleEras64.s */
Line 639 ⟶ 688:
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
<pre>
Prime : 2
Line 669 ⟶ 718:
=={{header|ABAP}}==
<syntaxhighlight lang="lisp">
PARAMETERS: p_limit TYPE i OBLIGATORY DEFAULT 100.
Line 711 ⟶ 760:
ENDIF.
ENDLOOP.
</syntaxhighlight>
=={{header|ABC}}==
<syntaxhighlight lang="ABC">HOW TO SIEVE UP TO n:
SHARE sieve
PUT {} IN sieve
FOR cand IN {2..n}: PUT 1 IN sieve[cand]
FOR cand IN {2..floor root n}:
IF sieve[cand] = 1:
PUT cand*cand IN comp
WHILE comp <= n:
PUT 0 IN sieve[comp]
PUT comp+cand IN comp
HOW TO REPORT prime n:
SHARE sieve
IF n<2: FAIL
REPORT sieve[n] = 1
SIEVE UP TO 100
FOR n IN {1..100}:
IF prime n: WRITE n</syntaxhighlight>
{{out}}
<pre>2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97</pre>
=={{header|ACL2}}==
<
(declare (xargs :measure (nfix (- n i))))
(if (zp (- n i))
Line 743 ⟶ 815:
(defun sieve (limit)
(sieve-r 2 limit))</
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE MAX="1000"
PROC Main()
BYTE ARRAY t(MAX+1)
INT i,j,k,first
FOR i=0 TO MAX
DO
t(i)=1
OD
t(0)=0
t(1)=0
i=2 first=1
WHILE i<=MAX
DO
IF t(i)=1 THEN
IF first=0 THEN
Print(", ")
FI
PrintI(i)
FOR j=2*i TO MAX STEP i
DO
t(j)=0
OD
first=0
FI
i==+1
OD
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Sieve_of_Eratosthenes.png Screenshot from Atari 8-bit computer]
<pre>
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,
227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347,
349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743,
751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883,
887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997
</pre>
=={{header|ActionScript}}==
Works with ActionScript 3.0 (this is utilizing the actions panel, not a separated class file)
<
{
var primes:Array = new Array();
Line 770 ⟶ 887:
}
var e:Array = eratosthenes(1000);
trace(e);</
Output:
{{out}}
Line 779 ⟶ 896:
=={{header|Ada}}==
<
procedure Eratos is
Last: Positive := Positive'Value(Ada.Command_Line.Argument(1));
Prime: array(1 .. Last) of Boolean := (1 => False, others => True);
Line 788 ⟶ 905:
Cnt: Positive;
begin
while Base * Base <= Last loop
if Prime(Base) then
Cnt := Base + Base;
while Cnt <= Last loop
Prime(Cnt) := False;
Cnt := Cnt + Base;
Line 806 ⟶ 921:
end if;
end loop;
end Eratos;</
{{out}}
Line 814 ⟶ 929:
=={{header|Agda}}==
<
-- imports
open import Data.Nat as ℕ using (ℕ; suc; zero; _+_; _∸_)
Line 861 ⟶ 976:
remove _ ys zero = nothing ∷ ys i
remove y ys (suc j) = y ∷ ys j
</syntaxhighlight>
=={{header|Agena}}==
Tested with Agena 2.9.5 Win32
<
# generate and return a sequence containing the primes up to sieveSize
Line 896 ⟶ 1,011:
# test the sieve proc
for i in sieve( 100 ) do write( " ", i ) od; print();</
{{out}}
<pre>
Line 933 ⟶ 1,048:
'''Works with:''' ALGOL 60 for OS/360
<
'INTEGER' 'ARRAY' CANDIDATES(/0..1000/);
'INTEGER' I,J,K;
Line 972 ⟶ 1,087:
'END'
'END'
'END'</
=={{header|ALGOL 68}}==
<
PROC eratosthenes = (INT n)[]BOOL:
(
Line 992 ⟶ 1,107:
);
print((eratosthenes(80),new line))</
{{out}}
<pre>
Line 1,000 ⟶ 1,115:
=={{header|ALGOL W}}==
=== Standard, non-optimised sieve ===
<
% implements the sieve of Eratosthenes %
Line 1,042 ⟶ 1,157:
end
end.</
{{out}}
<pre>
Line 1,051 ⟶ 1,166:
Alternative version that only stores odd numbers greater than 1 in the sieve.
<
% implements the sieve of Eratosthenes %
% only odd numbers appear in the sieve, which starts at 3 %
Line 1,083 ⟶ 1,198:
for i := 1 until arrayMax do if s( i ) then writeon( ( i * 2 ) + 1 );
end
end.</
{{out}}
Same as the standard version.
=={{header|ALGOL-M}}==
<
BEGIN
Line 1,157 ⟶ 1,272:
END
</syntaxhighlight>
{{out}}
<pre>
Line 1,182 ⟶ 1,297:
=== Non-Optimized Version ===
<
b←⍵⍴1
b[⍳2⌊⍵]←0
Line 1,191 ⟶ 1,306:
}
primes2←{⍵/⍳⍴⍵}∘sieve2</
The required list of prime divisors obtains by recursion (<tt>{⍵/⍳⍴⍵}∇⌈⍵*0.5</tt>).
=== Optimized Version ===|
<
b←⍵⍴{∧⌿↑(×/⍵)⍴¨~⍵↑¨1}2 3 5
b[⍳6⌊⍵]←(6⌊⍵)⍴0 0 1 1 0 1
Line 1,206 ⟶ 1,321:
}
primes←{⍵/⍳⍴⍵}∘sieve</
The optimizations are as follows:
Line 1,215 ⟶ 1,330:
=== Examples ===
<
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Line 1,227 ⟶ 1,342:
+/∘sieve¨ 10*⍳10
0 4 25 168 1229 9592 78498 664579 5761455 50847534</
The last expression computes the number of primes < 1e0 1e1 ... 1e9.
Line 1,234 ⟶ 1,349:
=={{header|AppleScript}}==
<
script o
property numberList : {missing value}
Line 1,253 ⟶ 1,368:
end sieveOfEratosthenes
sieveOfEratosthenes(1000)</
{{out}}
<
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi}}
<syntaxhighlight lang="arm assembly">
/* ARM assembly Raspberry PI */
Line 1,354 ⟶ 1,469:
/***************************************************/
.include "../affichage.inc"
</syntaxhighlight>
<pre>
Prime : 2
Line 1,383 ⟶ 1,498:
Prime : 101
</pre>
=={{header|Arturo}}==
<syntaxhighlight lang="rebol">sieve: function [upto][
composites: array.of: inc upto false
loop 2..to :integer sqrt upto 'x [
if not? composites\[x][
loop range.step: x x^2 upto 'c [
composites\[c]: true
]
]
]
result: new []
loop.with:'i composites 'c [
unless c -> 'result ++ i
]
return result -- [0,1]
]
print sieve 100</syntaxhighlight>
{{out}}
<pre>2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97</pre>
=={{header|AutoHotkey}}==
{{AutoHotkey case}}Source: [http://www.autohotkey.com/forum/topic44657.html AutoHotkey forum] by Laszlo
<
Sieve(n) { ; Sieve of Eratosthenes => string of 0|1 chars, 1 at position k: k is prime
Line 1,400 ⟶ 1,539:
}
Return S
}</
===Alternative Version===
<
arr := []
loop % n-1
Line 1,417 ⟶ 1,556:
}
return Arr
}</
Examples:<
Arr := Sieve_of_Eratosthenes(n)
loop, % n-1
output .= (Arr[A_Index] ? A_Index : ".") . (!Mod(A_Index, 10) ? "`n" : "`t")
MsgBox % output
return</
{{out}}
<pre>. 2 3 . 5 . 7 . . .
Line 1,437 ⟶ 1,576:
=={{header|AutoIt}}==
<
$M = InputBox("Integer", "Enter biggest Integer")
Global $a[$M], $r[$M], $c = 1
Line 1,451 ⟶ 1,590:
$r[0] = $c - 1
ReDim $r[$c]
_ArrayDisplay($r)</
=={{header|AWK}}==
Line 1,476 ⟶ 1,615:
input from commandline as well as stdin,
and input is checked for valid numbers:
<
# usage: gawk -v n=101 -f sieve.awk
Line 1,495 ⟶ 1,634:
END { print "Bye!" }
</syntaxhighlight>
Here is an alternate version that uses an associative array to record composites with a prime dividing it. It can be considered a slow version, as it does not cross out composites until needed. This version assumes enough memory to hold all primes up to ULIMIT. It prints out noncomposites greater than 1.
<
BEGIN { ULIMIT=100
Line 1,510 ⟶ 1,649:
else print ( S[(n+n)] = n )
}
</syntaxhighlight>
==Bash==
Line 1,518 ⟶ 1,657:
{{works with|FreeBASIC}}
{{works with|RapidQ}}
<
INPUT "Enter number to search to: "; limit
Line 1,534 ⟶ 1,673:
FOR n = 2 TO limit
IF flags(n) = 0 THEN PRINT n; ", ";
NEXT n</
==={{header|Applesoft BASIC}}===
<
20 DIM FLAGS(LIMIT)
30 FOR N = 2 TO SQR (LIMIT)
Line 1,548 ⟶ 1,687:
100 FOR N = 2 TO LIMIT
110 IF FLAGS(N) = 0 THEN PRINT N;", ";
120 NEXT N</
==={{header|Atari BASIC}}===
{{trans|Commodore BASIC}}
Auto-initialization of arrays is not reliable, so we have to do our own. Also, PRINTing with commas doesn't quite format as nicely as one might hope, so we do a little extra work to keep the columns lined up.
<
110 PRINT "LIMIT";:INPUT LI
120 DIM N(LI):FOR I=0 TO LI:N(I)=1:NEXT I
Line 1,570 ⟶ 1,709:
250 IF C=3 THEN PRINT:C=0
260 NEXT I
270 IF C THEN PRINT</
{{Out}}
<pre> Ready
Line 1,587 ⟶ 1,726:
==={{header|Commodore BASIC}}===
Since C= BASIC initializes arrays to all zeroes automatically, we avoid needing our own initialization loop by simply letting 0 mean prime and using 1 for composite.
<
110 INPUT "LIMIT";LI
120 DIM N(LI)
Line 1,602 ⟶ 1,741:
230 NEXT I
240 PRINT
</syntaxhighlight>
{{Out}}
<pre>
Line 1,620 ⟶ 1,759:
==={{header|IS-BASIC}}===
<
110 LET LIMIT=100
120 NUMERIC T(1 TO LIMIT)
Line 1,635 ⟶ 1,774:
230 FOR I=2 TO LIMIT ! Display the primes
240 IF T(I)=0 THEN PRINT I;
250 NEXT</
==={{header|Locomotive Basic}}===
<
20 INPUT "Limit";limit
30 DIM f(limit)
Line 1,649 ⟶ 1,788:
100 FOR n=2 TO limit
110 IF f(n)=0 THEN PRINT n;",";
120 NEXT</
==={{header|MSX Basic}}===
<
6 REM Translated from Rosetta's ZX Spectrum implementation
10 INPUT "Enter number to search to: ";l
Line 1,665 ⟶ 1,804:
100 FOR n=2 TO l
110 IF p(n)=0 THEN PRINT n;", ";
120 NEXT n</
==={{header|Sinclair ZX81 BASIC}}===
Line 1,671 ⟶ 1,810:
A note on <code>FAST</code> and <code>SLOW</code>: under normal circumstances the CPU spends about 3/4 of its time driving the display and only 1/4 doing everything else. Entering <code>FAST</code> mode blanks the screen (which we do not want to update anyway), resulting in substantially improved performance; we then return to <code>SLOW</code> mode when we have something to print out.
<
20 FAST
30 DIM N(L)
Line 1,683 ⟶ 1,822:
110 FOR I=2 TO L
120 IF NOT N(I) THEN PRINT I;" ";
130 NEXT I</
==={{header|ZX Spectrum Basic}}===
<
20 DIM p(l)
30 FOR n=2 TO SQR l
Line 1,697 ⟶ 1,836:
100 FOR n=2 TO l
110 IF p(n)=0 THEN PRINT n;", ";
120 NEXT n</
==={{header|QBasic}}===
{{works with|QBasic|1.1}}
{{works with|QuickBasic|4.5}}
<syntaxhighlight lang="qbasic">limit = 120
DIM flags(limit)
FOR n = 2 TO limit
flags(n) = 1
NEXT n
PRINT "Prime numbers less than or equal to "; limit; " are: "
FOR n = 2 TO SQR(limit)
IF flags(n) = 1 THEN
FOR i = n * n TO limit STEP n
flags(i) = 0
NEXT i
END IF
NEXT n
FOR n = 1 TO limit
IF flags(n) THEN PRINT USING "####"; n;
NEXT n</syntaxhighlight>
{{out}}
<pre>Prime numbers less than or equal to 120 are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113</pre>
==={{header|BASIC256}}===
<syntaxhighlight lang="basic256">arraybase 1
limit = 120
dim flags(limit)
for n = 2 to limit
flags[n] = True
next n
print "Prime numbers less than or equal to "; limit; " are: "
for n = 2 to sqr(limit)
if flags[n] then
for i = n * n to limit step n
flags[i] = False
next i
end if
next n
for n = 1 to limit
if flags[n] then print rjust(n,4);
next n</syntaxhighlight>
{{out}}
<pre>Prime numbers less than or equal to 120 are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113</pre>
==={{header|True BASIC}}===
{{trans|QBasic}}
<syntaxhighlight lang="qbasic">LET limit = 120
DIM flags(0)
MAT redim flags(limit)
FOR n = 2 to limit
LET flags(n) = 1
NEXT n
PRINT "Prime numbers less than or equal to "; limit; " are: "
FOR n = 2 to sqr(limit)
IF flags(n) = 1 then
FOR i = n*n to limit step n
LET flags(i) = 0
NEXT i
END IF
NEXT n
FOR n = 1 to limit
IF flags(n)<>0 then PRINT using "####": n;
NEXT n
END</syntaxhighlight>
{{out}}
<pre>Same as QBasic entry.</pre>
==={{header|QL SuperBASIC}}===
Line 1,703 ⟶ 1,916:
{{trans|ZX Spectrum Basic}}
Sets h$ to 1 for higher multiples of 2 via <code>FILL$</code>, later on sets <code>STEP</code> to 2n; replaces Floating Pt array p(z) with string variable h$(z) to sieve out all primes < z=441 (<code>l</code>=21) in under 1K, so that h$ is fillable to its maximum (32766), even on a 48K ZX Spectrum if translated back.
<
10 INPUT "Enter Stopping Pt for squared factors: ";z
15 LET l=SQR(z)
Line 1,713 ⟶ 1,926:
90 REM Display the primes
100 FOR n=2 TO z: IF h$(n)=0: PRINT n;", ";
</syntaxhighlight>
====2i wheel emulation of Sinclair ZX81 BASIC====
Backward-compatible also on Spectrums, as well as 1K ZX81s for all primes < Z=441. N.B. the <code>STEP</code> of 2 in line 40 mitigates line 50's inefficiency when going to 90. <
10 INPUT Z
15 LET L=SQR(Z)
Line 1,732 ⟶ 1,945:
120 IF H$(I)="0" THEN PRINT I!
130 NEXT I
</syntaxhighlight>
====2i wheel emulation of Sinclair ZX80 BASIC====
. . . with 2:1 compression (of 16-bit integer variables on ZX80s) such that it obviates having to account for any multiple of 2; one has to input odd upper limits on factors to be squared, <code>L</code> (=21 at most on 1K ZX80s for all primes till 439).
Backward-compatible on ZX80s after substituting ** for ^ in line 120.<syntaxhighlight lang="qbasic">
10 INPUT L
15 LET Z=(L+1)*(L- 1)/2
Line 1,748 ⟶ 1,962:
120 IF NOT H(I) THEN PRINT 0^I+1+I*2!
130 NEXT I
</syntaxhighlight>
====Sieve of Sundaram====
Objections that the latter emulation has strayed far from the given task are obviously justified. Yet not as obvious is that we are now
just a slight transformation away from the Sieve of Sundaram, as transformed as follows: <code>O</code> is the highest value for an Index of succesive diagonal elements in Sundaram's matrix, for which H(J) also includes the off-diagonal elements in-between, such that
duplicate entries are omitted. Thus, a slightly transformed Sieve of Sundaram is what Eratosthenes' Sieve becomes upon applying all
optimisations incorporated into the prior entries for QL SuperBASIC,
Backward-compatible on 1K ZX80s for all primes < 441 (O=10) after substituting ** for ^ in line 120.<
10 INPUT O
15 LET Z=2*O
30 DIM H(Z)
40 FOR I=1 TO O
45 LET A=2*I
50 REM IF H(A) THEN GOTO 90
60 FOR J=A TO Z STEP 1+I*2
65 REM IF H(J) THEN GOTO 80
70 LET H(J)=1
80 NEXT J
Line 1,767 ⟶ 1,984:
120 IF NOT H(I) THEN PRINT 0^I+1+I*2!
130 NEXT I
</syntaxhighlight>
====Eulerian optimisation====
While slower than the optimised Sieve of Eratosthenes before it, the Sieve of Sundaram above has a compatible compression scheme that's more convenient than the conventional one used beforehand. It is therefore applied below along with Euler's alternative optimisation in a reversed implementation that lacks backward-compatibility to ZX80 BASIC. This program is designed around features & limitations of the QL, yet can be rewritten more efficiently for 1K ZX80s, as they allow integer variables to be parameters of <code>FOR</code> statements (& as their 1K of static RAM is equivalent to L1 cache, even in <code>FAST</code> mode). That's left as an exercise for ZX80 enthusiasts, who for o%=14 should be able to generate all primes < 841, i.e. 3 orders of (base 2) magnitude above the limit for the program listed under Sinclair ZX81 BASIC. In QL SuperBASIC, o% may at most be 127--generating all primes < 65,025 (almost 2x the upper limit for indices & integer variables used to calculate them ~2x faster than for floating point as used in line 30
<
10 INPUT "Enter highest value of diagonal index q%: ";o%
15 LET z%=o%*(2+o%*2) : h$=FILL$("
30 FOR p=m TO q STEP -1: h$(
42 GOTO 87
61 IF h$(p%)="1"
62 IF p%<q%
63 LET p%=p%-1 : GOTO 61
87 LET q%=q%+1 : IF h$(q%)="1"
90 LET p%=z% DIV (2*q%+1) : IF q%<=o%
100 LET z%=z%-1 : IF z%=0: PRINT N%(z%) : STOP
110 GOTO 100
127 DEF FN N%(i)=0^i+1+i*2
</syntaxhighlight>
=={{header|Batch File}}==
<
@echo off
setlocal ENABLEDELAYEDEXPANSION
Line 1,805 ⟶ 2,024:
if !crible.%%i! EQU 1 echo %%i
)
pause</
{{Out}}
<pre style="height:20ex">limit: 100
Line 1,835 ⟶ 2,054:
=={{header|BBC BASIC}}==
<
DIM sieve% limit%
Line 1,849 ⟶ 2,068:
FOR I% = 1 TO limit%
IF sieve%?I% = 0 PRINT I%;
NEXT</
=={{header|BCPL}}==
<
manifest $( LIMIT = 1000 $)
Line 1,884 ⟶ 2,103:
$)
wrch('*N')
$)</
{{out}}
<pre> 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
Line 1,897 ⟶ 2,116:
=== Odds-only bit packed array version (64 bit) ===
This sieve also uses an iterator structure to enumerate the primes in the sieve. It's inspired by the golang bit packed sieve that returns a closure as an iterator. However, BCPL does not support closures, so the code uses an iterator object.
<syntaxhighlight lang="bcpl">
GET "libhdr"
Line 2,020 ⟶ 2,239:
RESULTIS 0
}
</syntaxhighlight>
{{Out}}
<pre>
Line 2,052 ⟶ 2,271:
@ ^ p3\" ":<
2 234567890123456789012345678901234567890123456789012345678901234567890123456789
=={{header|Binary Lambda Calculus}}==
The BLC sieve of Eratosthenes as documented at https://github.com/tromp/AIT/blob/master/characteristic_sequences/primes.lam is the 167 bit program
<pre>00010001100110010100011010000000010110000010010001010111110111101001000110100001110011010000000000101101110011100111111101111000000001111100110111000000101100000110110</pre>
The infinitely long output is
<pre>001101010001010001010001000001010000010001010001000001000001010000010001010000010001000001000000010001010001010001000000000000010001000001010000000001010000010000010001000001000001010000000001010001010000000000010000000000010001010001000001010000000001000001000001000001010000010001010000000001000000000000010001010001000000000000010000010000000001010001000001000...</pre>
=={{header|BQN}}==
A more efficient sieve (primes below one billion in under a minute) is provided as <code>PrimesTo</code> in bqn-libs [https://github.com/mlochbaum/bqn-libs/blob/master/primes.bqn primes.bqn].
<syntaxhighlight lang="bqn">Primes ← {
𝕩≤2 ? ↕0 ; # No primes below 2
p ← 𝕊⌈√n←𝕩 # Initial primes by recursion
b ← 2≤↕n # Initial sieve: no 0 or 1
E ← {↕∘⌈⌾((𝕩×𝕩+⊢)⁼)n} # Multiples of 𝕩 under n, starting at 𝕩×𝕩
/ b E⊸{0¨⌾(𝕨⊸⊏)𝕩}´ p # Cross them out
}</syntaxhighlight>
{{out}}
<syntaxhighlight lang="bqn"> Primes 100
⟨ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 ⟩
≠∘Primes¨ 10⋆↕7 # Number of primes below 1e0, 1e1, ... 1e6
⟨ 0 4 25 168 1229 9592 78498 ⟩</syntaxhighlight>
=={{header|Bracmat}}==
This solution does not use an array. Instead, numbers themselves are used as variables. The numbers that are not prime are set (to the silly value "nonprime"). Finally all numbers up to the limit are tested for being initialised. The uninitialised (unset) ones must be the primes.
<
= n j i
. !arg:?n
Line 2,076 ⟶ 2,323:
)
& eratosthenes$100
)</
{{out}}
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
=={{header|C}}==
Plain sieve, without any optimizations:<
#include <math.h>
Line 2,108 ⟶ 2,355:
}
return sieve;
}</
'''Another example:'''
Line 2,115 ⟶ 2,362:
Then, in a loop, fill zeroes into those places where i * j is less than or equal to n (number of primes requested), which means they have multiples!
To understand this better, look at the output of the following example.
To print this back, we look for ones in the array and only print those spots. <
#include <malloc.h>
void sieve(int *, int);
Line 2,153 ⟶ 2,400:
}
printf("\n\n");
}</
j:2
Before a[2*2]: 1
Line 2,177 ⟶ 2,424:
i:9
i:10
Primes numbers from 1 to 10 are : 2, 3, 5, 7, </
=={{header|C sharp|C#}}==
{{works with|C sharp|C#|2.0+}}
<
using System.Collections;
using System.Collections.Generic;
Line 2,224 ⟶ 2,471:
}
}
}</
===
{{trans|F#}}
To show that C# code can be written in somewhat functional paradigms, the following in an implementation of the Richard Bird sieve from the Epilogue of [Melissa E. O'Neill's definitive article](http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf) in Haskell:
<
using System.Collections;
using System.Collections.Generic;
Line 2,273 ⟶ 2,518:
}
IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); }
}</
{{trans|F#}}
The above code can easily be converted to "'''odds-only'''" and a infinite tree-like folding scheme with the following minor changes:
<
using System.Collections;
using System.Collections.Generic;
Line 2,328 ⟶ 2,573:
}
IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); }
}</
The above code runs over ten times faster than the original Richard Bird algorithm.
{{trans|F#}}
First, an implementation of a Min Heap Priority Queue is provided as extracted from the entry at [http://rosettacode.org/wiki/Priority_queue#C.23 RosettaCode], with only the necessary methods duplicated here:
<
using KeyT = System.UInt32;
using System;
Line 2,394 ⟶ 2,639:
public static MinHeapPQ<V> replaceMin(KeyT k, V v, MinHeapPQ<V> pq) {
pq.rplcmin(k, v); return pq; }
}</
===Restricted Base Primes Queue===
The following code implements an improved version of the '''odds-only''' O'Neil algorithm, which provides the improvements of only adding base prime composite number streams to the queue when the sieved number reaches the square of the base prime (saving a huge amount of memory and considerable execution time, including not needing as wide a range of a type for the internal prime numbers) as well as minimizing stream processing using fusion:
<syntaxhighlight lang="csharp">using System;
using System.Collections;
using System.Collections.Generic;
Line 2,432 ⟶ 2,681:
public IEnumerator<PrimeT> GetEnumerator() { return nmrtr(); }
IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); }
}</
The above code is at least about 2.5 times faster than the Tree Folding version.
===Dictionary (Hash table) Sieve===
The above code adds quite a bit of overhead in having to provide a version of a Priority Queue for little advantage over a Dictionary (hash table based) version as per the code below:
<syntaxhighlight lang="csharp">using System;
using System.Collections;
using System.Collections.Generic;
Line 2,472 ⟶ 2,723:
public IEnumerator<PrimeT> GetEnumerator() { return nmrtr(); }
IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); }
}</
The above code runs in about three quarters of the time as the above Priority Queue based version for a range of a million primes which will fall even further behind for increasing ranges due to the Dictionary providing O(1) access times as compared to the O(log n) access times for the Priority Queue; the only slight advantage of the PQ based version is at very small ranges where the constant factor overhead of computing the table hashes becomes greater than the "log n" factor for small "n".
===Best performance: CPU-Cache-Optimized Segmented Sieve===
All of the above unbounded versions are really just an intellectual exercise as with very little extra lines of code above the fastest Dictionary based version, one can have an bit-packed page-segmented array based version as follows:
<
using System.Collections;
using System.Collections.Generic;
Line 2,535 ⟶ 2,786:
public IEnumerator<PrimeT> GetEnumerator() { return nmrtr(); }
IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); }
}</
The above code is about 25 times faster than the Dictionary version at computing the first about 50 million primes (up to a range of one billion), with the actual enumeration of the result sequence now taking longer than the time it takes to cull the composite number representation bits from the arrays, meaning that it is over 50 times faster at actually sieving the primes. The code owes its speed as compared to a naive "one huge memory array" algorithm to using an array size that is the size of the CPU L1 or L2 caches and using bit-packing to fit more number representations into this limited capacity; in this way RAM memory access times are reduced by a factor of from about four to about 10 (depending on CPU and RAM speed) as compared to those naive implementations, and the minor computational cost of the bit manipulations is compensated by a large factor in total execution time.
The time to enumerate the result primes sequence can be reduced somewhat (about a second) by removing the automatic iterator "yield return" statements and converting them into a "
In order to make further gains in speed, custom methods must be used to avoid using iterator sequences. If this is done, then further gains can be made by extreme wheel factorization (up to about another about four times gain in speed) and multi-processing (with another gain in speed proportional to the actual independent CPU cores used).
Line 2,546 ⟶ 2,797:
All of the above unbounded code can be tested by the following "main" method (replace the name "PrimesXXX" with the name of the class to be tested):
<
Console.WriteLine(new PrimesXXX().ElementAt(1000000 - 1)); // zero based indexing...
}</
To produce the following output for all tested versions (although some are considerably faster than others):
Line 2,559 ⟶ 2,810:
This implementation follows the standard library pattern of [http://en.cppreference.com/w/cpp/algorithm/iota std::iota]. The start and end iterators are provided for the container. The destination container is used for marking primes and then filled with the primes which are less than the container size. This method requires no memory allocation inside the function.
<
#include <iterator>
#include <algorithm>
#include <vector>
// Fills the range [start, end) with 1 if the integer corresponding to the index is composite and 0 otherwise.
// requires: I is RandomAccessIterator
template<typename I>
void mark_composites(I start, I end)
{
std::fill(start, end, 0);
for (
{
if (*
{
auto prime = std::
// mark all multiples of this prime number as composite.
auto multiple_it = it;
while (std::distance(multiple_it, end) > prime)
{
std::advance(multiple_it, prime);
*multiple_it = 1;
}
}
}
}
// Fills "out" with the prime numbers in the range 2...N where N = distance(start, end).
// requires: I is a RandomAccessIterator
// O is an OutputIterator
template <typename I, typename O>
O sieve_primes(I start, I end, O out)
{
mark_composites(start, end);
for (auto it = start + 1; it != end; ++it)
{
if (*it == 0)
{
*
++
}
}
return
}
int main(
{
std::vector<
sieve_primes(is_composite.begin(), is_composite.end(), std::ostream_iterator<int>(std::cout, " "));
// sieve_primes(is_composite.begin(), is_composite.end(), std::back_inserter(primes));
}
</syntaxhighlight>
=== Boost ===
<
template<class UnaryFunction>
void primesupto(int limit, UnaryFunction yield)
Line 2,629 ⟶ 2,888:
if (is_prime[n])
yield(n);
}</
Full program:
{{works with|Boost}}<
$ g++ -I/path/to/boost sieve.cpp -o sieve && sieve 10000000
*/
Line 2,673 ⟶ 2,932:
cout << "limit sum pi(n)\n"
<< limit << " " << sum << " " << count << endl;
}</
=={{header|Chapel}}==
{{incorrect|Chapel|Doesn't compile since at least Chapel version 1.20 to 1.24.1.}}
This solution uses nested iterators to create new wheels at run time:
<
iter sieve(prime):int {
Line 2,700 ⟶ 2,959:
yield candidate;
}
}</
<
for p in sieve(2) {
if p > N {
Line 2,708 ⟶ 2,967:
}
write(" ", p);
}</
===Alternate Conventional Bit-Packed Implementation===
Line 2,716 ⟶ 2,975:
compile with the `--fast` option
<
use BitOps;
Line 2,755 ⟶ 3,014:
for p in 2 .. n do if cmpsts[p >> 3] & (1: uint(8) << (p & 7)) == 0 then yield p;
}</
{{out}}
Line 2,767 ⟶ 3,026:
===Alternate Odds-Only Bit-Packed Implementation===
<
use BitOps;
Line 2,810 ⟶ 3,069:
if cmpsts[i >> 3] & (1: uint(8) << (i & 7)) == 0 then yield i + i + 3;
}</
{{out}}
Line 2,825 ⟶ 3,084:
{{trans|Python}} [https://rosettacode.org/wiki/Sieve_of_Eratosthenes#Infinite_generator_with_a_faster_algorithm code link]
{{works with|Chapel|1.
<
config const limit = 100000000;
Line 2,878 ⟶ 3,137:
write("Found ", count, " primes up to ", limit);
writeln(" in ", timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
}</
{{out}}
<pre>The first 25 primes are: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Found 5761455 primes up to 100000000 in
Time as run using Chapel version 24.1 on an Intel Skylake i5-6500 at 3.6 GHz (turbo, single threaded).
As you can see, this is much slower than the array based versions
As an alternate to the use of a built-in library, the following code implements a specialized BasePrimesTable that works similarly to the way the Python associative arrays work as to hashing algorithm used (no hashing, as the hash values for integers are just themselves) and something similar to the Python method of handling hash table collisions is used:
{{works with|Chapel|1.
Compile with the `--fast` compiler command line option
<
config const limit = 100000000;
Line 2,989 ⟶ 3,248:
write("Found ", count, " primes up to ", limit);
writeln(" in ", timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
}</
{{out}}
<pre>The first 25 primes are: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Found 5761455 primes up to 100000000 in
This last code is quite usable up to a hundred million (as here) or even a billion in a little over ten times the time, but is still slower than the very simple odds-only monolithic array version and is also more complex, although it uses less memory (only for the hash table for the base primes of about eight Kilobytes for sieving to a billion compared to over 60 Megabytes for the monolithic odds-only simple version).
Chapel version 1.25.1 provides yet another option as to the form of the code although the algorithm is the same in that one can now override the hashing function for Chapel records so that they can be used as the Key Type for Hash Map's as follows:
{{works with|Chapel|1.25.1}}
Compile with the `--fast` compiler command line option
<syntaxhighlight lang="chapel">use Time;
use Map;
config const limit = 100000000;
type Prime = uint(32);
class Primes { // needed so we can use next to get successive values
record PrimeR { var prime: Prime; proc hash() { return prime; } }
var n: PrimeR = new PrimeR(0); var obp: Prime; var q: Prime;
var bps: owned Primes?;
var dict = new map(PrimeR, Prime);
proc next(): Prime { // odd primes!
if this.n.prime < 5 { this.n.prime = 5; return 3; }
if this.bps == nil {
this.bps = new Primes(); // secondary odd base primes feed
this.obp = this.bps!.next(); this.q = this.obp * this.obp;
}
while true {
if this.n.prime >= this.q { // advance secondary stream of base primes...
const adv = this.obp * 2; const key = new PrimeR(this.q + adv);
this.obp = this.bps!.next(); this.q = this.obp * this.obp;
this.dict.add(key, adv);
}
else if this.dict.contains(this.n) { // found a composite; advance...
const adv = this.dict.getValue(this.n); this.dict.remove(this.n);
var nkey = new PrimeR(this.n.prime + adv);
while this.dict.contains(nkey) do nkey.prime += adv;
this.dict.add(nkey, adv);
}
else { const p = this.n.prime;
this.n.prime += 2; return p; }
this.n.prime += 2;
}
return 0; // to keep compiler happy in returning a value!
}
iter these(): Prime { yield 2; while true do yield this.next(); }
}
proc main() {
var count = 0;
write("The first 25 primes are: ");
for p in new Primes() { if count >= 25 then break; write(p, " "); count += 1; }
writeln();
var timer: Timer;
timer.start();
count = 0;
for p in new Primes() { if p > limit then break; count += 1; }
timer.stop();
write("Found ", count, " primes up to ", limit);
writeln(" in ", timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
}</syntaxhighlight>
This works in about exactly the same time as the last previous code, but doesn't require special custom adaptations of the associative array so that the standard library Map can be used.
===Functional Tree Folding Odds-Only Version===
Line 3,004 ⟶ 3,327:
{{trans|Nim}} [https://rosettacode.org/wiki/Sieve_of_Eratosthenes#Nim_Unbounded_Versions code link]
{{works with|Chapel|1.22|- compile with the --fast compiler command line flag for full optimization}}
<
type Prime = uint(32);
Line 3,119 ⟶ 3,442:
for p in primes() { if p > limit then break; cnt += 1; }
timer.stop(); write("\nFound ", cnt, " primes up to ", limit);
writeln(" in ", timer.elapsed(TimeUnits.milliseconds), " milliseconds.");</
{{out}}
<pre>The first 25 primes are: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Line 3,132 ⟶ 3,455:
To take advantage of the features that make Chapel shine, we need to use it to do some parallel computations, and to efficiently do that for the Sieve of Eratosthenes, we need to divide the work into page segments where we can assign each largish segment to a separate thread/task; this also improves the speed due to better cache associativity with most memory accesses to values that are already in the cache(s). Once we have divided the work, Chapel offers lots of means to implement the parallelism but to be a true Sieve of Eratosthenes, we need to have the ability to output the results in order; with many of the convenience mechanisms not doing that, the best/simplest option is likely task parallelism with the output results assigned to an rotary indexed array containing the `sync` results. It turns out that, although the Chapel compiler can sometimes optimize the code so the overhead of creating tasks is not onerous, for this case where the actual tasks are somewhat complex, the compiler can't recognize that an automatically generated thread pool(s) are required so we need to generate the thread pool(s) manually. The code that implements the multi-threading of page segments using thread pools is as follows:
{{works with|Chapel|1.24.1|- compile with the --fast compiler command line flag for full optimization}}
<
type Prime = uint(64);
Line 3,444 ⟶ 3,767:
write("Found ", count, " primes up to ", LIMIT);
writeln(" in ", timer.elapsed(TimeUnits.milliseconds), " milliseconds.");</
{{out}}
<pre>The first 25 primes are: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Line 3,490 ⟶ 3,813:
=={{header|Clojure}}==
<
(remove (set (mapcat #(range (* % %) n %)
(range 2 (Math/sqrt n))))
(range 2 n)))</
The above is **not strictly a Sieve of Eratosthenes** as the composite culling ranges (in the ''mapcat'') include all of the multiples of all of the numbers and not just the multiples of primes. When tested with <code clojure>(println (time (count (primes< 1000000))))</code>, it takes about 5.5 seconds just to find the number of primes up to a million, partly because of the extra work due to the use of the non-primes, and partly because of the constant enumeration using sequences with multiple levels of function calls. Although very short, this code is likely only useful up to about this range of a million.
Line 3,499 ⟶ 3,822:
It may be written using the ''into #{}'' function to run slightly faster due to the ''set'' function being concerned with only distinct elements whereas the ''into #{}'' only does the conjunction, and even at that doesn't do that much as it does the conjunction to an empty sequence, the code as follows:
<
(remove (into #{}
(mapcat #(range (* % %) n %)
(range 2 (Math/sqrt n))))
(range 2 n)))</
The above code is slightly faster for the reasons given, but is still not strictly a Sieve of Eratosthenes due to sieving by all numbers and not just by the base primes.
The following code also uses the ''into #{}'' transducer but has been slightly wheel-factorized to sieve odds-only:
<
(if (< n 2) ()
(cons 2 (remove (into #{}
(mapcat #(range (* % %) n %)
(range 3 (Math/sqrt n) 2)))
(range 3 n 2)))))</
The above code is a little over twice as fast as the non-odds-only due to the reduced number of operations. It still isn't strictly a Sieve of Eratosthenes as it sieves by all odd base numbers and not only by the base primes.
The following code calculates primes up to and including ''n'' using a mutable boolean array but otherwise entirely functional code; it is tens (to a hundred) times faster than the purely functional codes due to the use of mutability in the boolean array:
<
"Computes lazy sequence of prime numbers up to a given number using sieve of Eratosthenes"
[n]
Line 3,530 ⟶ 3,853:
(do (dorun (map #(cullp %) (filter #(not (aget cmpsts %))
(range 2 (inc root)))))
(filter #(not (aget cmpsts %)) (range 2 (inc n))))))</
'''Alternative implementation using Clojure's side-effect oriented list comprehension.'''
<
"Returns a lazy sequence of prime numbers less than lim"
[lim]
Line 3,544 ⟶ 3,867:
(doseq [j (range (* i i) lim i)]
(aset refs j false)))
(filter #(aget refs %) (range 2 lim)))))</
'''Alternative implementation using Clojure's side-effect oriented list comprehension. Odds only.'''
<
"Returns a lazy sequence of prime numbers less than lim"
[lim]
Line 3,557 ⟶ 3,880:
(doseq [j (range (* (+ i i) (inc i)) max-i (+ i i 1))]
(aset refs j false)))
(cons 2 (map #(+ % % 1) (filter #(aget refs %) (range 1 max-i)))))))</
This implemantation is about twice as fast as the previous one and uses only half the memory.
Line 3,566 ⟶ 3,889:
'''Alternative very slow entirely functional implementation using lazy sequences'''
<
"Computes lazy sequence of prime numbers up to a given number using sieve of Eratosthenes"
[n]
Line 3,574 ⟶ 3,897:
(cons p (lazy-seq (nxtprm (-> (range (* p p) (inc n) p)
set (remove cs) rest)))))))]
(nxtprm (range 2 (inc n)))))</
The reason that the above code is so slow is that it has has a high constant factor overhead due to using a (hash) set to remove the composites from the future composites stream, each prime composite stream removal requires a scan across all remaining composites (compared to using an array or vector where only the culled values are referenced, and due to the slowness of Clojure sequence operations as compared to iterator/sequence operations in other languages.
Line 3,581 ⟶ 3,904:
Here is an immutable boolean vector based non-lazy sequence version other than for the lazy sequence operations to output the result:
<
"Computes lazy sequence of prime numbers up to a given number using sieve of Eratosthenes"
[max-prime]
Line 3,595 ⟶ 3,918:
(assoc 1 false)
(sieve 2))
(map-indexed #(vector %2 %1)) (filter first) (map second))))</
The above code is still quite slow due to the cost of the immutable copy-on-modify operations.
Line 3,602 ⟶ 3,925:
The following code implements an odds-only sieve using a mutable bit packed long array, only using a lazy sequence for the output of the resulting primes:
<
(defn primes-to
Line 3,628 ⟶ 3,951:
(recur (inc i)))))))))]
(if (< n 2) nil
(cons 3 (if (< n 3) nil (do (cull) (lazy-seq (nxtprm 0)))))))))</
The above code is about as fast as any "one large sieving array" type of program in any computer language with this level of wheel factorization other than the lazy sequence operations are quite slow: it takes about ten times as long to enumerate the results as it does to do the actual sieving work of culling the composites from the sieving buffer array. The slowness of sequence operations is due to nested function calls, but primarily due to the way Clojure implements closures by "boxing" all arguments (and perhaps return values) as objects in the heap space, which then need to be "un-boxed" as primitives as necessary for integer operations. Some of the facilities provided by lazy sequences are not needed for this algorithm, such as the automatic memoization which means that each element of the sequence is calculated only once; it is not necessary for the sequence values to be retraced for this algorithm.
Line 3,635 ⟶ 3,958:
The following code overcomes many of those limitations by using an internal (OPSeq) "deftype" which implements the ISeq interface as well as the Counted interface to provide immediate count returns (based on a pre-computed total), as well as the IReduce interface which can greatly speed come computations based on the primes sequence (eased greatly using facilities provided by Clojure 1.7.0 and up):
<
"Computes lazy sequence of prime numbers up to a given number using sieve of Eratosthenes"
[n]
Line 3,707 ⟶ 4,030:
(toString [this] (if (= cnt tcnt) "()"
(.toString (seq (map identity this))))))
(->OPSeq 0 cmpsts 0 (numprms))))))))</
'(time (count (primes-tox 10000000)))' takes about 40 milliseconds (compiled) to produce 664579.
Line 3,725 ⟶ 4,048:
'''A Clojure version of Richard Bird's Sieve using Lazy Sequences (sieves odds only)'''
<
"Computes the unbounded sequence of primes using a Sieve of Eratosthenes algorithm by Richard Bird."
[]
Line 3,746 ⟶ 4,069:
(do (def oddprms (cons 3 (lazy-seq (let [cmpsts (-> oddprms (allmtpls) (mrgmltpls))]
(minusStrtAt 5 cmpsts)))))
(cons 2 (lazy-seq oddprms)))))</
The above code is quite slow due to both that the data structure is a linear merging of prime multiples and due to the slowness of the Clojure sequence operations.
Line 3,753 ⟶ 4,076:
The following code speeds up the above code by merging the linear sequence of sequences as above by pairs into a right-leaning tree structure:
<
"Computes the unbounded sequence of primes using a Sieve of Eratosthenes algorithm modified from Bird."
[]
Line 3,777 ⟶ 4,100:
(do (def oddprms (cons 3 (lazy-seq (let [cmpsts (-> oddprms (allmtpls) (mrgmltpls))]
(minusStrtAt 5 cmpsts)))))
(cons 2 (lazy-seq oddprms)))))</
The above code is still slower than it should be due to the slowness of Clojure's sequence operations.
Line 3,784 ⟶ 4,107:
The following code uses a custom "deftype" non-memoizing Co Inductive Stream/Sequence (CIS) implementing the ISeq interface to make the sequence operations more efficient and is about four times faster than the above code:
<
clojure.lang.ISeq
(first [_] v)
Line 3,832 ⟶ 4,155:
(do (def oddprms (->CIS 3 (fn [] (let [cmpsts (-> oddprms (allmtpls) (mrgmltpls))]
(minusStrtAt 5 cmpsts)))))
(->CIS 2 (fn [] oddprms)))))</
'(time (count (take-while #(<= (long %) 10000000) (primes-treeFoldingx))))' takes about 3.4 seconds for a range of 10 million.
Line 3,842 ⟶ 4,165:
The following code is a version of the O'Neill Haskell code but does not use wheel factorization other than for sieving odds only (although it could be easily added) and uses a Hash Map (constant amortized access time) rather than a Priority Queue (log n access time for combined remove-and-insert-anew operations, which are the majority used for this algorithm) with a lazy sequence for output of the resulting primes; the code has the added feature that it uses a secondary base primes sequence generator and only adds prime culling sequences to the composites map when they are necessary, thus saving time and limiting storage to only that required for the map entries for primes up to the square root of the currently sieved number:
<
"Infinite sequence of primes using an incremental Sieve or Eratosthenes with a Hashmap"
[]
Line 3,858 ⟶ 4,181:
(cons c (lazy-seq (nxtoddprm (+ c 2) q bsprms cmpsts))))))]
(do (def baseoddprms (cons 3 (lazy-seq (nxtoddprm 5 9 baseoddprms {}))))
(cons 2 (lazy-seq (nxtoddprm 3 9 baseoddprms {}))))))</
The above code is slower than the best tree folding version due to the added constant factor overhead of computing the hash functions for every hash map operation even though it has computational complexity of (n log log n) rather than the worse (n log n log log n) for the previous incremental tree folding sieve. It is still about 100 times slower than the sieve based on the bit-packed mutable array due to these constant factor hashing overheads.
Line 3,868 ⟶ 4,191:
In order to implement the O'Neill Priority Queue incremental Sieve of Eratosthenes algorithm, one requires an efficient implementation of a Priority Queue, which is not part of standard Clojure. For this purpose, the most suitable Priority Queue is a binary tree heap based MinHeap algorithm. The following code implements a purely functional (using entirely immutable state) MinHeap Priority Queue providing the required functions of (emtpy-pq) initialization, (getMin-pq pq) to examinte the minimum key/value pair in the queue, (insert-pq pq k v) to add entries to the queue, and (replaceMinAs-pq pq k v) to replaace the minimum entry with a key/value pair as given (it is more efficient that if functions were provided to delete and then re-insert entries in the queue; there is therefore no "delete" or other queue functions supplied as the algorithm does not requrie them:
<
Object
(toString [_] (str "<" k "," v ">")))
Line 3,913 ⟶ 4,236:
(if (<= kl kr)
(recur l #(cont (->PQNode kvl % r)))
(recur r #(cont (->PQNode kvr l %))))))))))))</
Note that the above code is written partially using continuation passing style so as to leave the "recur" calls in tail call position as required for efficient looping in Clojure; for practical sieving ranges, the algorithm could likely use just raw function recursion as recursion depth is unlikely to be used beyond a depth of about ten or so, but raw recursion is said to be less code efficient.
Line 3,919 ⟶ 4,242:
The actual incremental sieve using the Priority Queue is as follows, which code uses the same optimizations of postponing the addition of prime composite streams to the queue until the square root of the currently sieved number is reached and using a secondary base primes stream to generate the primes composite stream markers in the queue as was used for the Hash Map version:
<
"Infinite sequence of primes using an incremental Sieve or Eratosthenes with a Priority Queue"
[]
Line 3,937 ⟶ 4,260:
(cons c (lazy-seq (nxtoddprm (+ c 2) q bsprms cmpsts)))))))]
(do (def baseoddprms (cons 3 (lazy-seq (nxtoddprm 5 9 baseoddprms (empty-pq)))))
(cons 2 (lazy-seq (nxtoddprm 3 9 baseoddprms (empty-pq)))))))</
The above code is faster than the Hash Map version up to about a sieving range of fifteen million or so, but gets progressively slower for larger ranges due to having (n log n log log n) computational complexity rather than the (n log log n) for the Hash Map version, which has a higher constant factor overhead that is overtaken by the extra "log n" factor.
Line 3,953 ⟶ 4,276:
To show that Clojure does not need to be particularly slow, the following version runs about twice as fast as the non-segmented unbounded array based version above (extremely fast compared to the non-array based versions) and only a little slower than other equivalent versions running on virtual machines: C# or F# on DotNet or Java and Scala on the JVM:
<
(def PGSZ (bit-shift-left 1 14)) ;; size of CPU cache
Line 4,100 ⟶ 4,423:
(next pgseq)
(+ cnt (count-pg PGBTS pg))))))]
(nxt-pg 0 (primes-pages) 1))))</
The above code runs just as fast as other virtual machine languages when run on a 64-bit JVM; however, when run on a 32-bit JVM it runs almost five times slower. This is likely due to Clojure only using 64-bit integers for integer operations and these operations getting JIT compiled to use library functions to simulate those operations using combined 32-bit operations under a 32-bit JVM whereas direct CPU operations can be used on a 64-bit JVM
Line 4,111 ⟶ 4,434:
The base primes culling page size is reduced from the page size for the main primes so that there is less overhead for smaller primes ranges; otherwise excess base primes are generated for fairly small sieve ranges.
=={{header|CLU}}==
<syntaxhighlight lang="clu">% Sieve of Eratosthenes
eratosthenes = proc (n: int) returns (array[bool])
prime: array[bool] := array[bool]$fill(1, n, true)
prime[1] := false
for p: int in int$from_to(2, n/2) do
if prime[p] then
for c: int in int$from_to_by(p*p, n, p) do
prime[c] := false
end
end
end
return(prime)
end eratosthenes
% Print primes up to 1000 using the sieve
start_up = proc ()
po: stream := stream$primary_output()
prime: array[bool] := eratosthenes(1000)
col: int := 0
for i: int in array[bool]$indexes(prime) do
if prime[i] then
col := col + 1
stream$putright(po, int$unparse(i), 5)
if col = 10 then
col := 0
stream$putc(po, '\n')
end
end
end
end start_up</syntaxhighlight>
{{out}}
<pre> 2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229
233 239 241 251 257 263 269 271 277 281
283 293 307 311 313 317 331 337 347 349
353 359 367 373 379 383 389 397 401 409
419 421 431 433 439 443 449 457 461 463
467 479 487 491 499 503 509 521 523 541
547 557 563 569 571 577 587 593 599 601
607 613 617 619 631 641 643 647 653 659
661 673 677 683 691 701 709 719 727 733
739 743 751 757 761 769 773 787 797 809
811 821 823 827 829 839 853 857 859 863
877 881 883 887 907 911 919 929 937 941
947 953 967 971 977 983 991 997</pre>
=={{header|CMake}}==
<
# Check for integer overflow. With CMake using 32-bit signed integer,
# this check fails when limit > 46340.
Line 4,147 ⟶ 4,522:
endforeach(i)
set(${var} ${list} PARENT_SCOPE)
endfunction(eratosthenes)</
# Print all prime numbers through 100.
eratosthenes(primes 100)
Line 4,153 ⟶ 4,528:
=={{header|COBOL}}==
<
*> which are kludges to get syntax highlighting to work.
IDENTIFICATION DIVISION.
Line 4,207 ⟶ 4,582:
GOBACK
.</
=={{header|Comal}}==
{{trans|BASIC}}
<
input "Limit? ": limit
dim sieve(1:limit)
Line 4,234 ⟶ 4,609:
endif
endfor i
print</
{{Out}}
Line 4,246 ⟶ 4,621:
=={{header|Common Lisp}}==
<
(loop
with sieve = (make-array (1+ maximum)
Line 4,256 ⟶ 4,631:
and do (loop for composite from (expt candidate 2)
to maximum by candidate
do (setf (bit sieve composite) 1))))</
Working with odds only (above twice speedup), and marking composites only for primes up to the square root of the maximum:
<
"Prime numbers sieve for odd numbers.
Returns a list with all the primes that are less than or equal to maximum."
Line 4,273 ⟶ 4,648:
:do (loop :for j :from (* i (1+ i) 2) :to maxi :by odd-number
:do (setf (sbit sieve j) 1))
:finally (return (cons 2 values))))</
The indexation scheme used here interprets each index <code>i</code> as standing for the value <code>2i+1</code>. Bit <code>0</code> is unused, a small price to pay for the simpler index calculations compared with the <code>2i+3</code> indexation scheme. The multiples of a given odd prime <code>p</code> are enumerated in increments of <code>2p</code>, which corresponds to the index increment of <code>p</code> on the sieve array. The starting point <code>p*p = (2i+1)(2i+1) = 4i(i+1)+1</code> corresponds to the index <code>2i(i+1)</code>.
Line 4,280 ⟶ 4,655:
=={{header|Cowgol}}==
<
# To change the maximum prime, change the size of this array
Line 4,310 ⟶ 4,685:
end if;
cand := cand + 1;
end loop;</
{{out}}
Line 4,324 ⟶ 4,699:
4987
4999</pre>
=={{header|Craft Basic}}==
<syntaxhighlight lang="basic">define limit = 120
dim flags[limit]
for n = 2 to limit
let flags[n] = 1
next n
print "prime numbers less than or equal to ", limit ," are:"
for n = 2 to sqrt(limit)
if flags[n] = 1 then
for i = n * n to limit step n
let flags[i] = 0
next i
endif
next n
for n = 1 to limit
if flags[n] then
print n
endif
next n</syntaxhighlight>
{{out| Output}}<pre>
prime numbers less than or equal to 120 are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 </pre>
=={{header|Crystal}}==
Line 4,331 ⟶ 4,746:
This implementation uses a `BitArray` so it is automatically bit-packed to use just one bit per number representation:
<
require "bit_array"
Line 4,380 ⟶ 4,795:
print SoE.new(1_000_000_000).each.size
elpsd = (Time.monotonic - start_time).total_milliseconds
puts " in #{elpsd} milliseconds."</
{{out}}
Line 4,393 ⟶ 4,808:
the non-odds-only version as per the above should never be used because in not using odds-only, it uses twice the memory and over two and a half times the CPU operations as the following odds-only code, which is very little more complex:
<
require "bit_array"
Line 4,445 ⟶ 4,860:
print SoE_Odds.new(1_000_000_000).each.size
elpsd = (Time.monotonic - start_time).total_milliseconds
puts " in #{elpsd} milliseconds."</
{{out}}
Line 4,458 ⟶ 4,873:
For sieving of ranges larger than a few million efficiently, a page-segmented sieve should always be used to preserve CPU cache associativity by making the page size to be about that of the CPU L1 data cache. The following code implements a page-segmented version that is an extensible sieve (no upper limit needs be specified) using a secondary memoized feed of base prime value arrays which use a smaller page-segment size for efficiency. When the count of the number of primes is desired, the sieve is polymorphic in output and counts the unmarked composite bits by using fast `popcount` instructions taken 64-bits at a time. The code is as follows:
<
alias Prime = UInt64
Line 4,660 ⟶ 5,075:
answr = primes_count_to(1_000_000_000) # fast way
elpsd = (Time.monotonic - start_time).total_milliseconds
print "#{answr} in #{elpsd} milliseconds.\r\n"</
{{out}}
Line 4,673 ⟶ 5,088:
=={{header|D}}==
===Simpler Version===
Prints all numbers less than the limit.<
uint[] sieve(in uint limit) nothrow @safe {
Line 4,691 ⟶ 5,106:
void main() {
50.sieve.writeln;
}</
{{out}}
<pre>[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]</pre>
Line 4,697 ⟶ 5,112:
===Faster Version===
This version uses an array of bits (instead of booleans, that are represented with one byte), and skips even numbers. The output is the same.
<
size_t[] sieve(in size_t m) pure nothrow @safe {
Line 4,735 ⟶ 5,150:
void main() {
50.sieve.writeln;
}</
===Extensible Version===
(This version is used in the task [[Extensible prime generator#D|Extensible prime generator]].)
<
struct Prime {
uint[] a = [2];
Line 4,773 ⟶ 5,188:
uint.max.iota.map!prime.until!q{a > 50}.writeln;
}
}</
To see the output (that is the same), compile with <code>-version=sieve_of_eratosthenes3_main</code>.
=={{header|Dart}}==
<
String iterableToString(Iterable seq) {
String str = "[";
Line 4,809 ⟶ 5,224:
print(iterableToString(sortedValues)); // expect sieve.length to be 168 up to 1000...
// Expect.equals(168, sieve.length);
}</
{{out}}<pre>
Found 168 primes up to 1000 in 9 milliseconds.
Line 4,817 ⟶ 5,232:
===faster bit-packed array odds-only solution===
<
import 'dart:math';
Line 4,849 ⟶ 5,264:
print("There were $answer primes found up to $range.");
print("This test bench took $elapsed milliseconds.");
}</
{{output}}
<pre>( 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 )
Line 4,864 ⟶ 5,279:
The following code will have about O(n log (log n)) performance due to a hash table having O(1) average performance and is only somewhat slow due to the constant overhead of processing hashes:
<
Iterable<int> oddprms() sync* {
yield(3); yield(5); // need at least 2 for initialization
Line 4,906 ⟶ 5,321:
print("There were $answer primes found up to $range.");
print("This test bench took $elapsed milliseconds.");
}</
{{output}}
<pre>( 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 )
Line 4,922 ⟶ 5,337:
{{trans|Kotlin}}
<
import 'dart:math';
import 'dart:collection';
Line 5,130 ⟶ 5,545:
print("There were $answer primes found up to $range.");
print("This test bench took $elapsed milliseconds.");
}</
{{output}}
<pre>( 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 )
Line 5,142 ⟶ 5,557:
The algorithm can be sped up by a factor of four by extreme wheel factorization and (likely) about a factor of the effective number of CPU cores by using multi-processing isolates, but there isn't much point if one is to use the prime generator for output. For most purposes, it is better to use custom functions that directly manipulate the culled bit-packed page segments as `countPrimesTo` does here.
=={{header|dc}}==
<syntaxhighlight lang="dc">[dn[,]n dsx [d 1 r :a lx + d ln!<.] ds.x lx] ds@
[sn 2 [d;a 0=@ 1 + d ln!<#] ds#x] se
100 lex</syntaxhighlight>
{{out}}
<pre>2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,\
97,</pre>
=={{header|Delphi}}==
<
{$APPTYPE CONSOLE}
Line 5,228 ⟶ 5,653:
Sieve.Free;
readln;
end.</
Output:
<pre>2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 </pre>
=={{header|Draco}}==
<syntaxhighlight lang="draco">/* Sieve of Eratosthenes - fill a given boolean array */
proc nonrec sieve([*] bool prime) void:
word p, c, max;
max := dim(prime,1)-1;
prime[0] := false;
prime[1] := false;
for p from 2 upto max do prime[p] := true od;
for p from 2 upto max>>1 do
if prime[p] then
for c from p*2 by p upto max do
prime[c] := false
od
fi
od
corp
/* Print primes up to 1000 using the sieve */
proc nonrec main() void:
word MAX = 1000;
unsigned MAX i;
byte c;
[MAX+1] bool prime;
sieve(prime);
c := 0;
for i from 0 upto MAX do
if prime[i] then
write(i:4);
c := c + 1;
if c=10 then c:=0; writeln() fi
fi
od
corp</syntaxhighlight>
{{out}}
<pre> 2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229
233 239 241 251 257 263 269 271 277 281
283 293 307 311 313 317 331 337 347 349
353 359 367 373 379 383 389 397 401 409
419 421 431 433 439 443 449 457 461 463
467 479 487 491 499 503 509 521 523 541
547 557 563 569 571 577 587 593 599 601
607 613 617 619 631 641 643 647 653 659
661 673 677 683 691 701 709 719 727 733
739 743 751 757 761 769 773 787 797 809
811 821 823 827 829 839 853 857 859 863
877 881 883 887 907 911 919 929 937 941
947 953 967 971 977 983 991 997</pre>
=={{header|DWScript}}==
<
var
n, k : Integer;
Line 5,254 ⟶ 5,732:
var i : Integer;
for i:=0 to r.High do
PrintLn(r[i]);</
=={{header|Dylan}}==
With outer to sqrt and inner to p^2 optimizations:
<
let limit = floor(n ^ 0.5) + 1;
let sieve = make(limited(<simple-vector>, of: <boolean>), size: n + 1, fill: #t);
Line 5,281 ⟶ 5,759:
if (sieve[x]) format-out("Prime: %d\n", x); end;
end;
end;</
=={{header|E}}==
Line 5,319 ⟶ 5,797:
=={{header|EasyLang}}==
<syntaxhighlight>
max = sqrt len sieve[]
if
while
.
.
.
for i = 2 to len sieve[]
</syntaxhighlight>
=={{header|eC}}==
{{incorrect|eC|It uses rem testing and so is a trial division algorithm, not a sieve of Eratosthenes.}}
Note: this is not a Sieve of Eratosthenes; it is just trial division.
<
public class FindPrime
{
Line 5,387 ⟶ 5,863:
}
}
</syntaxhighlight>
=={{header|EchoLisp}}==
===Sieve===
<
;; converts sieve->list for integers in [nmin .. nmax[
Line 5,420 ⟶ 5,896:
→ (1000003 1000033 1000037 1000039 1000081 1000099)
(s-next-prime s-primes 9_000_000)
→ 9000011</
===Segmented sieve===
Allow to extend the basis sieve (n) up to n^2. Memory requirement is O(√n)
<
;; delta multiple of sqrt(n)
;; segment is [left .. left+delta-1]
Line 5,457 ⟶ 5,933:
;; 8 msec using the native (prime?) function
(for/list ((p (in-range 1_000_000_000 1_000_001_000))) #:when (prime? p) p)</
===Wheel===
A 2x3 wheel gives a 50% performance gain.
<
(define (weratosthenes n)
(define primes (make-bit-vector n )) ;; everybody to #f (false)
Line 5,477 ⟶ 5,953:
(for ([j (in-range (* p p) n p)])
(bit-vector-set! primes j #f)))
primes)</
=={{header|EDSAC order code}}==
Line 5,485 ⟶ 5,961:
On the EdsacPC simulator (see link above) the printout starts off very slowly, and gradually gets faster.
<
[Sieve of Eratosthenes]
[EDSAC program. Initial Orders 2]
Line 5,706 ⟶ 6,182:
E 19 Z [address to start execution]
P F [acc = 0 at start]
</syntaxhighlight>
{{out}}
<pre>
Line 5,730 ⟶ 6,206:
=={{header|Eiffel}}==
{{works with|EiffelStudio|6.6 beta (with provisional loop syntax)}}
<
APPLICATION
Line 5,764 ⟶ 6,240:
end
end
end</
Output:
Line 5,772 ⟶ 6,248:
=={{header|Elixir}}==
<
def eratosthenes(limit \\ 1000) do
sieve = [false, false | Enum.to_list(2..limit)] |> List.to_tuple
Line 5,796 ⟶ 6,272:
if x=elem(sieve, n), do: :io.format("~3w", [x]), else: :io.format(" .")
if rem(n+1, 20)==0, do: IO.puts ""
end)</
{{out}}
Line 5,814 ⟶ 6,290:
Shorter version (but slow):
<
defmodule Sieve do
def primes_to(limit), do: sieve(Enum.to_list(2..limit))
Line 5,821 ⟶ 6,297:
defp sieve([]), do: []
end
</syntaxhighlight>
'''Alternate much faster odds-only version more suitable for immutable data structures using a (hash) Map'''
The above code has a very limited useful range due to being very slow: for example, to sieve to a million, even changing the algorithm to odds-only, requires over 800 thousand "copy-on-update" operations of the entire saved immutable tuple ("array") of 500 thousand bytes in size, making it very much a "toy" application. The following code overcomes that problem by using a (immutable/hashed) Map to store the record of the current state of the composite number chains resulting from each of the secondary streams of base primes, which are only 167 in number up to this range; it is a functional "incremental" Sieve of Eratosthenes implementation:
<
@typep stt :: {integer, integer, integer, Enumerable.integer, %{integer => integer}}
Line 5,878 ⟶ 6,354:
|> (fn {t,ans} ->
IO.puts "There are #{ans} primes up to #{range}."
IO.puts "This test bench took #{t} microseconds." end).()</
{{output}}
<pre>The first 25 primes are:
Line 5,892 ⟶ 6,368:
In order to save the computation time of computing the hashes, the following version uses a deferred execution Co-Inductive Stream type (constructed using Tuple's) in an infinite tree folding structure (by the `pairs` function):
<
@typep cis :: {integer, (() -> cis)}
@typep ciss :: {cis, (() -> ciss)}
Line 5,972 ⟶ 6,448:
|> (fn {t,ans} ->
IO.puts "There are #{ans} primes up to #{range}."
IO.puts "This test bench took #{t} microseconds." end).()</
It's output is identical to the previous version other than the time required is less than half; however, it has a O(n (log n) (log (log n))) asymptotic computation complexity meaning that it gets slower with range faster than the above version. That said, it would take sieving to billions taking hours before the two would take about the same time.
=={{header|Elm}}==
===Elm with immutable arrays===
<syntaxhighlight lang="elm">
module PrimeArray exposing (main)
import Array exposing (Array, foldr, map, set)
import Html exposing (div, h1, p, text)
import Html.Attributes exposing (style)
{-
The Eratosthenes sieve task in Rosetta Code does not accept the use of modulo function (allthough Elm functions modBy and remainderBy work always correctly as they require type Int excluding type Float). Thus the solution needs an indexed work array as Elm has no indexes for lists.
In this method we need no division remainder calculations, as we just set the markings of non-primes into the array. We need the indexes that we know, where the marking of the non-primes shall be set.
Because everything is immutable in Elm, every change of array values will create a new array save the original array unchanged. That makes the program running slower or consuming more space of memory than with non-functional imperative languages. All conventional loops (for, while, until) are excluded in Elm because immutability requirement.
Live: https://ellie-app.com/pTHJyqXcHtpa1
-}
alist =
List.range 2 150
-- Work array contains integers 2 ... 149
workArray =
Array.fromList alist
n : Int
n =
List.length alist
-- The max index of integers used in search for primes
-- limit * limit < n
-- equal: limit <= √n
limit : Int
limit =
round (0.5 + sqrt (toFloat n))
-- Remove zero cells of the array
findZero : Int -> Bool
findZero =
\el -> el > 0
zeroFree : Array Int
zeroFree =
Array.filter findZero workResult
nrFoundPrimes =
Array.length zeroFree
workResult : Array Int
workResult =
loopI 2 limit workArray
{- As Elm has no loops (for, while, until)
we must use recursion instead!
The search of prime starts allways saving the
first found value (not setting zero) and continues setting the multiples of prime to zero.
Zero is no integer and may thus be used as marking of non-prime numbers. At the end, only the primes remain in the array and the zeroes are removed from the resulted array to be shown in Html.
-}
-- The recursion increasing variable i follows:
loopI : Int -> Int -> Array Int -> Array Int
loopI i imax arr =
if i > imax then
arr
else
let
arr2 =
phase i arr
in
loopI (i + 1) imax arr2
-- The helper function
phase : Int -> Array Int -> Array Int
phase i =
arrayMarker i (2 * i - 2) n
lastPrime =
Maybe.withDefault 0 <| Array.get (nrFoundPrimes - 1) zeroFree
outputArrayInt : Array Int -> String
outputArrayInt arr =
decorateString <|
foldr (++) "" <|
Array.map (\x -> String.fromInt x ++ " ") arr
decorateString : String -> String
decorateString str =
"[ " ++ str ++ "]"
-- Recursively marking the multiples of p with zero
-- This loop operates with constant p
arrayMarker : Int -> Int -> Int -> Array Int -> Array Int
arrayMarker p min max arr =
let
arr2 =
set min 0 arr
min2 =
min + p
in
if min < max then
arrayMarker p min2 max arr2
else
arr
main =
div [ style "margin" "2%" ]
[ h1 [] [ text "Sieve of Eratosthenes" ]
, text ("List of integers [2, ... ," ++ String.fromInt n ++ "]")
, p [] [ text ("Total integers " ++ String.fromInt n) ]
, p [] [ text ("Max prime of search " ++ String.fromInt limit) ]
, p [] [ text ("The largest found prime " ++ String.fromInt lastPrime) ]
, p [ style "color" "blue", style "font-size" "1.5em" ]
[ text (outputArrayInt zeroFree) ]
, p [] [ text ("Found " ++ String.fromInt nrFoundPrimes ++ " primes") ]
]
</syntaxhighlight>
{{out}}
<pre>
List of integers [2, ... ,149]
Total integers 149
Max prime of search 13
The largest found prime 149
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 ]
Found 35 primes </pre>
===Concise Elm Immutable Array Version===
Although functional, the above code is written in quite an imperative style, so the following code is written in a more concise functional style and includes timing information for counting the number of primes to a million:
<syntaxhighlight lang="elm">module Main exposing (main)
import Browser exposing (element)
import Task exposing (Task, succeed, perform, andThen)
import Html exposing (Html, div, text)
import Time exposing (now, posixToMillis)
import Array exposing (repeat, get, set)
cLIMIT : Int
cLIMIT = 1000000
primesArray : Int -> List Int
primesArray n =
if n < 2 then [] else
let
sz = n + 1
loopbp bp arr =
let s = bp * bp in
if s >= sz then arr else
let tst = get bp arr |> Maybe.withDefault True in
if tst then loopbp (bp + 1) arr else
let
cullc c iarr =
if c >= sz then iarr else
cullc (c + bp) (set c True iarr)
in loopbp (bp + 1) (cullc s arr)
cmpsts = loopbp 2 (repeat sz False)
cnvt (i, t) = if t then Nothing else Just i
in cmpsts |> Array.toIndexedList
|> List.drop 2 -- skip the values for zero and one
|> List.filterMap cnvt -- primes are indexes of not composites
type alias Model = List String
type alias Msg = Model
test : (Int -> List Int) -> Int -> Cmd Msg
test primesf lmt =
let
to100 = primesf 100 |> List.map String.fromInt |> String.join ", "
to100str = "The primes to 100 are: " ++ to100
timemillis() = now |> andThen (succeed << posixToMillis)
in timemillis() |> andThen (\ strt ->
let cnt = primesf lmt |> List.length
in timemillis() |> andThen (\ stop ->
let answrstr = "Found " ++ (String.fromInt cnt) ++ " primes to "
++ (String.fromInt cLIMIT) ++ " in "
++ (String.fromInt (stop - strt)) ++ " milliseconds."
in succeed [to100str, answrstr] ) ) |> perform identity
main : Program () Model Msg
main =
element { init = \ _ -> ( [], test primesArray cLIMIT )
, update = \ msg _ -> (msg, Cmd.none)
, subscriptions = \ _ -> Sub.none
, view = div [] << List.map (div [] << List.singleton << text) }</syntaxhighlight>
{{out}}
<pre>The primes up to 100 are: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97.
Found 78498 primes to 1000000 in 958 milliseconds.</pre>
The above output is the contents of the HTML web page as shown with Google Chrome version 1.23 running on an AMD 7840HS CPU at 5.1 GHz (single thread boosted).
===Concise Elm Immutable Array Odds-Only Version===
The following code can replace the `primesArray` function in the above program and called from the testing and display code (two places):
<syntaxhighlight lang="elm">primesArrayOdds : Int -> List Int
primesArrayOdds n =
if n < 2 then [] else
let
sz = (n - 1) // 2
loopi i arr =
let s = (i + i) * (i + 3) + 3 in
if s >= sz then arr else
let tst = get i arr |> Maybe.withDefault True in
if tst then loopi (i + 1) arr else
let
bp = i + i + 3
cullc c iarr =
if c >= sz then iarr else
cullc (c + bp) (set c True iarr)
in loopi (i + 1) (cullc s arr)
cmpsts = loopi 0 (repeat sz False)
cnvt (i, t) = if t then Nothing else Just <| i + i + 3
oddprms = cmpsts |> Array.toIndexedList |> List.filterMap cnvt
in 2 :: oddprms</syntaxhighlight>
{{out}}
<pre>The primes up to 100 are: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97.
Found 78498 primes to 1000000 in 371 milliseconds.</pre>
The above output is the contents of the HTML web page as shown with Google Chrome version 1.23 running on an AMD 7840HS CPU at 5.1 GHz (single thread boosted).
===Richard Bird Tree Folding Elm Version===
The Elm language doesn't efficiently handle the Sieve of Eratosthenes (SoE) algorithm because it doesn't have directly accessible linear arrays (the Array module used above is based on a persistent tree of sub arrays) and also does Copy On Write (COW) for every write to every location as well as a logarithmic process of updating as a "tree" to minimize the COW operations. Thus, there is better performance implementing the Richard Bird Tree Folding functional algorithm, as follows:
{{trans|Haskell}}
<syntaxhighlight lang="elm">module Main exposing (main)
import Browser exposing (element)
import Task exposing (Task, succeed, perform, andThen)
import Html exposing (Html, div, text)
import Time exposing (now, posixToMillis)
cLIMIT : Int
cLIMIT = 1000000
type CIS a = CIS a (() -> CIS a)
uptoCIS2List : comparable -> CIS comparable -> List comparable
uptoCIS2List n cis =
let loop (CIS hd tl) lst =
if hd > n then List.reverse lst
else loop (tl()) (hd :: lst)
in loop cis []
countCISTo : comparable -> CIS comparable -> Int
countCISTo n cis =
let loop (CIS hd tl) cnt =
if hd > n then cnt else loop (tl()) (cnt + 1)
in loop cis 0
primesTreeFolding : () -> CIS Int
primesTreeFolding() =
let
merge (CIS x xtl as xs) (CIS y ytl as ys) =
case compare x y of
LT -> CIS x <| \ () -> merge (xtl()) ys
EQ -> CIS x <| \ () -> merge (xtl()) (ytl())
GT -> CIS y <| \ () -> merge xs (ytl())
pmult bp =
let adv = bp + bp
pmlt p = CIS p <| \ () -> pmlt (p + adv)
in pmlt (bp * bp)
allmlts (CIS bp bptl) =
CIS (pmult bp) <| \ () -> allmlts (bptl())
pairs (CIS frst tls) =
let (CIS scnd tlss) = tls()
in CIS (merge frst scnd) <| \ () -> pairs (tlss())
cmpsts (CIS (CIS hd tl) tls) =
CIS hd <| \ () -> merge (tl()) <| cmpsts <| pairs (tls())
testprm n (CIS hd tl as cs) =
if n < hd then CIS n <| \ () -> testprm (n + 2) cs
else testprm (n + 2) (tl())
oddprms() =
CIS 3 <| \ () -> testprm 5 <| cmpsts <| allmlts <| oddprms()
in CIS 2 <| \ () -> oddprms()
type alias Model = List String
type alias Msg = Model
test : (() -> CIS Int) -> Int -> Cmd Msg
test primesf lmt =
let
to100 = primesf() |> uptoCIS2List 100
|> List.map String.fromInt |> String.join ", "
to100str = "The primes to 100 are: " ++ to100
timemillis() = now |> andThen (succeed << posixToMillis)
in timemillis() |> andThen (\ strt ->
let cnt = primesf() |> countCISTo lmt
in timemillis() |> andThen (\ stop ->
let answrstr = "Found " ++ (String.fromInt cnt) ++ " primes to "
++ (String.fromInt cLIMIT) ++ " in "
++ (String.fromInt (stop - strt)) ++ " milliseconds."
in succeed [to100str, answrstr] ) ) |> perform identity
main : Program () Model Msg
main =
element { init = \ _ -> ( [], test primesTreeFolding cLIMIT )
, update = \ msg _ -> (msg, Cmd.none)
, subscriptions = \ _ -> Sub.none
, view = div [] << List.map (div [] << List.singleton << text) }</syntaxhighlight>
{{out}}
<pre>The primes up to 100 are: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97.
Found 78498 primes to 1000000 in 201 milliseconds.</pre>
The above output is the contents of the HTML web page as shown with Google Chrome version 1.23 running on an AMD 7840HS CPU at 5.1 GHz (single thread boosted).
===Elm Priority Queue Version===
Using a Binary Minimum Heap Priority Queue is a constant factor faster than the above code as the data structure is balanced rather than "heavy to the right" and requires less memory allocations/deallocation in the following code, which implements enough of the Priority Queue for the purpose. Just substitute the following code for `primesTreeFolding` and pass `primesPQ` as an argument to `test` rather than `primesTreeFolding`:
<syntaxhighlight lang="elm">type PriorityQ comparable v =
Mt
| Br comparable v (PriorityQ comparable v)
(PriorityQ comparable v)
emptyPQ : PriorityQ comparable v
emptyPQ = Mt
peekMinPQ : PriorityQ comparable v -> Maybe (comparable, v)
peekMinPQ pq = case pq of
(Br k v _ _) -> Just (k, v)
Mt -> Nothing
pushPQ : comparable -> v -> PriorityQ comparable v
-> PriorityQ comparable v
pushPQ wk wv pq =
case pq of
Mt -> Br wk wv Mt Mt
(Br vk vv pl pr) ->
if wk <= vk then Br wk wv (pushPQ vk vv pr) pl
else Br vk vv (pushPQ wk wv pr) pl
siftdown : comparable -> v -> PriorityQ comparable v
-> PriorityQ comparable v -> PriorityQ comparable v
siftdown wk wv pql pqr =
case pql of
Mt -> Br wk wv Mt Mt
(Br vkl vvl pll prl) ->
case pqr of
Mt -> if wk <= vkl then Br wk wv pql Mt
else Br vkl vvl (Br wk wv Mt Mt) Mt
(Br vkr vvr plr prr) ->
if wk <= vkl && wk <= vkr then Br wk wv pql pqr
else if vkl <= vkr then Br vkl vvl (siftdown wk wv pll prl) pqr
else Br vkr vvr pql (siftdown wk wv plr prr)
replaceMinPQ : comparable -> v -> PriorityQ comparable v
-> PriorityQ comparable v
replaceMinPQ wk wv pq = case pq of
Mt -> Mt
(Br _ _ pl pr) -> siftdown wk wv pl pr
primesPQ : () -> CIS Int
primesPQ() =
let
sieve n pq q (CIS bp bptl as bps) =
if n >= q then
let adv = bp + bp in let (CIS nbp _ as nbps) = bptl()
in sieve (n + 2) (pushPQ (q + adv) adv pq) (nbp * nbp) nbps
else let
(nxtc, _) = peekMinPQ pq |> Maybe.withDefault (q, 0) -- default when empty
adjust tpq =
let (c, adv) = peekMinPQ tpq |> Maybe.withDefault (0, 0)
in if c > n then tpq
else adjust (replaceMinPQ (c + adv) adv tpq)
in if n >= nxtc then sieve (n + 2) (adjust pq) q bps
else CIS n <| \ () -> sieve (n + 2) pq q bps
oddprms() = CIS 3 <| \ () -> sieve 5 emptyPQ 9 <| oddprms()
in CIS 2 <| \ () -> oddprms()</syntaxhighlight>
{{out}}
<pre>The primes up to 100 are: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97.
Found 78498 primes to 1000000 in 124 milliseconds.</pre>
The above output is the contents of the HTML web page as shown with Google Chrome version 1.23 running on an AMD 7840HS CPU at 5.1 GHz (single thread boosted).
=={{header|Emacs Lisp}}==
{{libheader|cl-lib}}
<syntaxhighlight lang="lisp">(defun sieve-set (limit)
(let ((xs (make-vector (1+ limit) 0)))
(cl-loop for i from 2 to limit
when (zerop (aref xs i))
collect i
and do (cl-loop for m from (* i i) to limit by i
do (aset xs m 1)))))</syntaxhighlight>
Straightforward implementation of [http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Implementation sieve of Eratosthenes], 2 times faster:
<syntaxhighlight lang="lisp">(defun sieve (limit)
(let ((xs (vconcat [0 0] (number-sequence 2 limit))))
(cl-loop for i from 2 to (sqrt limit)
when (aref xs i)
do (cl-loop for m from (* i i) to limit by i
do (aset xs m 0)))
(remove 0 xs)))</syntaxhighlight>
=={{header|Erlang}}==
===Erlang using Dicts===
<syntaxhighlight lang="erlang">
-module( sieve_of_eratosthenes ).
Line 6,019 ⟶ 6,912:
find_prime( error, _N, Acc ) -> Acc;
find_prime( {ok, _Value}, N, {Max, Dict} )
{Max, lists:foldl( fun dict:erase/2, Dict, lists:seq(N*N, Max, N))};
find_prime( {ok, _Value}, _, R) -> R.
</syntaxhighlight>
{{out}}
<pre>
Line 6,032 ⟶ 6,927:
Has the virtue of working for any -> N :)
<syntaxhighlight lang="erlang">
-module( sieve ).
-export( [main/1,primes/2] ).
Line 6,066 ⟶ 6,961:
Primes = lists:filter( fun({_,Y}) -> Y > 0 end, Tuples),
[ X || {X,_} <- Primes ].
</syntaxhighlight>
{{out}}
<pre>
Line 6,080 ⟶ 6,975:
Since I had written a really odd and slow one, I thought I'd best do a better performer. Inspired by an example from https://github.com/jupp0r
<syntaxhighlight lang="erlang">
-module(ossieve).
Line 6,106 ⟶ 7,001:
ResultSet = ordsets:add_element(2,sieve(Candidates,Candidates,ordsets:new(),N)),
io:fwrite("Sieved... ~w~n",[ResultSet]).
</syntaxhighlight>
{{out}}
<pre>
Line 6,121 ⟶ 7,016:
A pure list comprehension approach.
<syntaxhighlight lang="erlang">
-module(sieveof).
-export([main/1,primes/1, primes/2]).
Line 6,139 ⟶ 7,034:
remove([H | X], [H | Y]) -> remove(X, Y);
remove(X, [H | Y]) -> [H | remove(X, Y)].
</syntaxhighlight>
{out}
<pre>
Line 6,154 ⟶ 7,049:
===Erlang ets + cpu distributed implementation ===
much faster previous erlang examples
<syntaxhighlight lang="erlang">
#!/usr/bin/env escript
%% -*- erlang -*-
Line 6,219 ⟶ 7,114:
comp_i(J, I, N) when J =< N -> ets:insert(comp, {J, 1}), comp_i(J+I, I, N);
comp_i(J, _, N) when J > N -> ok.
</syntaxhighlight>
{{out}}
<pre>
Line 6,228 ⟶ 7,123:
another several erlang implementation: http://mijkenator.github.io/2015/11/29/project-euler-problem-10/
===Erlang using lists:seq\3 for the initial list and the lists of multiples to be removed ===
<syntaxhighlight lang="erlang">
-module(primesieve).
-export([primes/1]).
mult(N, Limit) ->
case Limit > N * N of
true -> lists:seq(N * N, Limit, N);
false -> []
end.
primes(Limit) ->
case Limit > 1 of
true -> sieve(Limit, 3, [2] ++ lists:seq(3, Limit, 2), mult(3, Limit));
false -> []
end.
sieve(Limit, D, S, M) ->
case Limit < D * D of
true -> S;
false -> sieve(Limit, D + 2, S -- M, mult(D + 2, Limit))
end.
</syntaxhighlight>
{{out}}
<pre>
2> primesieve:primes(100).
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,
79,83,89,97]
3> timer:tc(primesieve, primes, [100]).
{20,
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,
79,83,89,97]}
</pre>
=={{header|ERRE}}==
<syntaxhighlight lang="erre">
PROGRAM SIEVE_ORG
! --------------------------------------------------
Line 6,260 ⟶ 7,190:
PRINT(COUNT%;" PRIMES")
END PROGRAM
</syntaxhighlight>
{{out}}
last lines of the output screen
Line 6,271 ⟶ 7,201:
16301 16319 16333 16339 16349 16361 16363 16369 16381
1899 PRIMES
</pre>
=={{header|Euler}}==
The original Euler doesn't have loops built-in. Loops can easily be added by defining and calling suitable procedures with literal procedures as parameters. In this sample, a C-style "for" loop procedure is defined and used to sieve and print the primes.<br>
'''begin'''
'''new''' sieve; '''new''' for; '''new''' prime; '''new''' i;
for <- ` '''formal''' init; '''formal''' test; '''formal''' incr; '''formal''' body;
'''begin'''
'''label''' again;
init;
again: '''if''' test '''then''' '''begin''' body; incr; '''goto''' again '''end''' '''else''' 0
'''end'''
'
;
sieve <- ` '''formal''' n;
'''begin'''
'''new''' primes; '''new''' i; '''new''' i2; '''new''' j;
primes <- '''list''' n;
for( ` i <- 1 ', ` i <= n ', ` i <- i + 1 '
, ` primes[ i ] <- '''true''' '
);
primes[ 1 ] <- '''false''';
for( ` i <- 2 '
, ` [ i2 <- i * i ] <= n '
, ` i <- i + 1 '
, ` '''if''' primes[ i ] '''then'''
for( ` j <- i2 ', ` j <= n ', ` j <- j + i '
, ` primes[ j ] <- '''false''' '
)
'''else''' 0
'
);
primes
'''end'''
'
;
prime <- sieve( 30 );
for( ` i <- 1 ', ` i <= '''length''' prime ', ` i <- i + 1 '
, ` '''if''' prime[ i ] '''then''' '''out''' i '''else''' 0 '
)
'''end''' $
{{out}}
<pre>
NUMBER 2
NUMBER 3
NUMBER 5
NUMBER 7
NUMBER 11
NUMBER 13
NUMBER 17
NUMBER 19
NUMBER 23
NUMBER 29
</pre>
=={{header|Euphoria}}==
<
sequence flags,primes
flags = repeat(1, limit)
Line 6,291 ⟶ 7,279:
end if
end for
? primes</
Output:
Line 6,306 ⟶ 7,294:
=={{header|F Sharp}}==
===Short with mutable state===
<syntaxhighlight lang="fsharp">
let primes max =
let mutable xs = [|2..max|]
let limit = max |> float |> sqrt |> int
for x in [|2..limit|] do
xs <- xs |> Array.except [|x*x..x..max|]
xs
</syntaxhighlight>
===Short Sweet Functional and Idiotmatic===
Well lists may not be lazy, but if you call it a sequence then it's a lazy list!
<
(*
An interesting implementation of The Sieve of Eratosthenes.
Line 6,321 ⟶ 7,318:
yield g; yield! fn (g - 1) g |> Seq.map2 (&&) ng |> Seq.cache |> fg }
Seq.initInfinite (fun x -> true) |> fg
</syntaxhighlight>
{{out}}
<pre>
Line 6,347 ⟶ 7,344:
This is the idea behind Richard Bird's unbounded code presented in the Epilogue of [http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf M. O'Neill's article] in Haskell. It is about twice as much code as the Haskell code because F# does not have a built-in lazy list so that the effect must be constructed using a Co-Inductive Stream (CIS) type since no memoization is required, along with the use of recursive functions in combination with sequences. The type inference needs some help with the new CIS type (including selecting the generic type for speed). Note the use of recursive functions to implement multiple non-sharing delayed generating base primes streams, which along with these being non-memoizing means that the entire primes stream is not held in memory as for the original Bird code:
<
let primesBird() =
Line 6,362 ⟶ 7,359:
else minusat (n + 1u) (ctlf())
let rec baseprms() = CIS(2u, fun() -> baseprms() |> allmltps |> cmpsts |> minusat 3u)
Seq.unfold (fun (CIS(p, ptlf)) -> Some(p, ptlf())) (baseprms())</
The above code sieves all numbers of two and up including all even numbers as per the page specification; the following code makes the very minor changes for an odds-only sieve, with a speedup of over a factor of two:
<
let primesBirdOdds() =
Line 6,381 ⟶ 7,378:
else minusat (n + 2u) (ctlf())
let rec oddprms() = CIS(3u, fun() -> oddprms() |> allmltps |> cmpsts |> minusat 5u)
Seq.unfold (fun (CIS(p, ptlf)) -> Some(p, ptlf())) (CIS(2u, fun() -> oddprms()))</
'''Tree Folding Sieve'''
The above code is still somewhat inefficient as it operates on a linear right extending structure that deepens linearly with increasing base primes (those up to the square root of the currently sieved number); the following code changes the structure into an infinite binary tree-like folding by combining each pair of prime composite streams before further processing as usual - this decreases the processing by approximately a factor of log n:
<
let primesTreeFold() =
Line 6,404 ⟶ 7,401:
else minusat (n + 2u) (ctlf())
let rec oddprms() = CIS(3u, fun() -> oddprms() |> allmltps |> cmpsts |> minusat 5u)
Seq.unfold (fun (CIS(p, ptlf)) -> Some(p, ptlf())) (CIS(2u, fun() -> oddprms()))</
The above code is over four times faster than the "BirdOdds" version (at least 10x faster than the first, "primesBird", producing the millionth prime) and is moderately useful for a range of the first million primes or so.
Line 6,411 ⟶ 7,408:
In order to investigate Priority Queue Sieves as espoused by O'Neill in the referenced article, one must find an equivalent implementation of a Min Heap Priority Queue as used by her. There is such an purely functional implementation [http://rosettacode.org/wiki/Priority_queue#Functional in RosettaCode translated from the Haskell code she used], from which the essential parts are duplicated here (Note that the key value is given an integer type in order to avoid the inefficiency of F# in generic comparison):
<
module MinHeap =
Line 6,448 ⟶ 7,445:
let replaceMin wk wv = function | Mt -> Mt
| Br(_, ll, rr) -> siftdown wk wv ll rr</
Except as noted for any individual code, all of the following codes need the following prefix code in order to implement the non-memoizing Co-Inductive Streams (CIS's) and to set the type of particular constants used in the codes to the same time as the "Prime" type:
<
type Prime = uint32
let frstprm = 2u
let frstoddprm = 3u
let inc1 = 1u
let inc = 2u</
The F# equivalent to O'Neill's "odds-only" code is then implemented as follows, which needs the included changed prefix in order to change the primes type to a larger one to prevent overflow (as well the key type for the MinHeap needs to be changed from uint32 to uint64); it is functionally the same as the O'Neill code other than for minor changes to suit the use of CIS streams and the option output of the "peekMin" function:
<
type Prime = uint64
let frstprm = 2UL
Line 6,489 ⟶ 7,486:
let rec nxto i = CIS(i, fun() -> nxto (i + inc)) in nxto frstoddprm
Seq.unfold (fun (cis: CIS<Prime>) -> Some(cis.v, cis.cont()))
(CIS(frstprm, fun() -> (sieve odds)))</
However, that algorithm suffers in speed and memory use due to over-eager adding of prime composite streams to the queue such that the queue used is much larger than it needs to be and a much larger range of primes number must be used in order to avoid numeric overflow on the square of the prime added to the queue. The following code corrects that by using a secondary (actually a multiple of) base primes streams which are constrained to be based on a prime that is no larger than the square root of the currently sieved number - this permits the use of much smaller Prime types as per the default prefix:
<
let rec nxtprm n pq q (bps: CIS<Prime>) =
if n >= q then let bp = bps.v in let adv = bp + bp
Line 6,511 ⟶ 7,508:
nxtprm (frstoddprm + inc) MinHeap.empty (frstoddprm * frstoddprm) (oddprms()))
Seq.unfold (fun (cis: CIS<Prime>) -> Some(cis.v, cis.cont()))
(CIS(frstprm, fun() -> (oddprms())))</
The above code is well over five times faster than the previous translated O'Neill version for the given variety of reasons.
Line 6,529 ⟶ 7,526:
The following code is written in functional style other than it uses a mutable bit array to sieve the composites:
<
let buf = System.Collections.BitArray(int limit + 1, true)
let cull p = { p * p .. p .. limit } |> Seq.iter (fun c -> buf.[int c] <- false)
Line 6,539 ⟶ 7,536:
if argv = null || argv.Length = 0 then failwith "no command line argument for limit!!!"
printfn "%A" (primes (System.UInt32.Parse argv.[0]) |> Seq.length)
0 // return an integer exit code</
Substituting the following minor changes to the code for the "primes" function will only deal with the odd prime candidates for a speed up of over a factor of two as well as a reduction of the buffer size by a factor of two:
<
let lmtb,lmtbsqrt = (limit - 3u) / 2u, (uint32 (sqrt (double limit)) - 3u) / 2u
let buf = System.Collections.BitArray(int lmtb + 1, true)
Line 6,551 ⟶ 7,548:
let oddprms = { 0u .. lmtb } |> Seq.map (fun i -> if buf.[int i] then i + i + 3u else 0u)
|> Seq.filter ((<>) 0u)
seq { yield 2u; yield! oddprms }</
The following code uses other functional forms for the inner culling loops of the "primes function" to reduce the use of inefficient sequences so as to reduce the execution time by another factor of almost three:
<
let lmtb,lmtbsqrt = (limit - 3u) / 2u, (uint32 (sqrt (double limit)) - 3u) / 2u
let buf = System.Collections.BitArray(int lmtb + 1, true)
Line 6,562 ⟶ 7,559:
let rec cullp c = if c <= lmtb then buf.[int c] <- false; cullp (c + p)
(if buf.[int i] then cullp s); culltest (i + 1u) in culltest 0u
seq {yield 2u; for i = 0u to lmtb do if buf.[int i] then yield i + i + 3u }</
Now much of the remaining execution time is just the time to enumerate the primes as can be seen by turning "primes" into a primes counting function by substituting the following for the last line in the above code doing the enumeration; this makes the code run about a further five times faster:
<
if i > int lmtb then acc else if buf.[i] then count (i + 1) (acc + 1) else count (i + 1) acc
count 0 1</
Since the final enumeration of primes is the main remaining bottleneck, it is worth using a "roll-your-own" enumeration implemented as an object expression so as to save many inefficiencies in the use of the built-in seq computational expression by substituting the following code for the last line of the previous codes, which will decrease the execution time by a factor of over three (instead of almost five for the counting-only version, making it almost as fast):
<
let i = ref -2
let rec nxti() = i:=!i + 1;if !i <= int lmtb && not buf.[!i] then nxti() else !i <= int lmtb
Line 6,588 ⟶ 7,585:
member this.GetEnumerator() = nmrtr()
interface System.Collections.IEnumerable with
member this.GetEnumerator() = nmrtr() :> System.Collections.IEnumerator }</
The various optimization techniques shown here can be used "jointly and severally" on any of the basic versions for various trade-offs between code complexity and performance. Not shown here are other techniques of making the sieve faster, including extending wheel factorization to much larger wheels such as 2/3/5/7, pre-culling the arrays, page segmentation, and multi-processing.
Line 6,599 ⟶ 7,596:
The following code uses the DotNet Dictionary class instead of the above functional Priority Queue to implement the sieve; as average (amortized) hash table access is O(1) rather than O(log n) as for the priority queue, this implementation is slightly faster than the priority queue version for the first million primes and will always be faster for any range above some low range value:
<
let frstprm = 2u
let frstoddprm = 3u
Line 6,624 ⟶ 7,621:
nxtprm (frstoddprm + inc) (frstoddprm * frstoddprm) (oddprms()))
Seq.unfold (fun (cis: CIS<Prime>) -> Some(cis.v, cis.cont()))
(CIS(frstprm, fun() -> (oddprms())))</
The above code uses functional forms of code (with the imperative style commented out to show how it could be done imperatively) and also uses a recursive non-sharing secondary source of base primes just as for the Priority Queue version. As for the functional codes, the Primes type can easily be changed to "uint64" for wider range of sieving.
Line 6,635 ⟶ 7,632:
All of the above unbounded implementations including the above Dictionary based version are quite slow due to their large constant factor computational overheads, making them more of an intellectual exercise than something practical, especially when larger sieving ranges are required. The following code implements an unbounded page segmented version of the sieve in not that many more lines of code, yet runs about 25 times faster than the Dictionary version for larger ranges of sieving such as to one billion; it uses functional forms without mutability other than for the contents of the arrays and the `primes` enumeration generator function that must use mutability for speed:
<
type private PrimeNdx = float // they are slow in JavaScript polyfills
Line 6,773 ⟶ 7,770:
let answr = countPrimesTo limit // over twice as fast way!
let elpsd = (System.DateTime.Now.Ticks - start) / 10000L
printfn "Found %d primes to %A in %d milliseconds." answr limit elpsd</
{{out}}
Line 6,790 ⟶ 7,787:
Factor is pleasantly multiparadigm. Usually, it's natural to write more functional or declarative code in Factor, but this is an instance where it is more natural to write imperative code. Lexical variables are useful here for expressing the necessary mutations in a clean way.
<
math.ranges prettyprint sequences ;
IN: rosetta-code.sieve-of-erato
Line 6,821 ⟶ 7,818:
120 sieve . ;
MAIN: sieve-demo</
=={{header|FOCAL}}==
<
1.2 A N
1.3 I (2047-N)5.1
Line 6,839 ⟶ 7,836:
4.1 T %4.0,W,!
5.1 T "PLEASE ENTER A NUMBER LESS THAN 2048."!; G 1.1</
Note that with the 4k paper tape version of FOCAL, the program will run out of memory for N>190 or so.
Line 6,871 ⟶ 7,868:
The above code is not really very good Forth style as the main initialization, sieving, and output, are all in one `sieve` routine which makes it difficult to understand and refactor; Forth code is normally written in a series of very small routines which makes it easier to understand what is happening on the data stack, since Forth does not have named local re-entrant variable names as most other languages do for local variables (which other languages also normally store local variables on the stack). Also, it uses the `HERE` pointer to user space which points to the next available memory after all compilation is done as a unsized buffer pointer, but as it does not reserve that space for the sieving buffer, it can be changed by other concatenated routines in unexpected ways; better is to allocate the sieving buffer as required from the available space at the time the routines are run and pass that address between concatenated functions until a finalization function frees the memory and clears the stack; this is equivalent to allocating from the "heap" in other languages. The below code demonstrates these ideas:
<
\ given square index and prime index, u0, sieve the multiples of said prime...
Line 6,916 ⟶ 7,913:
\ testing the code...
100 initsieve sieve .primes
1000000 .countprimesto</
{{out}}
Line 6,929 ⟶ 7,926:
Although the above version resolves many problems of the first version, it is wasteful of memory as each composite number in the sieve buffer is a byte of eight bits representing a boolean value. The memory required can be reduced eight-fold by bit packing the sieve buffer; this will take more "bit-twiddling" to read and write the bits, but reducing the memory used will give better cache assiciativity to larger ranges such that there will be a net gain in performance. This will make the code more complex and the stack manipulations will be harder to write, debug, and maintain, so ANS Forth 1994 provides a local variable naming facility to make this much easier. The following code implements bit-packing of the sieve buffer using local named variables when required:
<syntaxhighlight lang="text">\ produces number of one bits in given word...
: numbts ( u -- u ) \ pop count number of bits...
0 SWAP BEGIN DUP 0<> WHILE SWAP 1+ SWAP DUP 1- AND REPEAT DROP ;
Line 7,014 ⟶ 8,011:
100 initsieve sieve .primes
1000000000 .countprimesto</
The output of the above code is the same as the previous version, but it takes about two thirds the time while using eight times less memory; it takes about 6.5 seconds on my Intel Skylake i5-6500 at 3.6 GHz (turbo) using swiftForth (32-bit) and about 3.5 seconds on VFX Forth (64-bit), both of which compile to machine code but with the latter much more optimized; gforth-fast is about twice as slow as swiftForth and five times slower then VFX Forth as it just compiles to threaded execution tokens (more like an interpreter).
Line 7,022 ⟶ 8,019:
While the above version does greatly reduce the amount of memory used for a given sieving range and thereby also somewhat reduces execution time; any sieve intended for sieving to limits of a hundred million or more should use a page-segmented implementation; page-segmentation means that only storage for a representation of the base primes up to the square root of the limit plus a sieve buffer that should also be at least proportional to the same square root is required; this will again make the execution faster as ranges go up due to better cache associativity with most memory accesses being within the CPU cache sizes. The following Forth code implements a basic version that does this:
<
1 17 LSHIFT CONSTANT L1CacheBits
L1CacheBits 8 * CONSTANT L2CacheBits
Line 7,133 ⟶ 8,130:
100 .primes
1000000000 .countPrimesTo</
{{out}}
Line 7,155 ⟶ 8,152:
=={{header|Fortran}}==
{{works with|Fortran|77}}
<syntaxhighlight lang="fortran">
PROGRAM MAIN
INTEGER LI
WRITE (6,100)
READ (5,110) LI
call SOE(LI)
100 FORMAT( 'Limit:' )
110 FORMAT( I4 )
STOP
END
C --- SIEVE OF ERATOSTHENES ----------
SUBROUTINE SOE( LI )
INTEGER LI
LOGICAL A(LI)
INTEGER SL,P,I
DO 10 I=1,LI
A(I) = .TRUE.
10 CONTINUE
SL = INT(SQRT(REAL(LI)))
A(1) = .FALSE.
DO 30 P=2,SL
IF ( .NOT. A(P) ) GOTO 30
DO 20 I=P*P,LI,P
A(I)=.FALSE.
20 CONTINUE
30 CONTINUE
DO 40 I=2,LI
IF ( A(I) ) WRITE(6,100) I
40 CONTINUE
100 FORMAT(I3)
RETURN
END
</syntaxhighlight>
{{works with|Fortran|90 and later}}
<
implicit none
Line 7,173 ⟶ 8,210:
write (*, *)
end program sieve</
Output:
<syntaxhighlight lang="text">2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97</
Because it uses four byte logical's (default size) as elements of the sieve buffer, the above code uses 400 bytes of memory for this trivial task of sieving to 100; it also has 49 + 31 + 16 + 8 = 104 (for the culling by the primes of two, three, five, and seven) culling operations.
Line 7,181 ⟶ 8,218:
'''Optimised using a pre-computed wheel based on 2:'''
<
implicit none
Line 7,199 ⟶ 8,236:
write (*, *)
end program sieve_wheel_2</
Output:
<syntaxhighlight lang="text">2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97</
This so-called "optimized" version still uses 400 bytes of memory but slightly reduces to 74 operations from 104 operations including the initialization of marking all of the even representations as composite due to skipping the re-culling of the even representation, so isn't really much of an optimization at all!
Line 7,209 ⟶ 8,246:
The above implementations, especially the second odds-only code, are some of the most inefficient versions of the Sieve of Eratosthenes in any language here as to time and space efficiency, only worse by some naive JavaScript implementations that use eight-byte Number's as logical values; the second claims to be wheel factorized but still uses all the same memory as the first and still culls by the even numbers in the initialization of the sieve buffer. As well, using four bytes (default logical size) to store a boolean value is terribly wasteful if these implementations were to be extended to non-toy ranges. The following code implements proper wheel factorization by two, reducing the space used by a factor of about eight to 49 bytes by using `byte` as the sieve buffer array elements and not requiring the evens initialization, thus reducing the number of operations to 16 + 8 + 4 = 28 (for the culling primes of three, five, and seven) culling operations:
<
implicit none
Line 7,227 ⟶ 8,264:
write (*, *)
end program sieve_wheel_2</
The output is the same as the earlier version.
Line 7,235 ⟶ 8,272:
The above implementation is still space inefficient in effectively only using one bit out of eight; the following version implements bit packing to reduce memory use by a factor of eight by using bits to represent composite numbers rather than bytes:
<
implicit none
Line 7,263 ⟶ 8,300:
print '(a, i0, a, i0, a, f0.0, a)', &
'There are ', cnt, ' primes up to ', i_max, '.'
end program sieve_wheel_2</
{{out}}
Line 7,274 ⟶ 8,311:
As well as adding page-segmentation, the following code adds multi-processing which is onc of the capabilities for which modern Fortran is known:
<
implicit none
Line 7,422 ⟶ 8,459:
deallocate(sbaa)
end program sieve_paged</
{{out}}
Line 7,432 ⟶ 8,469:
===Basic version===
function Sieve returns a list of primes less than or equal to the given aLimit
<
program prime_sieve;
{$mode objfpc}{$coperators on}
Line 7,491 ⟶ 8,528:
I: DWord;
begin
Write(aList[I], ', ');
WriteLn(aList[aList.Size - 1]);
end;
aList.Free;
end;
Line 7,506 ⟶ 8,546:
end;
end.
</syntaxhighlight>
===Alternative segmented(odds only) version===
function OddSegmentSieve returns a list of primes less than or equal to the given aLimit
<
program prime_sieve;
{$mode objfpc}{$coperators on}
Line 7,632 ⟶ 8,672:
for I := 0 to Length(aList) - 2 do
Write(aList[I], ', ');
WriteLn(aList[High(aList)]);
end;
begin
Line 7,639 ⟶ 8,680:
PrintPrimes(OddSegmentSieve(Limit));
end.
</syntaxhighlight>
=={{header|FreeBASIC}}==
<
Sub sieve(n As Integer)
Line 7,680 ⟶ 8,721:
Print
Print "Press any key to quit"
Sleep</
{{out}}
Line 7,698 ⟶ 8,739:
=={{header|Frink}}==
<
n = eval[input["Enter highest number: "]]
results = array[sieve[n]]
Line 7,717 ⟶ 8,758:
return select[array, { |x| x != 0 }]
}
</syntaxhighlight>
=={{header|Furor}}==
''Note: With benchmark function''
<syntaxhighlight lang="furor">
tick sto startingtick
#g 100000 sto MAX
Line 7,739 ⟶ 8,780:
end
{ „MAX” } { „startingtick” } { „primeNumbers” } { „count” }
</syntaxhighlight>
=={{header|Peri}}==
''Note: With benchmark function''
<syntaxhighlight lang="peri">
###sysinclude standard.uh
tick sto startingtick
#g 100000 sto MAX
@MAX mem !maximize sto primeNumbers
one count
2 0 sto#s primeNumbers
2 @MAX külső: {{ ,
@count {{
{{}}§külső primeNumbers[{{}}] !/ else {{<}}§külső
}} // @count vége
//{{}} gprintnl // A talált prímszám kiiratásához kommentezzük ki e sort
{{}} @count++ sto#s primeNumbers
}} // @MAX vége
@primeNumbers inv mem
//."Time : " tick @startingtick - print ." tick\n"
."Prímek száma = " @count printnl
end
{ „MAX” } { „startingtick” } { „primeNumbers” } { „count” }
</syntaxhighlight>
=={{header|FutureBasic}}==
===Basic sieve of array of booleans===
<syntaxhighlight lang="futurebasic">window 1, @"Sieve of Eratosthenes", (0,0,720,300)
begin globals
end globals
local fn SieveOfEratosthenes( n as long )
for i = 2 to n
for j = i * i to n step i
gPrimes(j) = _true
next
if gPrimes(i) = 0 then print i
next i
kill gPrimes
end fn
fn SieveOfEratosthenes( 100 )
HandleEvents</syntaxhighlight>
Output:
<pre>
Line 7,773 ⟶ 8,837:
=={{header|Fōrmulæ}}==
{{FormulaeEntry|page=https://formulae.org/?script=examples/Sieve_of_Eratosthenes}}
'''Solution'''
[[File:Fōrmulæ - Sieve of Eratosthenes 01.png]]
'''Test case'''
[[File:Fōrmulæ - Sieve of Eratosthenes 02.png]]
[[File:Fōrmulæ - Sieve of Eratosthenes 03.png]]
=={{header|GAP}}==
<
local a, i, j;
a := ListWithIdenticalEntries(n, true);
Line 7,804 ⟶ 8,874:
Eratosthenes(100);
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 ]</
=={{header|GLBasic}}==
<
// GLBasic implementation
Line 7,831 ⟶ 8,901:
KEYWAIT
</syntaxhighlight>
=={{header|Go}}==
===Basic sieve of array of booleans===
<
import "fmt"
Line 7,876 ⟶ 8,946:
}
}
}</
Output:
<pre>
Line 7,895 ⟶ 8,965:
The above version's output is rather specialized; the following version uses a closure function to enumerate over the culled composite number array, which is bit packed. By using this scheme for output, no extra memory is required above that required for the culling array:
<
import (
Line 7,942 ⟶ 9,012:
}
fmt.Printf("\r\n%v\r\n", count)
}</
{{output}}
<pre>2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Line 7,949 ⟶ 9,019:
===Sieve Tree===
A fairly odd sieve tree method:
<
import "fmt"
Line 8,008 ⟶ 9,078:
fmt.Println(p())
}
}</
===Concurrent Daisy-chain sieve===
A concurrent prime sieve adopted from the example in the "Go Playground" window at http://golang.org/
<
import "fmt"
Line 8,063 ⟶ 9,133:
}
}
}</
The output:
<pre>
Line 8,073 ⟶ 9,143:
===Postponed Concurrent Daisy-chain sieve===
Here we postpone the ''creation'' of filters until the prime's square is seen in the input, to radically reduce the amount of filter channels in the sieve chain.
<
import "fmt"
Line 8,140 ⟶ 9,210:
}
}
}</
The output:
Line 8,150 ⟶ 9,220:
===Incremental Odds-only Sieve===
Uses Go's built-in hash tables to store odd composites, and defers adding new known composites until the square is seen.
<syntaxhighlight lang="go">
package main
Line 8,176 ⟶ 9,246:
var p int
p = <-primes
Line 8,209 ⟶ 9,279:
}
}
</syntaxhighlight>
The output:
<pre>
Line 8,217 ⟶ 9,287:
=={{header|Groovy}}==
This solution uses a BitSet for compactness and speed, but in [[Groovy]], BitSet has full List semantics. It also uses both the "square root of the boundary" shortcut and the "square of the prime" shortcut.
<
def isPrime = new BitSet(bound)
isPrime[0..1] = false
Line 8,227 ⟶ 9,297:
}
(0..bound).findAll { isPrime[it] }
}</
Test:
<syntaxhighlight lang
Output:
Line 8,237 ⟶ 9,307:
=={{header|GW-BASIC}}==
<
20 DIM FLAGS(LIMIT)
30 FOR N = 2 TO SQR (LIMIT)
Line 8,248 ⟶ 9,318:
100 FOR N = 2 TO LIMIT
110 IF FLAGS(N) = 0 THEN PRINT N;", ";
120 NEXT N</
=={{header|Haskell}}==
Line 8,255 ⟶ 9,325:
Mutable array of unboxed <code>Bool</code>s indexed by <code>Int</code>s:
<
{-# OPTIONS_GHC -O2 #-}
Line 8,290 ⟶ 9,360:
putStrLn $ "Found " ++ show answr ++ " to " ++ show top ++
" in " ++ show elpsd ++ " milliseconds."</
The above code chooses conciseness and elegance over speed, but it isn't too slow:
Line 8,303 ⟶ 9,373:
Mutable array of unboxed <code>Bool</code>s indexed by <code>Int</code>s, representing odds only:
<
import Control.Monad.ST
import Data.Array.ST
Line 8,322 ⟶ 9,392:
primesToUO :: Int -> [Int]
primesToUO top | top > 1 = 2 : [2*i + 1 | (i,True) <- assocs $ sieveUO top]
| otherwise = []</
This represents ''odds only'' in the array. [http://ideone.com/KwZNc Empirical orders of growth] is ~ <i>n<sup>1.2</sup></i> in ''n'' primes produced, and improving for bigger ''n''‍ ‍s. Memory consumption is low (array seems to be packed) and growing about linearly with ''n''. Can further be [http://ideone.com/j24jxV significantly sped up] by re-writing the <code>forM_</code> loops with direct recursion, and using <code>unsafeRead</code> and <code>unsafeWrite</code> operations.
Line 8,334 ⟶ 9,404:
The reason for this alternate version is to have an accessible version of "odds only" that uses the same optimizations and is written in the same coding style as the basic version. This can be used by just substituting the following code for the function of the same name in the first base example above. Mutable array of unboxed <code>Bool</code>s indexed by <code>Int</code>s, representing odds only:
<
primesTo limit
| limit < 2 = []
Line 8,347 ⟶ 9,417:
$ takeWhile ((>=) lmt . snd) -- for bp's <= square root limit
[ getbpndx i | (i, False) <- assocs oddcmpstsf ]
return $ 2 : [ i + i + 3 | (i, False) <- assocs oddcmpstsf ]</
{{out}}
Line 8,370 ⟶ 9,440:
===Immutable arrays===
Monolithic sieving array. ''Even'' numbers above 2 are pre-marked as composite, and sieving is done only by ''odd'' multiples of ''odd'' primes:
<
primesToA m = sieve 3 (array (3,m) [(i,odd i) | i<-[3..m]] :: UArray Int Bool)
Line 8,377 ⟶ 9,447:
| p*p > m = 2 : [i | (i,True) <- assocs a]
| a!p = sieve (p+2) $ a//[(i,False) | i <- [p*p, p*p+2*p..m]]
| otherwise = sieve (p+2) a</
Its performance sharply depends on compiler optimizations. Compiled with -O2 flag in the presence of the explicit type signature, it is very fast in producing first few million primes. <code>(//)</code> is an array update operator.
Line 8,384 ⟶ 9,454:
Works by segments between consecutive primes' squares. Should be the fastest of non-monadic code. ''Evens'' are entirely ignored:
<
primesSA = 2 : prs ()
Line 8,396 ⟶ 9,466:
a :: UArray Int Bool
a = accumArray (\ b c -> False) True (1,q-1)
[(i,()) | (s,y) <- fs, i <- [y+s, y+s+s..q]]</
====As list comprehension====
<syntaxhighlight lang="haskell">import Data.Array.Unboxed
import Data.List (tails, inits)
primes = 2 : [ n |
(r:q:_, px) <- zip (tails (2 : [p*p | p <- primes]))
(inits primes),
(n, True) <- assocs ( accumArray (\_ _ -> False) True
(r+1,q-1)
[ (m,()) | p <- px
, s <- [ div (r+p) p * p]
, m <- [s,s+p..q-1] ] :: UArray Int Bool
) ]</syntaxhighlight>
===Basic list-based sieve===
Straightforward implementation of the sieve of Eratosthenes in its original bounded form. This finds primes in gaps between the composites, and composites as an enumeration of each prime's multiples.
<
eratos (p : xs)
| p*p > m = p : xs
Line 8,411 ⟶ 9,496:
EQ -> minus xs ys
GT -> minus a ys
minus a b = a </
Its time complexity is similar to that of optimal [[Primality_by_trial_division#Haskell|trial division]] because of limitations of Haskell linked lists, where <code>(minus a b)</code> takes time proportional to <code>length(union a b)</code> and not <code>(length b)</code>, as achieved in imperative setting with direct-access memory. Uses ordered list representation of sets.
Line 8,418 ⟶ 9,503:
===Unbounded list based sieve===
Unbounded, "naive", too eager to subtract (see above for the definition of <code>minus</code>):
<
where
sieve (p:xs) = p : sieve (minus xs [p, p+p..])
-- unfoldr (\(p:xs)-> Just (p, minus xs [p, p+p..])) [2..]</
This is slow, with complexity increasing as a square law or worse so that it is only moderately useful for the first few thousand primes or so.
The number of active streams can be limited to what's strictly necessary by postponement until the square of a prime is seen, getting a massive complexity improvement to better than <i>~ n<sup>1.5</sup></i> so it can get first million primes or so in a tolerable time:
<
where
sieve (x:xs) q (p:t)
Line 8,432 ⟶ 9,517:
-- fix $ (2:) . concat
-- . unfoldr (\(p:ps,xs)-> Just . second ((ps,) . (`minus` [p*p, p*p+p..]))
-- . span (< p*p) $ xs) . (,[3..]) </
Transposing the workflow, going by segments between the consecutive squares of primes:
<
primesSE = 2 : sieve 3 4 (tail primesSE) (inits primesSE)
Line 8,444 ⟶ 9,529:
-- True (x,q-1) [(i,()) | f <- fs, let n=div(x+f-1)f*f,
-- i <- [n, n+f..q-1]] :: UArray Int Bool )]
++ sieve q (head ps^2) (tail ps) ft</
The basic gradually-deepening left-leaning <code>(((a-b)-c)- ... )</code> workflow of <code>foldl minus a bs</code> above can be rearranged into the right-leaning <code>(a-(b+(c+ ... )))</code> workflow of <code>minus a (foldr union [] bs)</code>. This is the idea behind Richard Bird's unbounded code presented in [http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf M. O'Neill's article], equivalent to:
<
-- = _Y ( (2:) . minus [3..] . _LU . map(\p-> [p*p, p*p+p..]) )
Line 8,461 ⟶ 9,546:
LT -> x : union xs b
EQ -> x : union xs ys
GT -> y : union a ys</
Using <code>_Y</code> is meant to guarantee the separate supply of primes to be independently calculated, recursively, instead of the same one being reused, corecursively; thus the memory footprint is drastically reduced. This idea was introduced by M. ONeill as a double-staged production, with a separate primes feed.
Line 8,471 ⟶ 9,556:
This merges primes' multiples streams in a ''tree''-like fashion, as a sequence of balanced trees of <code>union</code> nodes, likely achieving theoretical time complexity only a ''log n'' factor above the optimal ''n log n log (log n)'', for ''n'' primes produced. Indeed, empirically it runs at about ''~ n<sup>1.2</sup>'' (for producing first few million primes), similarly to priority-queue–based version of M. O'Neill's, and with very low space complexity too (not counting the produced sequence of course):
<
primes() = 2 : _Y ((3:) . gaps 5 . _U . map(\p-> [p*p, p*p+2*p..])) where
_Y g = g (_Y g) -- = g (g (g ( ... ))) non-sharing multistage fixpoint combinator
Line 8,478 ⟶ 9,563:
_U ((x:xs):t) = x : (merge xs . _U . pairs) t -- tree-shaped folding big union
pairs (xs:ys:t) = merge xs ys : pairs t
merge xs@(x:
Works with odds only, the simplest kind of wheel. Here's the [http://ideone.com/qpnqe test entry] on Ideone.com, and a [http://ideone.com/p0e81 comparison with more versions].
Line 8,486 ⟶ 9,571:
====With Wheel====
Using <code>_U</code> defined above,
<
primesW = [2,3,5,7] ++ _Y ( (11:) . gapsW 13 (tail wheel) . _U .
map (\p->
Line 8,497 ⟶ 9,582:
wheel = 2:4:2:4:6:2:6:4:2:4:6:6:2:6:4:2:6:4:6:8:4:2:4:2: -- gaps = (`gapsW` cycle [2])
4:8:6:4:6:2:4:6:2:6:6:4:2:4:6:2:6:4:2:4:2:10:2:10:wheel
-- cycle $ zipWith (-) =<< tail $ [i | i <- [11..221], gcd i 210 == 1]</
Used [[Emirp_primes#List-based|here]] and [[Extensible_prime_generator#List_based|here]].
Line 8,507 ⟶ 9,592:
2. Improving the means to re-generate the position on the wheel for the recursive base primes without the use of `dropWhile`, etc. The below improved code uses a copy of the place in the wheel for each found base prime for ease of use in generating the composite number to-be-culled chains.
<
wheelGen :: Int -> ([Int],Int,[Int])
wheelGen n = loop 1 3 [2] [2] where
Line 8,544 ⟶ 9,629:
| x < y = x : union xs' ys
| y < x = y : union xs ys'
| otherwise = x : union xs' ys' -- x and y must be equal!</
When compiled with -O2 optimization and -fllvm (the LLVM back end), the above code is over twice as fast as the Odds-Only version as it should be as that is about the ratio of reduced operations minus some slightly increased operation complexity, sieving the primes to a hundred million in about seven seconds on a modern middle range desktop computer. It is almost twice as fast as the "primesW" version due to the increased algorithmic efficiency!
Line 8,555 ⟶ 9,640:
In order to implement a Priority Queue version with Haskell, an efficient Priority Queue, which is not part of the standard Haskell libraries, is required. A Min Heap implementation is likely best suited for this task in providing the most efficient frequently used peeks of the next item in the queue and replacement of the first item in the queue (not using a "pop" followed by a "push) with "pop" operations then not used at all, and "push" operations used relatively infrequently. Judging by O'Neill's use of an efficient "deleteMinAndInsert" operation which she states "(We provide deleteMinAndInsert becausea heap-based implementation can support this operation with considerably less rearrangement than a deleteMin followed by an insert.)", which statement is true for a Min Heap Priority Queue and not others, and her reference to a priority queue by (Paulson, 1996), the queue she used is likely the one as provided as a simple true functional [http://rosettacode.org/wiki/Priority_queue#Haskell Min Heap implementation on RosettaCode], from which the essential functions are reproduced here:
<
| Br !k v !(PriorityQ k v) !(PriorityQ k v)
deriving (Eq, Ord, Read, Show)
Line 8,584 ⟶ 9,669:
replaceMinPQ :: Ord k => k -> v -> PriorityQ k v -> PriorityQ k v
replaceMinPQ wk wv Mt = Mt
replaceMinPQ wk wv (Br _ _ pl pr) = siftdown wk wv pl pr</
The "peekMin" function retrieves both the key and value in a tuple so processing is required to access whichever is required for further processing. As well, the output of the peekMin function is a Maybe with the case of an empty queue providing a Nothing output.
The following code is O'Neill's original odds-only code (without wheel factorization) from her paper slightly adjusted as per the requirements of this Min Heap implementation as laid out above; note the `seq` adjustments to the "adjust" function to make the evaluation of the entry tuple more strict for better efficiency:
<
-- this copyright message is retained and changed versions of the file
-- are clearly marked.
Line 8,612 ⟶ 9,697:
| otherwise = table
where (n, n':ns) = case peekMinPQ table of
Just tpl -> tpl</
The above code is almost four times slower than the version of the Tree Merging sieve above for the first million primes although it is about the same speed as the original Richard Bird sieve with the "odds-only" adaptation as above. It is slow and uses a huge amount of memory for primarily one reason: over eagerness in adding prime composite streams to the queue, which are added as the primes are listed rather than when they are required as the output primes stream reaches the square of a given base prime; this over eagerness also means that the processed numbers must have a large range in order to not overflow when squared (as in the default Integer = infinite precision integers as used here and by O'Neill, but Int64's or Word64's would give a practical range) which processing of wide range numbers adds processing and memory requirement overhead. Although O'Neill's code is elegant, it also loses some efficiency due to the extensive use of lazy list processing, not all of which is required even for a wheel factorization implementation.
The following code is adjusted to reduce the amount of lazy list processing and to add a secondary base primes stream (or a succession of streams when the combinator is used) so as to overcome the above problems and reduce memory consumption to only that required for the primes below the square root of the currently sieved number; using this means that 32-bit Int's are sufficient for a reasonable range and memory requirements become relatively negligible:
<
primesPQx() = 2 : _Y ((3 :) . sieve 5 emptyPQ 9) -- initBasePrms
where
Line 8,638 ⟶ 9,723:
in ntbl `seq` adjust ntbl
| otherwise = table
where (c, adv) = case peekMinPQ table of Just ct -> ct `seq` ct</
The above code is over five times faster than the previous (O'Neill) Priority Queue code half again faster than the Tree-Merging Odds-Only code for a range of a hundred million primes; it is likely faster as the Min Heap is slightly more efficient than Tree Merging due to better tree balancing.
Line 8,644 ⟶ 9,729:
Since the Tree-Folding version above includes the minor changes to work with a factorization wheel, this should have the same minor modifications for comparison purposes, with the code as follows:
<
primesPQWheeled :: () -> [Int]
Line 8,674 ⟶ 9,759:
in ntbl `seq` adjust ntbl
| otherwise = table
where (c, (a:as')) = case peekMinPQ table of Just ct -> ct `seq` ct</
Compiled with -O2 optimization and -fllvm (the LLVM back end), this code gains about the expected ratio in performance in sieving to a range of a hundred million, sieving to this range in about five seconds on a modern medium range desktop computer. This is likely the fastest purely functional incremental type SoE useful for moderate ranges up to about a hundred million to a billion.
Line 8,681 ⟶ 9,766:
All of the above unbounded sieves are quite limited in practical sieving range due to the large constant factor overheads in computation, making them mostly just interesting intellectual exercises other than for small ranges of up to about the first million to ten million primes; the following '''"odds-only"''' page-segmented version using (bit-packed internally) mutable unboxed arrays is about 50 times faster than the fastest of the above algorithms for ranges of about that and higher, making it practical for the first several hundred million primes:
<
import Data.Int ( Int64 )
Line 8,722 ⟶ 9,807:
return cmpsts
pagesFrom lwi bps = map (`makePg` bps)
[ lwi, lwi + fromIntegral szblmt + 1 .. ]</
The above code as written has a maximum practical range of about 10^12 or so in about an hour.
Line 8,740 ⟶ 9,825:
To show the limitations of the individual prime enumeration, the following code has been refactored from the above to provide an alternate very fast method of counting the unset bits in the culled array (the primes = none composite) using a CPU native pop count instruction:
<
{-# OPTIONS_GHC -O2 -fllvm #-} -- use LLVM for about double speed!
Line 8,843 ⟶ 9,928:
putStr $ "Found " ++ show answr
putStr $ " primes up to " ++ show limit
putStrLn $ " in " ++ show elpsd ++ " milliseconds."</
When compiled with the "fast way" commented out and the "slow way enabled, the time to find the number of primes up to one billion is about 3.65 seconds on an Intel Sandy Bridge i3-2100 at 3.1 Ghz; with the "fast way" enabled instead, the time is only about 1.45 seconds for the same range, both compiled with the LLVM back end. This shows that more than half of the time for the "slow way" is spent just producing and enumerating the list of primes!
Line 8,859 ⟶ 9,944:
===APL-style===
Rolling set subtraction over the rolling element-wise addition on integers. Basic, slow, worse than quadratic in the number of primes produced, empirically:
<
. scanl1 minus
. scanl1 (zipWith (+)) $ repeat [2..]</
Or, a wee bit faster:
<
. tail) $ a)
. scanl1 (zipWith (+)) $ repeat [2..]</
A bit optimized, much faster, with better complexity,
<
. unfoldr (\(a:b:t) -> Just . second ((:t) . (`minus` b))
. span (< head b) $ a)
. scanl1 (zipWith (+) . tail) $ tails [1..]
-- $ [ [n*n, n*n+n..] | n <- [1..] ]</
getting nearer to the functional equivalent of the <code>primesPE</code> above, i.e.
<
. unfoldr (\(a:b:t) -> Just . second ((:t) . (`minus` b))
. span (< head b) $ a)
. ([3..] :) . map (\p-> [p*p, p*p+p..]) )</
An illustration:
<
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
[ 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32]
Line 8,902 ⟶ 9,987:
[ 64, 72, 80, 88, 96,104,112,120,128,136,144,152,160,168,176]
[ 81, 90, 99,108,117,126,135,144,153,162,171,180,189,198,207]
[100,110,120,130,140,150,160,170,180,190,200,210,220,230,240]</
=={{header|HicEst}}==
<
sieve = $ > 1 ! = 0 1 1 1 1 ...
Line 8,918 ⟶ 10,003:
DO i = 1, N
IF( sieve(i) ) WRITE() i
ENDDO </
=={{header|Hoon}}==
<syntaxhighlight lang="hoon">:: Find primes by the sieve of Eratosthenes
!:
|= end=@ud
=/ index 2
=/ primes `(list @ud)`(gulf 1 end)
|- ^- (list @ud)
?: (gte index (lent primes)) primes
$(index +(index), primes +:(skid primes |=([a=@ud] &((gth a index) =(0 (mod a index))))))
</syntaxhighlight>
=={{header|Icon}} and {{header|Unicon}}==
<
sieve(100)
end
Line 8,931 ⟶ 10,027:
do p[j] := 0
every write(i:=2 to n & p[i] == 1 & i)
end</
Alternatively using sets
<
sieve(100)
end
Line 8,945 ⟶ 10,041:
delete(primes,1)
every write(!sort(primes))
end</
=={{header|J}}==
{{eff note|J|i.&.(p:inv) }}
Implementation:<syntaxhighlight lang="j">sieve=: {{
r=. 0#t=. y# j=.1
while. y>j=.j+1 do.
if. j{t do.
t=. t > y$j{.1
r=. r, j
end.
end.
}}</syntaxhighlight>
Example:
<syntaxhighlight lang="j"> sieve 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97</syntaxhighlight>
To see into how this works, we can change the definition:
<syntaxhighlight lang
while. y>j=.j+1 do.
echo j;(y$j{.1);t=. t > y$j{.1
end.
}}</syntaxhighlight>
And go:<syntaxhighlight lang="j"> sieve 10
┌─┬───────────────────┬───────────────────┐
│2│1 0 1 0 1 0 1 0 1 0│0 1 0 1 0 1 0 1 0 1│
└─┴───────────────────┴───────────────────┘
┌─┬───────────────────┬───────────────────┐
│3│1 0 0 1 0 0 1 0 0 1│0 1 0 0 0 1 0 1 0 0│
└─┴───────────────────┴───────────────────┘
┌─┬───────────────────┬───────────────────┐
│5│1 0 0 0 0 1 0 0 0 0│0 1 0 0 0 0 0 1 0 0│
└─┴───────────────────┴───────────────────┘
┌─┬───────────────────┬───────────────────┐
│7│1 0 0 0 0 0 0 1 0 0│0 1 0 0 0 0 0 0 0 0│
└─┴───────────────────┴───────────────────┘
2 3 5 7</syntaxhighlight>
Thus, here, <code>t</code> would select numbers which have not yet been determined to be a multiple of a prime number.
=={{header|Janet}}==
===Simple, all primes below a limit===
Janet has a builtin [https://janet-lang.org/docs/data_structures/buffers.html "buffer" type] which is used as a mutable byte string. It has builtin utility methods to handle bit strings (see [https://janet-lang.org/api/buffer.html here] :)
This is based off the Python version.
<syntaxhighlight lang="janet">(defn primes-before
"Gives all the primes < limit"
[limit]
(assert (int? limit))
# Janet has a buffer type (mutable string) which has easy methods for use as bitset
(def buf-size (math/ceil (/ limit 8)))
(def is-prime (buffer/new-filled buf-size (bnot 0)))
(print "Size" buf-size "is-prime: " is-prime)
(buffer/bit-clear is-prime 0)
(buffer/bit-clear is-prime 1)
(for n 0 (math/ceil (math/sqrt limit))
(if (buffer/bit is-prime n) (loop [i :range-to [(* n n) limit n]]
(buffer/bit-clear is-prime i))))
(def res @[]) # Result: Mutable array
(if (buffer/bit is-prime i)
(array/push res i)))
(def res (array/new limit))
(for i 0 limit
(if (buffer/bit is-prime i)
(array/push res i)))
res)</syntaxhighlight>
=={{header|Java}}==
{{works with|Java|1.5+}}
<
public class Sieve{
Line 9,154 ⟶ 10,144:
return primes;
}
}</
To optimize by testing only odd numbers, replace the loop marked "unoptimized" with these lines:
<
for(int i = 3;i <= n;i += 2){
nums.add(i);
}</
Version using List:
<syntaxhighlight lang="java5">
import java.util.ArrayList;
import java.util.List;
public class Eratosthenes {
public List<Integer> sieve(Integer n) {
List<Integer> primes = new ArrayList<Integer>(n);
boolean[] isComposite = new boolean[n + 1];
for(int i = 2; i <= n; i++) {
if(!isComposite[i]) {
primes.add(i);
for(int j = i * i; j <= n; j += i) {
isComposite[j] = true;
}
}
}
return primes;
}
}
</syntaxhighlight>
Version using a BitSet:
<
import java.util.BitSet;
Line 9,178 ⟶ 10,189:
return primes;
}
}</
Version using a TreeSet:
<
import java.util.TreeSet;
Line 9,209 ⟶ 10,220:
return list;
}
}</
===Infinite iterator===
Line 9,215 ⟶ 10,226:
{{trans|Python}}
{{works with|Java|1.5+}}
<
import java.util.PriorityQueue;
import java.math.BigInteger;
Line 9,268 ⟶ 10,279:
}
}
}</
{{out}}
<pre>
Line 9,287 ⟶ 10,298:
{{trans|Python}}
{{works with|Java|1.5+}}
<
import java.util.HashMap;
Line 9,345 ⟶ 10,356:
}
}</
{{out}}<pre>Found 5761455 primes up to 100000000 in 4297 milliseconds.</pre>
Line 9,355 ⟶ 10,366:
{{trans|JavaScript}}
{{works with|Java|1.5+}}
<
import java.util.ArrayList;
Line 9,432 ⟶ 10,443:
}
}</
{{out}}<pre>Found 50847534 primes up to 1000000000 in 3201 milliseconds.</pre>
=={{header|JavaScript}}==
<
var primes = [];
if (limit >= 2) {
Line 9,463 ⟶ 10,474:
if (typeof print == "undefined")
print = (typeof WScript != "undefined") ? WScript.Echo : alert;
print(primes);</
outputs:
<pre>2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97</pre>
Line 9,469 ⟶ 10,480:
Substituting the following code for the function for '''an odds-only algorithm using bit packing''' for the array produces code that is many times faster than the above:
<
var prms = [];
if (limit >= 2) prms = [2];
Line 9,490 ⟶ 10,501:
}
return prms;
}</
While the above code is quite fast especially using an efficient JavaScript engine such as Google Chrome's V8, it isn't as elegant as it could be using the features of the new EcmaScript6 specification when it comes out about the end of 2014 and when JavaScript engines including those of browsers implement that standard in that we might choose to implement an incremental algorithm iterators or generators similar to as implemented in Python or F# (yield). Meanwhile, we can emulate some of those features by using a simulation of an iterator class (which is easier than using a call-back function) for an '''"infinite" generator based on an Object dictionary''' as in the following odds-only code written as a JavaScript class:
<
function SoEIncClass() {
this.n = 0;
Line 9,535 ⟶ 10,546:
};
return SoEIncClass;
})();</
The above code can be used to find the nth prime (which would require estimating the required range limit using the previous fixed range code) by using the following code:
<
for (var i = 1; i < 1000000; i++, gen.next());
var prime = gen.next();
Line 9,545 ⟶ 10,556:
if (typeof print == "undefined")
print = (typeof WScript != "undefined") ? WScript.Echo : alert;
print(prime);</
to produce the following output (about five seconds using Google Chrome's V8 JavaScript engine):
Line 9,555 ⟶ 10,566:
This can be implemented as '''an "infinite" odds-only generator using page segmentation''' for a considerable speed-up with the alternate JavaScript class code as follows:
<
function SoEPgClass() {
this.bi = -1; // constructor resets the enumeration to start...
Line 9,611 ⟶ 10,622:
};
return SoEPgClass;
})();</
The above code is about fifty times faster (about five seconds to calculate 50 million primes to about a billion on the Google Chrome V8 JavaScript engine) than the above dictionary based code.
The speed for both of these "infinite" solutions will also respond to further wheel factorization techniques, especially for the dictionary based version where any added overhead to deal with the factorization wheel will be negligible compared to the dictionary overhead. The dictionary version would likely speed up about a factor of three or a little more with maximum wheel factorization applied; the page segmented version probably won't gain more than a factor of two and perhaps less due to the overheads of array look-up operations.
function is copy-pasted from above to produce a webpage version for beginners:
<syntaxhighlight lang="javascript">
<script>
function eratosthenes(limit) {
var primes = [];
if (limit >= 2) {
var sqrtlmt = Math.sqrt(limit) - 2;
var nums = new Array(); // start with an empty Array...
for (var i = 2; i <= limit; i++) // and
nums.push(i); // only initialize the Array once...
for (var i = 0; i <= sqrtlmt; i++) {
var p = nums[i]
if (p)
for (var j = p * p - 2; j < nums.length; j += p)
nums[j] = 0;
}
for (var i = 0; i < nums.length; i++) {
var p = nums[i];
if (p)
primes.push(p);
}
}
return primes;
}
var primes = eratosthenes(100);
output='';
for (var i = 0; i < primes.length; i++) {
output+=primes[i];
if (i < primes.length-1) output+=',';
}
document.write(output);
</script>
</syntaxhighlight>
=={{header|JOVIAL}}==
<syntaxhighlight lang="jovial">
START
FILE MYOUTPUT ... $ ''Insufficient information to complete this declaration''
Line 9,672 ⟶ 10,717:
END
TERM$
</syntaxhighlight>
=={{header|jq}}==
{{works with|jq|1.4}}
==Bare Bones==
Short and sweet ...
<
# eratosthenes/0 produces an array of primes less than or equal to $n:
def eratosthenes:
def erase(i):
if .[i] then
reduce (range(2*i; length; i)) as $j (.; .[$j] = false)
else .
end;
Line 9,693 ⟶ 10,738:
| [null, null, range(2; $n)]
| reduce (2, 1 + (2 * range(1; $s))) as $i (.; erase($i))
| map(select(.));</
'''Examples''':
<syntaxhighlight lang
{{out}}
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
<syntaxhighlight lang
{{out}}
664579
===Enhanced Sieve===
Here is a more economical variant that:
* produces a stream of primes less than or equal to a given integer;
* only records the status of odd integers greater than 3 during the sieving process;
* optimizes the inner loop as described in the task description.
<syntaxhighlight lang=jq>
def primes:
# The array we use for the sieve only stores information for the odd integers greater than 1:
# index integer
# 0 3
# k 2*k + 3
# So if we wish to mark m = 2*k + 3, the relevant index is: m - 3 / 2
def ix:
if . % 2 == 0 then null
else ((. - 3) / 2)
end;
# erase(i) sets .[i*j] to false for odd integral j > i, and assumes i is odd
def erase(i):
((i - 3) / 2) as $k
# Consider relevant multiples:
then (((length * 2 + 3) / i)) as $upper
# ... only consider odd multiples from i onwards
| reduce range(i; $upper; 2) as $j (.;
(((i * $j) - 3) / 2) as $m
| if .[$m] then .[$m] = false else . end);
if . < 2 then []
else (. + 1) as $n
| (($n|sqrt) / 2) as $s
| [range(3; $n; 2)|true]
| reduce (1 + (2 * range(1; $s)) ) as $i (.; erase($i))
| . as $sieve
| 2, (range(3; $n; 2) | select($sieve[ix]))
end ;
def count(s): reduce s as $_ (0; .+1);
count(1e6 | primes)
</syntaxhighlight>
{{output}}
<pre>
78498
</pre>
=={{header|Julia}}==
Started with 2 already in the array, and then test only for odd numbers and push the prime ones onto the array.
<
function sieve(lim :: Int)
if lim < 2 return [] end
Line 9,725 ⟶ 10,817:
end
return result
end</
Alternate version using <code>findall</code> to get all primes at once in the end
<syntaxhighlight lang
for p in 2:n
primes[p .* (2:n÷p)]
end
findall(primes)
end</syntaxhighlight>
At about 35 seconds for a range of a billion on my Intel Atom i5-Z8350 CPU at 1.92 GHz (single threaded) or about 70 CPU clock cycles per culling operation, the above examples are two of the very slowest ways to compute the Sieve of Eratosthenes over any kind of a reasonable range due to a couple of factors:
Line 9,757 ⟶ 10,842:
If one is going to "crib" the MatLab algorithm as above, one may as well do it using odds-only as per the MatLab built-in. The following alternate code improves on the "Alternate" example above by making it sieve odds-only and adjusting the result array contents after to suit:
<
ni = (n - 1) ÷ 2
isprime = trues(ni)
Line 9,776 ⟶ 10,861:
end
end
end</
This takes less about 18.5 seconds or 36 CPU cycles per culling operation to find the primes to a billion, but that is still quite slow compared to what can be done below. Note that the result array needs to be created then copied, created by the <code>findall</code> function, then modified in place by the <code>map!</code> function to transform the indices to primes, and finally copied by the <code>pushfirst!</code> function to add the only even prime of two to the beginning, but these operations are quire fast. However, this still consumes a lot of memory, as in about 64 Megabytes for the sieve buffer and over 400 Megabytes for the result (8-byte Int's for 64 bit execution) to sieve to a billion, and culling the huge culling buffer that doesn't fit the CPU cache sizes is what makes it slow.
Line 9,784 ⟶ 10,869:
The creation of an output results array is not necessary if the purpose is just to scan across the resulting primes once, they can be output using an iterator (from a `BitArray`) as in the following odds-only code:
<
struct Primes
Line 9,832 ⟶ 10,917:
return (i + i + 1, i + 1)
end
end</
for which using the following code:
<
@time length(Primes(100)) # warm up JIT
# println(@time count(x->true, Primes(1000000000))) # about 1.5 seconds slower counting over iteration
println(@time length(Primes(1000000000)))
end
bench()</
results in the following output:
Line 9,855 ⟶ 10,940:
For any kind of reasonably large range such as a billion, a page segmented version should be used with the pages sized to the CPU caches for much better memory access times. As well, the following odds-only example uses a custom bit packing algorithm for a further two times speed-up, also reducing the memory allocation delays by reusing the sieve buffers when possible (usually possible):
<
const BasePrime = UInt32
const BasePrimesArray = Array{BasePrime,1}
Line 10,052 ⟶ 11,137:
end
low + state + state, state + 1
end</
When tested with the following code:
<
print("( ")
for p in PrimesPaged() p > 100 && break; print(p, " ") end
Line 10,070 ⟶ 11,155:
println(@time countPrimesTo(Prime(1000000000)))
end
bench()</
it produces the following:
Line 10,090 ⟶ 11,175:
One of the best simple purely functional Sieve of Eratosthenes algorithms is the infinite tree folding sequence algorithm as implemented in Haskell. As Julia does not have a standard LazyList implementation or library and as a full memoizing lazy list is not required for this algorithm, the following odds-only code implements the rudiments of a Co-Inductive Stream (CIS) in its implementation:
<
struct CIS{T}
Line 10,132 ⟶ 11,217:
|> allmultiples |> composites))
CIS{Int}(2, () -> oddprimes())
end</
when tested with the following:
<
it outputs the following:
Line 10,151 ⟶ 11,236:
To gain some extra speed above the purely functional algorithm above, the Python'ish version as a mutable iterator embedding a mutable standard base Dictionary can be used. The following version uses a secondary delayed injection stream of "base" primes defined recursively to provide the successions of composite values in the Dictionary to be used for sieving:
<
abstract type PrimesDictAbstract end # used for forward reference
mutable struct PrimesDict <: PrimesDictAbstract
Line 10,189 ⟶ 11,274:
end
end
end</
The above version can be used and tested with similar code as for the functional version, but is about ten times faster at about 400 CPU clock cycles per culling operation, meaning it has a practical range ten times larger although it still has a O(n (log n) (log log n)) asymptotic performance complexity; for larger ranges such as sieving to a billion or more, this is still over a hundred times slower than the page segmented version using a page segmented sieving array.
=={{header|Klingphix}}==
<
%limit %i
Line 10,204 ⟶ 11,289:
pstack
"Press ENTER to end " input</
=={{header|Kotlin}}==
<syntaxhighlight lang="kotlin">import kotlin.math.sqrt
fun sieve(max: Int): List<Int> {
for (x in 2..limit) xs -= x * x..max step x
return xs
}
fun main(args: Array<String>) {
println(sieve(100))
}</
{{out}}
Line 10,247 ⟶ 11,314:
The following code overcomes most of those problems: It only culls odd composites; it culls a bit-packed primitive array (also saving memory); It uses tailcall recursive functions for the loops, which are compiled into simple loops. It also outputs the results as an enumeration, which isn't fast but does not consume any more memory than the culling array. In this way, the program is only limited in sieving range by the maximum size limit of the culling array, although as it grows larger than the CPU cache sizes, it loses greatly in speed; however, that doesn't matter so much if just enumerating the results.
<
val topi = (rng - 3) shr 1
val lstw = topi shr 5
Line 10,295 ⟶ 11,362:
println()
println(primesOdds(1000000).count())
}</
{{output}}
<pre>2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Line 10,304 ⟶ 11,371:
Ah, one might say, for such a trivial range one writes for conciseness and not for speed. Well, I say, one can still save memory and some time using odds-only and a bit-packed array, but write very clear and concise (but slower) code using nothing but higher order functions and function calling. The following code using such techniques can use the same "main" function for the same output but is about two times slower, mostly due to the extra time spent making (nested) function calls, including the function calls necessary for enumeration. Note that the effect of using the "(l .. h).forEach { .. }" is the same as the "for i in l .. h { .. }" as both use an iteration across the range but the second is just syntax sugar to make it look more imperative:
<
val topi = (rng - 3) / 2 //convert to nearest index
val size = topi / 32 + 1 //word size to include index
Line 10,316 ⟶ 11,383:
val orng = (-1 .. topi).filter { it < 0 || is_p(it) }.map { i2p(it) }
return Iterable { -> orng.iterator() }
}</
The trouble with the above version is that, at least for Kotlin version 1.0, the ".filter" and ".map" extension functions for Iterable<Int> create Java "ArrayList"'s as their output (which are wrapped to return the Kotlin "List<Int>" interface), thus take a considerable amount of memory worse than the first version (using an ArrayList to store the resulting primes), since as the calculations are chained to ".map", require a second ArrayList of up to the same size while the mapping is being done. The following version uses Sequences , which aren't backed by any permanent structure, but it is another small factor slower due to the nested function calls:
<
val topi = (rng - 3) / 2 //convert to nearest index
val size = topi / 32 + 1 //word size to include index
Line 10,334 ⟶ 11,401:
val oseq = iseq(topi, -1).filter { it < 0 || is_p(it) }.map { i2p(it) }
return Iterable { -> oseq.iterator() }
}</
===Unbounded Versions===
Line 10,341 ⟶ 11,408:
The following Sieve of Eratosthenes is not purely functional in that it uses a Mutable HashMap to store the state of succeeding composite numbers to be skipped over, but embodies the principles of an incremental implementation of the Sieve of Eratosthenes sieving odds-only and is faster than most incremental sieves due to using mutability. As with the fastest of this kind of sieve, it uses a delayed secondary primes feed as a source of base primes to generate the composite number progressions. The code as follows:
<
yield(2)
fun oddprms(): Sequence<Int> = sequence {
Line 10,373 ⟶ 11,440:
}
yieldAll(oddprms())
}</
At about 370 clock cycles per culling operation (about 3,800 cycles per prime) on my tablet class Intel CPU, this is not blazing fast but adequate for ranges of a few millions to a hundred million and thus fine for doing things like solving Euler problems. For instance, Euler Problem 10 of summing the primes to two million can be done with the following "one-liner":
<
to output the correct answer of the following in about 270 milliseconds for my Intel x5-Z8350 at 1.92 Gigahertz:
Line 10,388 ⟶ 11,455:
{{trans|Haskell}}
<
fun toSequence() = generateSequence(this) { it.tailf() } .map { it.head }
}
Line 10,425 ⟶ 11,492:
val stop = System.currentTimeMillis()
println("Took ${stop - strt} milliseconds.")
}</
The code is about five times slower than the more imperative hash table based version immediately above due to the costs of the extra levels of function calls in the functional style. The Haskell version from which this is derived is much faster due to the extensive optimizations it does to do with function/closure "lifting" as well as a Garbage Collector specifically tuned for functional code.
Line 10,432 ⟶ 11,499:
The very fastest implementations of a primes sieve are all based on bit-packed mutable arrays which can be made unbounded by setting them up so that they are a succession of sieved bit-packed arrays that have been culled of composites. The following code is an odds=only implementation that, again, uses a secondary feed of base primes that is only expanded as necessary (in this case memoized by a rudimentary lazy list structure to avoid recalculation for every base primes sweep per page segment):
<
internal typealias BasePrime = Int
internal typealias BasePrimeArray = IntArray
Line 10,605 ⟶ 11,672:
}
}
}</
For this implementation, counting the primes to a million is trivial at about 15 milliseconds on the same CPU as above, or almost too short to count.
Line 10,618 ⟶ 11,685:
Kotlin isn't really fast even as compared to other virtual machine languages such as C# and F# on CLI but that is mostly due to limitations of the Java Virtual Machine (JVM) as to speed of generated Just In Time (JIT) compilation, handling of primitive number operations, enforced array bounds checks, etc. It will always be much slower than native code producing compilers and the (experimental) native compiler for Kotlin still isn't up to speed (pun intended), producing code that is many times slower than the code run on the JVM (December 2018).
=={{header|Lambdatalk}}==
<syntaxhighlight lang="scheme">
• 1) create an array of natural numbers, [0,1,2,3, ... ,n-1]
• 2) the 3rd number is 2, we set to dots all its composites by steps of 2,
• 3) the 4th number is 3, we set to dots all its composites by steps of 3,
• 4) the 6th number is 5, we set to dots all its composites by steps of 5,
• 5) the remaining numbers are primes and we clean all dots.
For instance:
1: 0 0 0 0 0 0 0 0 0 9 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
2: 0 1 2 3 . 5 . 7 . 9 . 1 . 3 . 5 . 7 . 9 . 1 . 3 . 5 . 7 . 9 .
3: 0 1 2 3 . 5 . 7 . . . 1 . 3 . . . 7 . 9 . . . 3 . 5 . . . 9 .
4: 0 1 2 3 . 5 . 7 . . . 1 . 3 . . . 7 . 9 . . . 3 . . . . . 9 .
| | | | | | | | | |
5: 0 0 0 0 1 1 1 1 2 2
2 3 5 7 1 3 7 9 3 9
1) recursive version {rsieve n}
{def rsieve
{def rsieve.mark
{lambda {:n :a :i :j}
{if {< :j :n}
then {rsieve.mark :n
{A.set! :j . :a}
:i
{+ :i :j}}
else :a}}}
{def rsieve.loop
{lambda {:n :a :i}
{if {< {* :i :i} :n}
then {rsieve.loop :n
{if {W.equal? {A.get :i :a} .}
then :a
else {rsieve.mark :n :a :i {* :i :i}}}
{+ :i 1}}
else :a}}}
{lambda {:n}
{S.replace \s by space in
{S.replace (\[|\]|\.|,) by space in
{A.disp
{A.slice 2 -1
{rsieve.loop :n
{A.new {S.serie 0 :n}} 2}}}}}}}
-> rsieve
{rsieve 1000}
-> 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997
Note: this version doesn't avoid stackoverflow.
2) iterative version {isieve n}
{def isieve
{def isieve.mark
{lambda {:n :a :i}
{S.map {{lambda {:a :j} {A.set! :j . :a}
} :a}
{S.serie {* :i :i} :n :i} }}}
{lambda {:n}
{S.replace \s by space in
{S.replace (\[|\]|\.|,) by space in
{A.disp
{A.slice 2 -1
{S.last
{S.map {{lambda {:n :a :i} {if {W.equal? {A.get :i :a} .}
then
else {isieve.mark :n :a :i}}
} :n {A.new {S.serie 0 :n}}}
{S.serie 2 {sqrt :n} 1}}}}}}}}}
-> isieve
{isieve 1000}
-> 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997
Notes:
- this version avoids stackoverflow.
- From 1 to 1000000 there are 78500 primes (computed in ~15000ms) and the last is 999983.
</syntaxhighlight>
=={{header|langur}}==
{{trans|D}}
<syntaxhighlight lang
val sieve =
if limit < 2: return []
var
for
if not
for
}
}
}
}
writeln
</syntaxhighlight>
{{out}}
<pre>[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]</pre>
=={{header|LFE}}==
<syntaxhighlight lang="lisp">
(defmodule eratosthenes
(export (sieve 1)))
(defun sieve (limit)
(sieve limit (lists:seq 2 limit)))
(defun sieve
((limit (= l (cons p _))) (when (> (* p p) limit))
l)
((limit (cons p ns))
(cons p (sieve limit (remove-multiples p (* p p) ns)))))
(defun remove-multiples (p q l)
(lists:reverse (remove-multiples p q l '())))
(defun remove-multiples
((_ _ '() s) s)
((p q (cons q ns) s)
(remove-multiples p q ns s))
((p q (= r (cons a _)) s) (when (> a q))
(remove-multiples p (+ q p) r s))
((p q (cons n ns) s)
(remove-multiples p q ns (cons n s))))
</syntaxhighlight>
{{Out}}
<pre>
lfe> (slurp "sieve.lfe")
#(ok eratosthenes)
lfe> (sieve 100)
(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97)
</pre>
=={{header|Liberty BASIC}}==
<
'The sieve() function uses the flags() array.
'This is a Sieve benchmark adapted from BYTE 1985
Line 10,670 ⟶ 11,861:
end if
next i
end function</
=={{header|Limbo}}==
<
include "sys.m";
Line 10,713 ⟶ 11,904:
}
}
</syntaxhighlight>
=={{header|Lingo}}==
<
property _sieve
Line 10,756 ⟶ 11,947:
end repeat
end repeat
end</
<
put sieve.getPrimes(100)</
{{out}}
Line 10,767 ⟶ 11,958:
=={{header|LiveCode}}==
<
set itemdel to comma
local sieve
Line 10,788 ⟶ 11,979:
sort items of sieve ascending numeric
return sieve
end sieveE</
Example<
-- 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113</
<
# calculates prime numbers up to a given number
Line 10,820 ⟶ 12,011:
end mouseUp
</syntaxhighlight>
[http://www.melellington.com/sieve/livecode-sieve-output.png LiveCode output example]
Line 10,853 ⟶ 12,044:
due to the use of mod (modulo = division) in the filter function.
A coinduction based solution just for fun:
<
:- object(sieve).
Line 10,892 ⟶ 12,083:
:- end_object.
</syntaxhighlight>
Example query:
<
?- sieve::primes(20, P).
P = [2, 3|_S1], % where
_S1 = [5, 7, 11, 13, 17, 19, 2, 3|_S1] .
</syntaxhighlight>
=={{header|LOLCODE}}==
<
CAN HAS STDIO?
Line 10,949 ⟶ 12,140:
I IZ Eratosumthin YR 100 MKAY
KTHXBYE</
{{Out}}
Line 10,955 ⟶ 12,146:
=={{header|Lua}}==
<
if n < 2 then return {} end
local t = {0} -- clears '1'
Line 10,964 ⟶ 12,155:
for i = 2, n do if t[i] ~= 0 then table.insert(primes, i) end end
return primes
end</
The following changes the code to '''odds-only''' using the same large array-based algorithm:
<
if n < 2 then return {} end
if n < 3 then return {2} end
Line 10,980 ⟶ 12,171:
for i = 0, lmt do if t[i] ~= 0 then table.insert(primes, i + i + 3) end end
return primes
end</
The following code implements '''an odds-only "infinite" generator style using a table as a hash table''', including postponing adding base primes to the table:
<
local _cand = 0; local _lstbp = 3; local _lstsqr = 9
local _composites = {}; local _bps = nil
Line 11,017 ⟶ 12,208:
while gen.next() <= 10000000 do count = count + 1 end -- sieves to 10 million
print(count)
</syntaxhighlight>
which outputs "664579" in about three seconds. As this code uses much less memory for a given range than the previous ones and retains efficiency better with range, it is likely more appropriate for larger sieve ranges.
Line 11,043 ⟶ 12,234:
=={{header|M2000 Interpreter}}==
<syntaxhighlight lang="m2000 interpreter">
Module EratosthenesSieve (x) {
\\ Κόσκινο του Ερατοσθένη
Dim i(x+1): k=2: k2=sqrt(x)
While k<=k2{if i(k) else for m=k*k to x step k{i(m)=1}
Print str$(timecount/1000,"####0.##")+" s"
Input "Press enter skip print or a non zero to get results:", a%
if a% then For i=2to
}
Print:Print "Done"
}
EratosthenesSieve 1000
</syntaxhighlight>
=={{header|M4}}==
<
define(`for',
`ifelse($#,0,
Line 11,078 ⟶ 12,263:
`j for(`k',eval(j*j),lim,j,
`define(a[k],1)')')')
</syntaxhighlight>
Output:
Line 11,087 ⟶ 12,272:
=={{header|MAD}}==
<
R TO GENERATE MORE PRIMES, CHANGE BOTH THESE NUMBERS
Line 11,113 ⟶ 12,298:
VECTOR VALUES BEGIN = $13HPRIMES UP TO ,I9*$
VECTOR VALUES NUMFMT = $I9*$
END OF PROGRAM</
{{out}}
Line 11,135 ⟶ 12,320:
=={{header|Maple}}==
<
local numbers_to_check, i, k;
numbers_to_check := [seq(2 .. n)];
Line 11,148 ⟶ 12,333:
return numbers_to_check;
end proc:
</syntaxhighlight>
{{out}}
<pre>
Line 11,156 ⟶ 12,341:
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
Do[If[numbers[[i]] != 0, Do[numbers[[i j]] = 0, {j, 2, n/i}]], {i,
2, Sqrt[n]}];
Select[numbers, # > 1 &]]
Eratosthenes[100]</
===Slightly Optimized Version===
The below has been improved to not require so many operations per composite number cull for about two thirds the execution time:
<
Do[If[numbers[[i]] != 0, Do[numbers[[j]] = 0, {j,i i,n,i}]],{i,2,Sqrt[n]}];
Select[numbers, # > 1 &]]
Eratosthenes[100]</
===Sieving Odds-Only Version===
The below has been further improved to only sieve odd numbers for a further reduction in execution time by a factor of over two:
<
Do[c = numbers[[i]]; If[c != 0,
Do[numbers[[j]] = 0, {j,(c c - 1)/2,limit,c}]], {i,1,(Sqrt[n] - 1)/2}];
Prepend[Select[numbers, # > 1 &], 2]]
Eratosthenes2[100]</
=={{header|MATLAB}} / {{header|Octave}}==
===Somewhat optimized true Sieve of Eratosthenes===
<
P = [0 2:x]; % Create vector with all ints between 2 and x where
Line 11,192 ⟶ 12,377:
P = P(P ~= 0); % Remove all zeroes from P, leaving only the primes.
end</
'''Limitation:''' your machine has to be able to allocate enough memory for an array of length x.
Line 11,199 ⟶ 12,384:
A more efficient Sieve avoids creating a large double precision vector P, instead using a logical array (which consumes 1/8 the memory of a double array of the same size) and only converting to double those values corresponding to primes.
<
ISP = [false true(1, x-1)]; % 1 is not prime, but we start off assuming all numbers between 2 and x are
for n = 2:sqrt(x)
Line 11,209 ⟶ 12,394:
P = find(ISP); % Convert the ISPRIME output to the values of the primes by finding the locations
% of the TRUE values in S.
end</
You can compare the output of this function against the PRIMES function included in MATLAB, which performs a somewhat more memory-efficient Sieve (by not storing even numbers, at the expense of a more complicated indexing expression inside the IF statement.)
=={{header|Maxima}}==
<
[a:makelist(true,n),i:1,j],
a[1]:false,
Line 11,223 ⟶ 12,408:
for j from i*i step i while j<=n do a[j]:false
)
)$</
=={{header|MAXScript}}==
Line 11,246 ⟶ 12,431:
=={{header|Mercury}}==
<
:- interface.
:- import_module io.
Line 11,304 ⟶ 12,489:
else
true
).</
=={{header|Microsoft Small Basic}}==
{{trans|GW-BASIC}}
<
TextWindow.Write("Enter number to search to: ")
limit = TextWindow.ReadNumber()
Line 11,331 ⟶ 12,516:
TextWindow.WriteLine("")
EndIf
</syntaxhighlight>
=={{header|Modula-2}}==
<syntaxhighlight lang="modula2">MODULE Erato;
FROM InOut IMPORT WriteCard, WriteLn;
FROM MathLib IMPORT sqrt;
CONST Max = 100;
VAR prime: ARRAY [2..Max] OF BOOLEAN;
i: CARDINAL;
PROCEDURE Sieve;
VAR i, j, sqmax: CARDINAL;
BEGIN
sqmax := TRUNC(sqrt(FLOAT(Max)));
FOR i := 2 TO Max DO prime[i] := TRUE; END;
FOR i := 2 TO sqmax DO
IF prime[i] THEN
j := i * 2;
(* alas, the BY clause in a FOR loop must be a constant *)
WHILE j <= Max DO
prime[j] := FALSE;
j := j + i;
END;
END;
END;
END Sieve;
BEGIN
Sieve;
FOR i := 2 TO Max DO
IF prime[i] THEN
WriteCard(i,5);
WriteLn;
END;
END;
END Erato.</syntaxhighlight>
{{out}}
<pre style='height:50ex;'> 2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97</pre>
=={{header|Modula-3}}==
===Regular version===
This version runs slow because of the way I/O is implemented in the CM3 compiler. Setting <code>ListPrimes = FALSE</code> achieves speed comparable to C on sufficiently high values of <code>LastNum</code> (e.g., 10^6).
<
IMPORT IO;
Line 11,394 ⟶ 12,643:
IO.PutChar('\n');
END Eratosthenes.</
===Advanced version===
This version uses more "advanced" types.
<
MODULE Sieve EXPORTS Main;
Line 11,423 ⟶ 12,672:
END;
IO.Put("\n");
END Sieve.</
=={{header|Mojo}}==
Tested with Mojo version 0.7:
<syntaxhighlight lang="mojo">from memory import memset_zero
from memory.unsafe import (DTypePointer)
from time import (now)
alias cLIMIT: Int = 1_000_000_000
struct SoEBasic(Sized):
var len: Int
var cmpsts: DTypePointer[DType.bool] # because DynamicVector has deep copy bug in mojo version 0.7
var sz: Int
var ndx: Int
fn __init__(inout self, limit: Int):
self.len = limit - 1
self.sz = limit - 1
self.ndx = 0
self.cmpsts = DTypePointer[DType.bool].alloc(limit - 1)
memset_zero(self.cmpsts, limit - 1)
for i in range(limit - 1):
let s = i * (i + 4) + 2
if s >= limit - 1: break
if self.cmpsts[i]: continue
let bp = i + 2
for c in range(s, limit - 1, bp):
self.cmpsts[c] = True
for i in range(limit - 1):
if self.cmpsts[i]: self.sz -= 1
fn __del__(owned self):
self.cmpsts.free()
fn __copyinit__(inout self, existing: Self):
self.len = existing.len
self.cmpsts = DTypePointer[DType.bool].alloc(self.len)
for i in range(self.len):
self.cmpsts[i] = existing.cmpsts[i]
self.sz = existing.sz
self.ndx = existing.ndx
fn __moveinit__(inout self, owned existing: Self):
self.len = existing.len
self.cmpsts = existing.cmpsts
self.sz = existing.sz
self.ndx = existing.ndx
fn __len__(self: Self) -> Int: return self.sz
fn __iter__(self: Self) -> Self: return self
fn __next__(inout self: Self) -> Int:
if self.ndx >= self.len: return 0
while (self.ndx < self.len) and (self.cmpsts[self.ndx]):
self.ndx += 1
let rslt = self.ndx + 2; self.sz -= 1; self.ndx += 1
return rslt
fn main():
print("The primes to 100 are:")
for prm in SoEBasic(100): print_no_newline(prm, " ")
print()
let strt0 = now()
let answr0 = len(SoEBasic(1_000_000))
let elpsd0 = (now() - strt0) / 1000000
print("Found", answr0, "primes up to 1,000,000 in", elpsd0, "milliseconds.")
let strt1 = now()
let answr1 = len(SoEBasic(cLIMIT))
let elpsd1 = (now() - strt1) / 1000000
print("Found", answr1, "primes up to", cLIMIT, "in", elpsd1, "milliseconds.")</syntaxhighlight>
{{out}}
<pre>The primes to 100 are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Found 78498 primes up to 1,000,000 in 1.2642770000000001 milliseconds.
Found 50847534 primes up to 1000000000 in 6034.328751 milliseconds.</pre>
as run on an AMD 7840HS CPU at 5.1 GHz.
Note that due to the huge memory array used, when large ranges are selected, the speed is disproportional in speed slow down by about four times.
This solution uses an interator struct which seems to be the Mojo-preferred way to do this, and normally a DynamicVector would have been used the the culling array except that there is a bug in this version of DynamicVector where the array is not properly deep copied when copied to a new location, so the raw pointer type is used.
===Odds-Only with Optimizations===
This version does three significant improvements to the above code as follows:
1) It is trivial to skip the processing to store representations for and cull the even comosite numbers other than the prime number two, saving half the storage space and reducing the culling time to about 40 percent.
2) There is a repeating pattern of culling composite representations over a bit-packed byte array (which reduces the storage requirement by another eight times) that repeats every eight culling operations, which can be encapsulated by a extreme loop unrolling technique with compiler generated constants as done here.
3) Further, there is a further extreme optimization technique of dense culling for small base prime values whose culling span is less than one register in size where the loaded register is repeatedly culled for different base prime strides before being written out (with such optimization done by the compiler), again using compiler generated modification constants. This technique is usually further optimizated by modern compilers to use efficient autovectorization and the use of SIMD registers available to the architecture to reduce these culling operations to an avererage of a tiny fraction of a CPU clock cycle per cull.
Mojo version 0.7 was tested:
<syntaxhighlight lang="mojo">from memory import (memset_zero, memcpy)
from memory.unsafe import (DTypePointer)
from math.bit import ctpop
from time import (now)
alias cLIMIT: Int = 1_000_000_000
alias cBufferSize: Int = 262144 # bytes
alias cBufferBits: Int = cBufferSize * 8
alias UnrollFunc = fn(DTypePointer[DType.uint8], Int, Int, Int) -> None
@always_inline
fn extreme[OFST: Int, BP: Int](pcmps: DTypePointer[DType.uint8], bufsz: Int, s: Int, bp: Int):
var cp = pcmps + (s >> 3)
let r1: Int = ((s + bp) >> 3) - (s >> 3)
let r2: Int = ((s + 2 * bp) >> 3) - (s >> 3)
let r3: Int = ((s + 3 * bp) >> 3) - (s >> 3)
let r4: Int = ((s + 4 * bp) >> 3) - (s >> 3)
let r5: Int = ((s + 5 * bp) >> 3) - (s >> 3)
let r6: Int = ((s + 6 * bp) >> 3) - (s >> 3)
let r7: Int = ((s + 7 * bp) >> 3) - (s >> 3)
let plmt: DTypePointer[DType.uint8] = pcmps + bufsz - r7
while cp < plmt:
cp.store(cp.load() | (1 << OFST))
(cp + r1).store((cp + r1).load() | (1 << ((OFST + BP) & 7)))
(cp + r2).store((cp + r2).load() | (1 << ((OFST + 2 * BP) & 7)))
(cp + r3).store((cp + r3).load() | (1 << ((OFST + 3 * BP) & 7)))
(cp + r4).store((cp + r4).load() | (1 << ((OFST + 4 * BP) & 7)))
(cp + r5).store((cp + r5).load() | (1 << ((OFST + 5 * BP) & 7)))
(cp + r6).store((cp + r6).load() | (1 << ((OFST + 6 * BP) & 7)))
(cp + r7).store((cp + r7).load() | (1 << ((OFST + 7 * BP) & 7)))
cp += bp
let eplmt: DTypePointer[DType.uint8] = plmt + r7
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << OFST))
cp += r1
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + BP) & 7)))
cp += r2 - r1
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 2 * BP) & 7)))
cp += r3 - r2
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 3 * BP) & 7)))
cp += r4 - r3
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 4 * BP) & 7)))
cp += r5 - r4
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 5 * BP) & 7)))
cp += r6 - r5
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 6 * BP) & 7)))
cp += r7 - r6
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 7 * BP) & 7)))
fn mkExtrm[CNT: Int](pntr: Pointer[UnrollFunc]):
@parameter
if CNT >= 32:
return
alias OFST = CNT >> 2
alias BP = ((CNT & 3) << 1) + 1
pntr.offset(CNT).store(extreme[OFST, BP])
mkExtrm[CNT + 1](pntr)
@always_inline
fn mkExtremeFuncs() -> Pointer[UnrollFunc]:
let jmptbl: Pointer[UnrollFunc] = Pointer[UnrollFunc].alloc(32)
mkExtrm[0](jmptbl)
return jmptbl
let extremeFuncs = mkExtremeFuncs()
alias DenseFunc = fn(DTypePointer[DType.uint64], Int, Int) -> DTypePointer[DType.uint64]
fn mkDenseCull[N: Int, BP: Int](cp: DTypePointer[DType.uint64]):
@parameter
if N >= 64:
return
alias MUL = N * BP
var cop = cp.offset(MUL >> 6)
cop.store(cop.load() | (1 << (MUL & 63)))
mkDenseCull[N + 1, BP](cp)
@always_inline
fn denseCullFunc[BP: Int](pcmps: DTypePointer[DType.uint64], bufsz: Int, s: Int) -> DTypePointer[DType.uint64]:
var cp: DTypePointer[DType.uint64] = pcmps + (s >> 6)
let plmt = pcmps + (bufsz >> 3) - BP
while cp < plmt:
mkDenseCull[0, BP](cp)
cp += BP
return cp
fn mkDenseFunc[CNT: Int](pntr: Pointer[DenseFunc]):
@parameter
if CNT >= 64:
return
alias BP = (CNT << 1) + 3
pntr.offset(CNT).store(denseCullFunc[BP])
mkDenseFunc[CNT + 1](pntr)
@always_inline
fn mkDenseFuncs() -> Pointer[DenseFunc]:
let jmptbl : Pointer[DenseFunc] = Pointer[DenseFunc].alloc(64)
mkDenseFunc[0](jmptbl)
return jmptbl
let denseFuncs : Pointer[DenseFunc] = mkDenseFuncs()
@always_inline
fn cullPass(cmpsts: DTypePointer[DType.uint8], bytesz: Int, s: Int, bp: Int):
if bp <= 129: # dense culling
var sm = s
while (sm >> 3) < bytesz and (sm & 63) != 0:
cmpsts[sm >> 3] |= (1 << (sm & 7))
sm += bp
let bcp = denseFuncs[(bp - 3) >> 1](cmpsts.bitcast[DType.uint64](), bytesz, sm)
var ns = 0
var ncp = bcp
let cmpstslmtp = (cmpsts + bytesz).bitcast[DType.uint64]()
while ncp < cmpstslmtp:
ncp[0] |= (1 << (ns & 63))
ns += bp
ncp = bcp + (ns >> 6)
else: # extreme loop unrolling culling
extremeFuncs[((s & 7) << 2) + ((bp & 7) >> 1)](cmpsts, bytesz, s, bp)
# for c in range(s, self.len, bp): # slow bit twiddling way
# self.cmpsts[c >> 3] |= (1 << (c & 7))
fn countPagePrimes(ptr: DTypePointer[DType.uint8], bitsz: Int) -> Int:
let wordsz: Int = (bitsz + 63) // 64 # round up to nearest 64 bit boundary
var rslt: Int = wordsz * 64
let bigcmps = ptr.bitcast[DType.uint64]()
for i in range(wordsz - 1):
rslt -= ctpop(bigcmps[i]).to_int()
rslt -= ctpop(bigcmps[wordsz - 1] | (-2 << ((bitsz - 1) & 63))).to_int()
return rslt
struct SoEOdds(Sized):
var len: Int
var cmpsts: DTypePointer[DType.uint8] # because DynamicVector has deep copy bug in Mojo version 0.7
var sz: Int
var ndx: Int
fn __init__(inout self, limit: Int):
self.len = 0 if limit < 2 else (limit - 3) // 2 + 1
self.sz = 0 if limit < 2 else self.len + 1 # for the unprocessed only even prime of two
self.ndx = -1
let bytesz = 0 if limit < 2 else ((self.len + 63) & -64) >> 3 # round up to nearest 64 bit boundary
self.cmpsts = DTypePointer[DType.uint8].alloc(bytesz)
memset_zero(self.cmpsts, bytesz)
for i in range(self.len):
let s = (i + i) * (i + 3) + 3
if s >= self.len: break
if (self.cmpsts[i >> 3] >> (i & 7)) & 1 != 0: continue
let bp = i + i + 3
cullPass(self.cmpsts, bytesz, s, bp)
self.sz = countPagePrimes(self.cmpsts, self.len) + 1 # add one for only even prime of two
fn __del__(owned self):
self.cmpsts.free()
fn __copyinit__(inout self, existing: Self):
self.len = existing.len
let bytesz = (self.len + 7) // 8
self.cmpsts = DTypePointer[DType.uint8].alloc(bytesz)
memcpy(self.cmpsts, existing.cmpsts, bytesz)
self.sz = existing.sz
self.ndx = existing.ndx
fn __moveinit__(inout self, owned existing: Self):
self.len = existing.len
self.cmpsts = existing.cmpsts
self.sz = existing.sz
self.ndx = existing.ndx
fn __len__(self: Self) -> Int: return self.sz
fn __iter__(self: Self) -> Self: return self
@always_inline
fn __next__(inout self: Self) -> Int:
if self.ndx < 0:
self.ndx = 0; self.sz -= 1; return 2
while (self.ndx < self.len) and ((self.cmpsts[self.ndx >> 3] >> (self.ndx & 7)) & 1 != 0):
self.ndx += 1
let rslt = (self.ndx << 1) + 3; self.sz -= 1; self.ndx += 1; return rslt
fn main():
print("The primes to 100 are:")
for prm in SoEOdds(100): print_no_newline(prm, " ")
print()
let strt0 = now()
let answr0 = len(SoEOdds(1_000_000))
let elpsd0 = (now() - strt0) / 1000000
print("Found", answr0, "primes up to 1,000,000 in", elpsd0, "milliseconds.")
let strt1 = now()
let answr1 = len(SoEOdds(cLIMIT))
let elpsd1 = (now() - strt1) / 1000000
print("Found", answr1, "primes up to", cLIMIT, "in", elpsd1, "milliseconds.")</syntaxhighlight>
{{out}}
<pre>The primes to 100 are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Found 78498 primes up to 1,000,000 in 0.085067000000000004 milliseconds.
Found 50847534 primes up to 1000000000 in 1204.866606 milliseconds.</pre>
This was run on the same computer as the above example; notice that while this is much faster than that version, it is still very slow as the sieving range gets large such that the relative processing time for a range that is 1000 times as large is about ten times slower than as might be expected by simple scaling. This is due to the "one huge sieving buffer" algorithm that gets very large with increasing range (and in fact will eventually limit the sieving range that can be used) to exceed the size of CPU cache buffers and thus greatly slow average memory access times.
===Page-Segmented Odds-Only with Optimizations===
While the above version performs reasonably well for small sieving ranges that fit within the CPU caches of a few tens of millions, as one can see it gets much slower with larger ranges and as well its huge RAM memory consumption limits the maximum range over which it can be used. This version solves these problems be breaking the huge sieving array into "pages" that each fit within the CPU cache size and processing each "page" sequentially until the target range is reached. This technique also greatly reduces memory requirements to only that required to store the base prime value representations up to the square root of the range limit (about O(n/log n) storage plus a fixed size page buffer. In this case, the storage for the base primes has been reduced by a constant factor by storing them as single byte deltas from the previous value, which works for ranges up to the 64-bit number range where the biggest gap is two times 192 and since we store only for odd base primes, the gap values are all half values to fit in a single byte.
Currently, Mojo has problems with some functions in the standard libraries such as the integer square root function is not accurate nor does it work for the required integer types so a custom integer square root function is supplied. As well, current Mojo does not support recursion for hardly any useful cases (other than compile time global function recursion), so the `SoeOdds` structure from the previous answer had to be kept to generate the base prime representation table (or this would have had to be generated from scratch within the new `SoEOddsPaged` structure). Finally, it didn't seem to be worth using the `Sized` trait for the new structure as this would seem to sometimes require processing the pages twice, one to obtain the size and once if iteration across the prime values is required.
Tested with Mojo version 0.7:
<syntaxhighlight lang="mojo">from memory import (memset_zero, memcpy)
from memory.unsafe import (DTypePointer)
from math.bit import ctpop
from time import (now)
alias cLIMIT: Int = 1_000_000_000
alias cBufferSize: Int = 262144 # bytes
alias cBufferBits: Int = cBufferSize * 8
fn intsqrt(n: UInt64) -> UInt64:
if n < 4:
if n < 1: return 0 else: return 1
var x: UInt64 = n; var qn: UInt64 = 0; var r: UInt64 = 0
while qn < 64 and (1 << qn) <= n:
qn += 2
var q: UInt64 = 1 << qn
while q > 1:
if qn >= 64:
q = 1 << (qn - 2); qn = 0
else:
q >>= 2
let t: UInt64 = r + q
r >>= 1
if x >= t:
x -= t; r += q
return r
alias UnrollFunc = fn(DTypePointer[DType.uint8], Int, Int, Int) -> None
@always_inline
fn extreme[OFST: Int, BP: Int](pcmps: DTypePointer[DType.uint8], bufsz: Int, s: Int, bp: Int):
var cp = pcmps + (s >> 3)
let r1: Int = ((s + bp) >> 3) - (s >> 3)
let r2: Int = ((s + 2 * bp) >> 3) - (s >> 3)
let r3: Int = ((s + 3 * bp) >> 3) - (s >> 3)
let r4: Int = ((s + 4 * bp) >> 3) - (s >> 3)
let r5: Int = ((s + 5 * bp) >> 3) - (s >> 3)
let r6: Int = ((s + 6 * bp) >> 3) - (s >> 3)
let r7: Int = ((s + 7 * bp) >> 3) - (s >> 3)
let plmt: DTypePointer[DType.uint8] = pcmps + bufsz - r7
while cp < plmt:
cp.store(cp.load() | (1 << OFST))
(cp + r1).store((cp + r1).load() | (1 << ((OFST + BP) & 7)))
(cp + r2).store((cp + r2).load() | (1 << ((OFST + 2 * BP) & 7)))
(cp + r3).store((cp + r3).load() | (1 << ((OFST + 3 * BP) & 7)))
(cp + r4).store((cp + r4).load() | (1 << ((OFST + 4 * BP) & 7)))
(cp + r5).store((cp + r5).load() | (1 << ((OFST + 5 * BP) & 7)))
(cp + r6).store((cp + r6).load() | (1 << ((OFST + 6 * BP) & 7)))
(cp + r7).store((cp + r7).load() | (1 << ((OFST + 7 * BP) & 7)))
cp += bp
let eplmt: DTypePointer[DType.uint8] = plmt + r7
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << OFST))
cp += r1
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + BP) & 7)))
cp += r2 - r1
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 2 * BP) & 7)))
cp += r3 - r2
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 3 * BP) & 7)))
cp += r4 - r3
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 4 * BP) & 7)))
cp += r5 - r4
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 5 * BP) & 7)))
cp += r6 - r5
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 6 * BP) & 7)))
cp += r7 - r6
if eplmt == cp or eplmt < cp: return
cp.store(cp.load() | (1 << ((OFST + 7 * BP) & 7)))
fn mkExtrm[CNT: Int](pntr: Pointer[UnrollFunc]):
@parameter
if CNT >= 32:
return
alias OFST = CNT >> 2
alias BP = ((CNT & 3) << 1) + 1
pntr.offset(CNT).store(extreme[OFST, BP])
mkExtrm[CNT + 1](pntr)
@always_inline
fn mkExtremeFuncs() -> Pointer[UnrollFunc]:
let jmptbl: Pointer[UnrollFunc] = Pointer[UnrollFunc].alloc(32)
mkExtrm[0](jmptbl)
return jmptbl
let extremeFuncs = mkExtremeFuncs()
alias DenseFunc = fn(DTypePointer[DType.uint64], Int, Int) -> DTypePointer[DType.uint64]
fn mkDenseCull[N: Int, BP: Int](cp: DTypePointer[DType.uint64]):
@parameter
if N >= 64:
return
alias MUL = N * BP
var cop = cp.offset(MUL >> 6)
cop.store(cop.load() | (1 << (MUL & 63)))
mkDenseCull[N + 1, BP](cp)
@always_inline
fn denseCullFunc[BP: Int](pcmps: DTypePointer[DType.uint64], bufsz: Int, s: Int) -> DTypePointer[DType.uint64]:
var cp: DTypePointer[DType.uint64] = pcmps + (s >> 6)
let plmt = pcmps + (bufsz >> 3) - BP
while cp < plmt:
mkDenseCull[0, BP](cp)
cp += BP
return cp
fn mkDenseFunc[CNT: Int](pntr: Pointer[DenseFunc]):
@parameter
if CNT >= 64:
return
alias BP = (CNT << 1) + 3
pntr.offset(CNT).store(denseCullFunc[BP])
mkDenseFunc[CNT + 1](pntr)
@always_inline
fn mkDenseFuncs() -> Pointer[DenseFunc]:
let jmptbl : Pointer[DenseFunc] = Pointer[DenseFunc].alloc(64)
mkDenseFunc[0](jmptbl)
return jmptbl
let denseFuncs : Pointer[DenseFunc] = mkDenseFuncs()
@always_inline
fn cullPass(cmpsts: DTypePointer[DType.uint8], bytesz: Int, s: Int, bp: Int):
if bp <= 129: # dense culling
var sm = s
while (sm >> 3) < bytesz and (sm & 63) != 0:
cmpsts[sm >> 3] |= (1 << (sm & 7))
sm += bp
let bcp = denseFuncs[(bp - 3) >> 1](cmpsts.bitcast[DType.uint64](), bytesz, sm)
var ns = 0
var ncp = bcp
let cmpstslmtp = (cmpsts + bytesz).bitcast[DType.uint64]()
while ncp < cmpstslmtp:
ncp[0] |= (1 << (ns & 63))
ns += bp
ncp = bcp + (ns >> 6)
else: # extreme loop unrolling culling
extremeFuncs[((s & 7) << 2) + ((bp & 7) >> 1)](cmpsts, bytesz, s, bp)
# for c in range(s, self.len, bp): # slow bit twiddling way
# self.cmpsts[c >> 3] |= (1 << (c & 7))
fn cullPage(lwi: Int, lmt: Int, cmpsts: DTypePointer[DType.uint8], bsprmrps: DTypePointer[DType.uint8]):
var bp = 1; var ndx = 0
while True:
bp += bsprmrps[ndx].to_int() << 1
let i = (bp - 3) >> 1
var s = (i + i) * (i + 3) + 3
if s >= lmt: break
if s >= lwi: s -= lwi
else:
s = (lwi - s) % bp
if s != 0: s = bp - s
cullPass(cmpsts, cBufferSize, s, bp)
ndx += 1
fn countPagePrimes(ptr: DTypePointer[DType.uint8], bitsz: Int) -> Int:
let wordsz: Int = (bitsz + 63) // 64 # round up to nearest 64 bit boundary
var rslt: Int = wordsz * 64
let bigcmps = ptr.bitcast[DType.uint64]()
for i in range(wordsz - 1):
rslt -= ctpop(bigcmps[i]).to_int()
rslt -= ctpop(bigcmps[wordsz - 1] | (-2 << ((bitsz - 1) & 63))).to_int()
return rslt
struct SoEOdds(Sized):
var len: Int
var cmpsts: DTypePointer[DType.uint8] # because DynamicVector has deep copy bug in Mojo version 0.7
var sz: Int
var ndx: Int
fn __init__(inout self, limit: Int):
self.len = 0 if limit < 2 else (limit - 3) // 2 + 1
self.sz = 0 if limit < 2 else self.len + 1 # for the unprocessed only even prime of two
self.ndx = -1
let bytesz = 0 if limit < 2 else ((self.len + 63) & -64) >> 3 # round up to nearest 64 bit boundary
self.cmpsts = DTypePointer[DType.uint8].alloc(bytesz)
memset_zero(self.cmpsts, bytesz)
for i in range(self.len):
let s = (i + i) * (i + 3) + 3
if s >= self.len: break
if (self.cmpsts[i >> 3] >> (i & 7)) & 1 != 0: continue
let bp = i + i + 3
cullPass(self.cmpsts, bytesz, s, bp)
self.sz = countPagePrimes(self.cmpsts, self.len) + 1 # add one for only even prime of two
fn __del__(owned self):
self.cmpsts.free()
fn __copyinit__(inout self, existing: Self):
self.len = existing.len
let bytesz = (self.len + 7) // 8
self.cmpsts = DTypePointer[DType.uint8].alloc(bytesz)
memcpy(self.cmpsts, existing.cmpsts, bytesz)
self.sz = existing.sz
self.ndx = existing.ndx
fn __moveinit__(inout self, owned existing: Self):
self.len = existing.len
self.cmpsts = existing.cmpsts
self.sz = existing.sz
self.ndx = existing.ndx
fn __len__(self: Self) -> Int: return self.sz
fn __iter__(self: Self) -> Self: return self
@always_inline
fn __next__(inout self: Self) -> Int:
if self.ndx < 0:
self.ndx = 0; self.sz -= 1; return 2
while (self.ndx < self.len) and ((self.cmpsts[self.ndx >> 3] >> (self.ndx & 7)) & 1 != 0):
self.ndx += 1
let rslt = (self.ndx << 1) + 3; self.sz -= 1; self.ndx += 1; return rslt
struct SoEOddsPaged:
var len: Int
var cmpsts: DTypePointer[DType.uint8] # because DynamicVector has deep copy bug in Mojo version 0.7
var sz: Int # 0 means finished; otherwise contains number of odd base primes
var ndx: Int
var lwi: Int
var bsprmrps: DTypePointer[DType.uint8] # contains deltas between odd base primes starting from zero
fn __init__(inout self, limit: UInt64):
self.len = 0 if limit < 2 else ((limit - 3) // 2 + 1).to_int()
self.sz = 0 if limit < 2 else 1 # means iterate until this is set to zero
self.ndx = -1 # for unprocessed only even prime of two
self.lwi = 0
if self.len < cBufferBits:
let bytesz = ((self.len + 63) & -64) >> 3 # round up to nearest 64 bit boundary
self.cmpsts = DTypePointer[DType.uint8].alloc(bytesz)
self.bsprmrps = DTypePointer[DType.uint8].alloc(self.sz)
else:
self.cmpsts = DTypePointer[DType.uint8].alloc(cBufferSize)
let bsprmitr = SoEOdds(intsqrt(limit).to_int())
self.sz = len(bsprmitr)
self.bsprmrps = DTypePointer[DType.uint8].alloc(self.sz)
var ndx = -1; var oldbp = 1
for bsprm in bsprmitr:
if ndx < 0: ndx += 1; continue # skip over the 2 prime
self.bsprmrps[ndx] = (bsprm - oldbp) >> 1
oldbp = bsprm; ndx += 1
self.bsprmrps[ndx] = 255 # one extra value to go beyond the necessary cull space
fn __del__(owned self):
self.cmpsts.free(); self.bsprmrps.free()
fn __copyinit__(inout self, existing: Self):
self.len = existing.len
self.sz = existing.sz
let bytesz = cBufferSize if self.len >= cBufferBits
else ((self.len + 63) & -64) >> 3 # round up to nearest 64 bit boundary
self.cmpsts = DTypePointer[DType.uint8].alloc(bytesz)
memcpy(self.cmpsts, existing.cmpsts, bytesz)
self.ndx = existing.ndx
self.lwi = existing.lwi
self.bsprmrps = DTypePointer[DType.uint8].alloc(self.sz)
memcpy(self.bsprmrps, existing.bsprmrps, self.sz)
fn __moveinit__(inout self, owned existing: Self):
self.len = existing.len
self.cmpsts = existing.cmpsts
self.sz = existing.sz
self.ndx = existing.ndx
self.lwi = existing.lwi
self.bsprmrps = existing.bsprmrps
fn countPrimes(self) -> Int:
if self.len <= cBufferBits: return len(SoEOdds(2 * self.len + 1))
var cnt = 1; var lwi = 0
let cmpsts = DTypePointer[DType.uint8].alloc(cBufferSize)
memset_zero(cmpsts, cBufferSize)
cullPage(0, cBufferBits, cmpsts, self.bsprmrps)
while lwi + cBufferBits <= self.len:
cnt += countPagePrimes(cmpsts, cBufferBits)
lwi += cBufferBits
memset_zero(cmpsts, cBufferSize)
let lmt = lwi + cBufferBits if lwi + cBufferBits <= self.len else self.len
cullPage(lwi, lmt, cmpsts, self.bsprmrps)
cnt += countPagePrimes(cmpsts, self.len - lwi)
return cnt
fn __len__(self: Self) -> Int: return self.sz
fn __iter__(self: Self) -> Self: return self
@always_inline
fn __next__(inout self: Self) -> Int: # don't count number of primes by interating - slooow
if self.ndx < 0:
self.ndx = 0; self.lwi = 0
if self.len < 2: self.sz = 0
elif self.len <= cBufferBits:
let bytesz = ((self.len + 63) & -64) >> 3 # round up to nearest 64 bit boundary
memset_zero(self.cmpsts, bytesz)
for i in range(self.len):
let s = (i + i) * (i + 3) + 3
if s >= self.len: break
if (self.cmpsts[i >> 3] >> (i & 7)) & 1 != 0: continue
let bp = i + i + 3
cullPass(self.cmpsts, bytesz, s, bp)
else:
memset_zero(self.cmpsts, cBufferSize)
cullPage(0, cBufferBits, self.cmpsts, self.bsprmrps)
return 2
let rslt = ((self.lwi + self.ndx) << 1) + 3; self.ndx += 1
if self.lwi + cBufferBits >= self.len:
while (self.lwi + self.ndx < self.len) and ((self.cmpsts[self.ndx >> 3] >> (self.ndx & 7)) & 1 != 0):
self.ndx += 1
else:
while (self.ndx < cBufferBits) and ((self.cmpsts[self.ndx >> 3] >> (self.ndx & 7)) & 1 != 0):
self.ndx += 1
while (self.ndx >= cBufferBits) and (self.lwi + cBufferBits <= self.len):
self.ndx = 0; self.lwi += cBufferBits; memset_zero(self.cmpsts, cBufferSize)
let lmt = self.lwi + cBufferBits if self.lwi + cBufferBits <= self.len else self.len
cullPage(self.lwi, lmt, self.cmpsts, self.bsprmrps)
let buflmt = cBufferBits if self.lwi + cBufferBits <= self.len else self.len - self.lwi
while (self.ndx < buflmt) and ((self.cmpsts[self.ndx >> 3] >> (self.ndx & 7)) & 1 != 0):
self.ndx += 1
if self.lwi + self.ndx >= self.len: self.sz = 0
return rslt
fn main():
print("The primes to 100 are:")
for prm in SoEOddsPaged(100): print_no_newline(prm, " ")
print()
let strt0 = now()
let answr0 = SoEOddsPaged(1_000_000).countPrimes()
let elpsd0 = (now() - strt0) / 1000000
print("Found", answr0, "primes up to 1,000,000 in", elpsd0, "milliseconds.")
let strt1 = now()
let answr1 = SoEOddsPaged(cLIMIT).countPrimes()
let elpsd1 = (now() - strt1) / 1000000
print("Found", answr1, "primes up to", cLIMIT, "in", elpsd1, "milliseconds.")</syntaxhighlight>
{{out}}
<pre>The primes to 100 are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Found 78498 primes up to 1,000,000 in 0.084122000000000002 milliseconds.
Found 50847534 primes up to 1000000000 in 139.509275 milliseconds.</pre>
This was tested on the same computer as the previous Mojo versions. Note that the time now scales quite well with range since there are no longer the huge RAM access time bottleneck's. This version is only about 2.25 times slower than Kim Walich's primesieve program written in C++ and the mostly constant factor difference will be made up if one adds wheel factorization to the same level as he uses (basic wheel factorization ratio of 48/105 plus some other more minor optimizations). This version can count the number of primes to 1e11 in about 21.85 seconds on this machine. It will work reasonably efficiently up to a range of about 1e14 before other optimization techniques such as "bucket sieving" should be used.
For counting the number of primes to a billion (1e9), this version has reduced the time by about a factor of 40 from the original version and over eight times from the odds-only version above. Adding wheel factorization will make it almost two and a half times faster yet for a gain in speed of about a hundred times over the original version.
=={{header|MUMPS}}==
<
;performs the Sieve of Erotosethenes up to the number passed in.
;This version sets an array containing the primes
Line 11,435 ⟶ 13,321:
FOR I=2:1:HI S:'$DATA(P(I)) ERATO1(I)=I
KILL I,J,P
QUIT</
Example:
<pre>USER>SET MAX=100,C=0 DO ERATO1^ROSETTA(MAX)
Line 11,444 ⟶ 13,330:
=={{header|Neko}}==
<
http://shootout.alioth.debian.org/
Line 11,479 ⟶ 13,365:
nsieve(10000 << (n - i));
i += 1;
}</
{{out}}
Line 11,494 ⟶ 13,380:
=={{header|NetRexx}}==
===Version 1 (slow)===
<
options replace format comments java crossref savelog symbols binary
Line 11,550 ⟶ 13,436:
method isFalse public constant binary returns boolean
return \isTrue
</syntaxhighlight>
;Output
<pre style="overflow:scroll">
Line 11,558 ⟶ 13,444:
</pre>
===Version 2 (significantly, i.e. 10 times faster)===
<
* Essential improvements:Use boolean instead of Rexx for sv
* and remove methods isTrue and isFalse
Line 11,624 ⟶ 13,510:
end p_
return primes</
=={{header|newLISP}}==
Line 11,632 ⟶ 13,518:
Note that the lambda expression in the following script does not involve a closure; newLISP has dynamic scope, so it matters that the same variable names will not be reused for some other purpose (at runtime) before the anonymous function is called.
<
; The initial sieve is a list of all the numbers starting at 2.
Line 11,651 ⟶ 13,537:
sieve)))
(exit)</
{{output}}
Line 11,832 ⟶ 13,718:
=={{header|Nim}}==
<
iterator primesUpto(limit: int): int =
Line 11,853 ⟶ 13,739:
for p in primesUpto(1000000):
count += 1
echo "There are ", count, " primes up to 1000000."</
{{out}}
<pre>Primes are:
Line 11,863 ⟶ 13,749:
The above version wastes quite a lot of memory by using a sequence of boolean values to sieve the composite numbers and sieving all numbers when two is the only even prime. The below code uses a bit-packed sequence to save a factor of eight in memory and also sieves only odd primes for another memory saving by a factor of two; it is also over two and a half times faster due to reduced number of culling operations and better use of the CPU cache as a little cache goes a lot further - this better use of cache is more than enough to make up for the extra bit-packing shifting operations:
<
let topndx = int((top - 3) div 2)
let sqrtndx = (int(sqrt float64(top)) - 3) div 2
Line 11,875 ⟶ 13,761:
for i in 0 .. topndx:
if (cmpsts[i shr 5] and (1u32 shl (i and 31))) == 0:
yield uint(i + i + 3)</
The above code can be used with the same output functions as in the first code, just replacing the name of the iterator "iprimes_upto" with this iterator's name "isoe_upto" in two places. The output will be identical.
Line 11,882 ⟶ 13,768:
For many purposes, one doesn't know the exact upper limit desired to easily use the above versions; in addition, those versions use an amount of memory proportional to the range sieved. In contrast, unbounded versions continuously update their range as they progress and only use memory proportional to the secondary base primes stream, which is only proportional to the square root of the range. One of the most basic functional versions is the TreeFolding sieve which is based on merging lazy streams as per Richard Bird's contribution to incremental sieves in Haskell, but which has a much better asymptotic execution complexity due to the added tree folding. The following code is a version of that in Nim (odds-only):
<
from times import epochTime
Line 11,963 ⟶ 13,849:
let elapsed = epochTime() - start
echo "There are ", counter, " primes up to 1000000."
echo "This test took ", elapsed, " seconds."</
{{output}}
<pre>The first 25 primes are: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Line 11,976 ⟶ 13,862:
To show the cost of functional forms of code, the following code is written embracing mutability, both by using a mutable hash table to store the state of incremental culling by the secondary stream of base primes and by using mutable values to store the state wherever possible, as per the following code:
<
type PrimeType = int
Line 12,025 ⟶ 13,911:
let elapsed = epochTime() - start
echo "The number of primes up to a million is: ", counter
stdout.write("This test took ", elapsed, " seconds.\n")</
{{out}}
Line 12,040 ⟶ 13,926:
For the highest speeds, one needs to use page segmented mutable arrays as in the bit-packed version here:
<
from times import epochTime # for testing
Line 12,210 ⟶ 14,096:
let elpsd = epochTime() - start
echo "Found ", counter, " primes up to ", LIMIT, " in ", elpsd, " seconds."</
{{output}}
Time is obtained with Nim 1.4 with options <code>-d:danger --gc:arc</code>.
Line 12,228 ⟶ 14,114:
=={{header|Niue}}==
{{incorrect|Niue|It uses rem testing and so is a trial division algorithm, not a sieve of Eratosthenes.}}
<
[ 1 + 'count ; [ <2 [ , ] when ] count times ] 'fill-stack ;
Line 12,248 ⟶ 14,134:
10 sieve .s ( => 2 3 5 7 9 ) reset newline
30 sieve .s ( => 2 3 5 7 11 13 17 19 23 29 ) </
=={{header|Oberon-2}}==
<
IMPORT Out, Math;
Line 12,284 ⟶ 14,170:
END;
Out.Ln;
END Primes.</
=={{header|OCaml}}==
===Imperative===
<
let is_prime = Array.create n true in
let limit = truncate(sqrt (float (n - 1))) in
Line 12,301 ⟶ 14,187:
is_prime.(0) <- false;
is_prime.(1) <- false;
is_prime</
<
let primes, _ =
let sieve = sieve n in
Line 12,311 ⟶ 14,197:
([], Array.length sieve - 1)
in
primes</
in the top-level:
Line 12,320 ⟶ 14,206:
===Functional===
<
let fold_iter f init a b =
let rec aux acc i =
Line 12,362 ⟶ 14,248:
li 2 (pred limit)
(* val primes : int -> int list *)
</syntaxhighlight>
in the top-level:
<
- : int list =
[2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59; 61; 67; 71;
73; 79; 83; 89; 97; 101; 103; 107; 109; 113; 127; 131; 137; 139; 149; 151;
157; 163; 167; 173; 179; 181; 191; 193; 197; 199]</
=== Another functional version ===
Line 12,374 ⟶ 14,260:
This uses zero to denote struck-out numbers. It is slightly inefficient as it strikes-out multiples above p rather than p<sup>2</sup>
<
| [] -> []
| h :: t ->
Line 12,392 ⟶ 14,278:
(* val primes : int -> int list *)
</syntaxhighlight>
in the top-level:
<
- : int list =
[2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59; 61; 67; 71;
73; 79; 83; 89; 97; 101; 103; 107; 109; 113; 127; 131; 137; 139; 149; 151;
157; 163; 167; 173; 179; 181; 191; 193; 197; 199]</
=={{header|Oforth}}==
<
| i j |
ListBuffer newSize(n) dup add(null) seqFrom(2, n) over addAll
Line 12,408 ⟶ 14,294:
dup at(i) ifNotNull: [ i sq n i step: j [ dup put(j, null) ] ]
]
filter(#notNull) ;</
{{out}}
Line 12,417 ⟶ 14,303:
=={{header|Ol}}==
<
(define all (iota 999 2))
Line 12,434 ⟶ 14,320:
(loop (cons (car r) l) (cdr r) (+ n 1) every)))))))
)
</syntaxhighlight>
Output:
<pre>
(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997)
</pre>
=={{header|ooRexx}}==
<syntaxhighlight lang="oorexx">
/*ooRexx program generates & displays primes via the sieve of Eratosthenes.
* derived from first Rexx version
* uses an array rather than a stem for the list
* uses string methods rather than BIFs
* uses new ooRexx keyword LOOP, extended assignment
* and line comments
* uses meaningful variable names and restructures code
* layout for improved understandability
****************************************************************************/
arg highest --get highest number to use.
if \highest~datatype('W') then
highest = 200 --use default value.
isPrime = .array~new(highest) --container for all numbers.
isPrime~fill(1) --assume all numbers are prime.
w = highest~length --width of the biggest number,
-- it's used for aligned output.
out1 = 'prime'~right(20) --first part of output messages.
np = 0 --no primes so far.
loop j = 2 for highest - 1 --all numbers up through highest.
if isPrime[j] = 1 then do --found one.
np += 1 --bump the prime counter.
say out1 np~right(w) ' --> ' j~right(w) --display output.
loop m = j * j to highest by j
isPrime[m] = '' --strike all multiples: not prime.
end
end
end
say
say np~right(out1~length + 1 + w) 'primes found up to and including ' highest
exit
</syntaxhighlight>
{{out}}
<pre>
prime 1 --> 2
prime 2 --> 3
prime 3 --> 5
prime 4 --> 7
prime 5 --> 11
prime 6 --> 13
prime 7 --> 17
prime 8 --> 19
prime 9 --> 23
prime 10 --> 29
prime 11 --> 31
prime 12 --> 37
prime 13 --> 41
prime 14 --> 43
prime 15 --> 47
prime 16 --> 53
prime 17 --> 59
prime 18 --> 61
prime 19 --> 67
prime 20 --> 71
prime 21 --> 73
prime 22 --> 79
prime 23 --> 83
prime 24 --> 89
prime 25 --> 97
prime 26 --> 101
prime 27 --> 103
prime 28 --> 107
prime 29 --> 109
prime 30 --> 113
prime 31 --> 127
prime 32 --> 131
prime 33 --> 137
prime 34 --> 139
prime 35 --> 149
prime 36 --> 151
prime 37 --> 157
prime 38 --> 163
prime 39 --> 167
prime 40 --> 173
prime 41 --> 179
prime 42 --> 181
prime 43 --> 191
prime 44 --> 193
prime 45 --> 197
prime 46 --> 199
46 primes found up to and including 200
</pre>
===Wheel Version===
<syntaxhighlight lang="oorexx">
/*ooRexx program generates primes via sieve of Eratosthenes algorithm.
* wheel version, 2 handled as special case
* loops optimized: outer loop stops at the square root of
* the limit, inner loop starts at the square of the
* prime just found
* use a list rather than an array and remove composites
* rather than just mark them
* convert list of primes to a list of output messages and
* display them with one say statement
*******************************************************************************/
arg highest -- get highest number to use.
if \highest~datatype('W') then
highest = 200 -- use default value.
w = highest~length -- width of the biggest number,
-- it's used for aligned output.
thePrimes = .list~of(2) -- the first prime is 2.
loop j = 3 to highest by 2 -- populate the list with odd nums.
thePrimes~append(j)
end
j = 3 -- first prime (other than 2)
ix = thePrimes~index(j) -- get the index of 3 in the list.
loop while j*j <= highest -- strike multiples of odd ints.
-- up to sqrt(highest).
loop jm = j*j to highest by j+j -- start at J squared, incr. by 2*J.
thePrimes~removeItem(jm) -- delete it since it's composite.
end
ix = thePrimes~next(ix) -- the index of the next prime.
j = thePrimes[ix] -- the next prime.
end
np = thePrimes~items -- the number of primes since the
-- list is now only primes.
out1 = ' prime number' -- first part of output messages.
out2 = ' --> ' -- middle part of output messages.
ix = thePrimes~first
loop n = 1 to np -- change the list of primes
-- to output messages.
thePrimes[ix] = out1 n~right(w) out2 thePrimes[ix]~right(w)
ix = thePrimes~next(ix)
end
last = np~right(out1~length+1+w) 'primes found up to and including ' highest
thePrimes~append(.endofline || last) -- add blank line and summary line.
say thePrimes~makearray~toString -- display the output.
exit
</syntaxhighlight>
{{out}}when using the limit of 100
<pre>
prime number 1 --> 2
prime number 2 --> 3
prime number 3 --> 5
prime number 4 --> 7
prime number 5 --> 11
prime number 6 --> 13
prime number 7 --> 17
prime number 8 --> 19
prime number 9 --> 23
prime number 10 --> 29
prime number 11 --> 31
prime number 12 --> 37
prime number 13 --> 41
prime number 14 --> 43
prime number 15 --> 47
prime number 16 --> 53
prime number 17 --> 59
prime number 18 --> 61
prime number 19 --> 67
prime number 20 --> 71
prime number 21 --> 73
prime number 22 --> 79
prime number 23 --> 83
prime number 24 --> 89
prime number 25 --> 97
25 primes found up to and including 100
</pre>
=={{header|Oz}}==
{{trans|Haskell}}
<
fun {Sieve N}
S = {Array.new 2 N true}
Line 12,466 ⟶ 14,514:
end
in
{Show {Primes 30}}</
=={{header|PARI/GP}}==
<
my(v=Vecsmall(lim\1,unused,1));
forprime(p=2,sqrt(lim),
Line 12,477 ⟶ 14,525:
);
for(i=1,lim,if(v[i],print1(i", ")))
};</
An alternate version:
<
{
v=vector(n,unused,1);
Line 12,488 ⟶ 14,536:
forstep(j=i^2,n,i,v[j]=0)));
for(i=2,n,if(v[i],print1(i",")))
};</
=={{header|Pascal}}==
Note: Some Pascal implementations put quite low limits on the size of a set (e.g. Turbo Pascal doesn't allow more than 256 members). To compile on such an implementation, reduce the constant PrimeLimit accordingly.
<
program primes(output)
Line 12,533 ⟶ 14,581:
end
end.
</syntaxhighlight>
===alternative using wheel ===
Using growing wheel to fill array for sieving for minimal unmark operations.
Sieving only with possible-prime factors.
<
program prim(output);
//Sieve of Erathosthenes with fast elimination of multiples of small primes
Line 12,667 ⟶ 14,715:
inc(prCnt,Ord(primes[i]));
writeln(prCnt,' primes up to ',PrimeLimit);
end.</
output: ( i3 4330 Haswell 3.5 Ghz fpc 2.6.4 -O3 )
Line 12,677 ⟶ 14,725:
</pre>
=={{header|PascalABC.NET}}==
<syntaxhighlight lang="delphi">
function Eratosthenes(N: integer): List<integer>;
type primetype = (nonprime,prime);
begin
var sieve := |nonprime|*2 + |prime|*(N-1);
for var i:=2 to N.Sqrt.Round do
if sieve[i] = prime then
for var j := i*i to N step i do
sieve[j] := nonprime;
Result := new List<integer>;
for var i:=2 to N do
if sieve[i] = prime then
Result.Add(i);
end;
begin
Eratosthenes(1000).Println
end.
</syntaxhighlight>
{{out}}
<pre>
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997
</pre>
=={{header|Perl}}==
Line 12,683 ⟶ 14,757:
===Classic Sieve===
<
my $n = shift;
my @composite;
Line 12,698 ⟶ 14,772:
}
@primes;
}</
===Odds only (faster)===
<
my($n) = @_;
return @{([],[],[2],[2,3],[2,3])[$n]} if $n <= 4;
Line 12,717 ⟶ 14,791:
}
@primes;
}</
===Odds only, using vectors for lower memory use===
<
my($end) = @_;
return @{([],[],[2],[2,3],[2,3])[$end]} if $end <= 4;
Line 12,735 ⟶ 14,809:
do { push @primes, 2*$_+1 if !vec($sieve,$_,1) } for (1..int(($end-1)/2));
@primes;
}</
===Odds only, using strings for best performance===
Compared to array versions, about 2x faster (with 5.16.0 or later) and lower memory. Much faster than the experimental versions below. It's possible a mod-6 or mod-30 wheel could give more improvement, though possibly with obfuscation. The best next step for performance and functionality would be segmenting.
<
my ($n, $i, $s, $d, @primes) = (shift, 7);
Line 12,754 ⟶ 14,828:
push @primes, pos while m/0/g;
@primes;
}</
This older version uses half the memory, but at the expense of a bit of speed and code complexity:
<
my($end) = @_;
return @{([],[],[2],[2,3],[2,3])[$end]} if $end <= 4;
Line 12,778 ⟶ 14,852:
push @primes, 2*pos($sieve)-1 while $sieve =~ m/0/g;
@primes;
}</
===Experimental===
Line 12,784 ⟶ 14,858:
Golfing a bit, at the expense of speed:
<
grep { not $s[ $i = $_ ] and do
{ $s[ $i += $_ ]++ while $i <= $_[0]; 1 }
Line 12,790 ⟶ 14,864:
}
print join ", " => sieve 100;</
Or with bit strings (much slower than the vector version above):
<
grep { not vec $s, $i = $_, 1 and do
{ (vec $s, $i += $_, 1) = 1 while $i <= $_[0]; 1 }
Line 12,799 ⟶ 14,873:
}
print join ", " => sieve 100;</
A short recursive version:
<
my $p = shift;
return $p, $p**2 > $_[$#_] ? @_ : erat(grep $_%$p, @_)
}
print join ', ' => erat 2..100000;</
Regexp (purely an example -- the regex engine limits it to only 32769):<
my ($s, $p) = "." . ("x" x shift);
Line 12,820 ⟶ 14,894:
}
print sieve(1000);</
===Extensible sieves===
Here are two incremental versions, which allows one to create a tied array of primes:
<
use warnings;
package Tie::SieveOfEratosthenes;
Line 12,930 ⟶ 15,004:
}
1;</
This one is based on the vector sieve shown earlier, but adds to a list as needed, just sieving in the segment. Slightly faster and half the memory vs. the previous incremental sieve. It uses the same API -- arguably we should be offset by one so $primes[$n] returns the $n'th prime.
<
use warnings;
package Tie::SieveOfEratosthenes;
Line 12,985 ⟶ 15,059:
}
1;</
=={{header|Phix}}==
{{Trans|Euphoria}}
<!--<
<span style="color: #008080;">constant</span> <span style="color: #000000;">limit</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1000</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">primes</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
Line 13,006 ⟶ 15,080:
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">primes</span><span style="color: #0000FF;">,{</span><span style="color: #004600;">pp_Maxlen</span><span style="color: #0000FF;">,</span><span style="color: #000000;">77</span><span style="color: #0000FF;">})</span>
<!--</
{{out}}
<pre>
Line 13,023 ⟶ 15,097:
=={{header|Phixmonti}}==
<
def sequence /# ( ini end [step] ) #/
Line 13,040 ⟶ 15,114:
endfor
( 1 limit 0 ) remove
pstack</
Another solution
<syntaxhighlight lang="phixmonti">include ..\Utilitys.pmt
1000
( "Primes in " over ": " ) lprint
2 swap 2 tolist for >ps
2
dup tps < while
tps over mod 0 == if false else 1 + true endif
over tps < and
endwhile
tps < ps> swap if drop endif
endfor
pstack</syntaxhighlight>
{{out}}
<pre>Primes in 1000:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
=== Press any key to exit ===</pre>
=={{header|PHP}}==
<
function iprimes_upto($limit)
{
Line 13,070 ⟶ 15,167:
100
);
</syntaxhighlight>
{{out}}
Line 13,084 ⟶ 15,181:
=={{header|Picat}}==
The SoE is provided in the standard library, defined as follows:
<syntaxhighlight lang="picat">
primes(N) = L =>
A = new_array(N),
Line 13,095 ⟶ 15,192:
end,
L=[I : I in 2..N, var(A[I])].
</syntaxhighlight>
{{Out}}
<pre>
Line 13,103 ⟶ 15,200:
</pre>
=={{header|PicoLisp}}==
<
(let Sieve (range 1 N)
(set Sieve)
Line 13,110 ⟶ 15,207:
(for (S (nth Sieve (* I I)) S (nth (cdr S) I))
(set S) ) ) )
(filter bool Sieve) ) )</
Output:
<pre>: (sieve 100)
Line 13,116 ⟶ 15,213:
===Alternate Version Using a 2x3x5x7 Wheel===
This works by destructively modifying the CDR of the previous cell when it finds a composite number. For sieving large sets (e.g. 1,000,000) it's much faster than the above.
<syntaxhighlight lang="picolisp">
(setq WHEEL-2357
(2 4 2 4 6 2 6 4
Line 13,149 ⟶ 15,246:
(remove-multiples P))
(append (2 3 5 7) Sieve)))
</
{{Out}}
<pre>
Line 13,161 ⟶ 15,258:
=={{header|PL/I}}==
<
dcl i fixed bin (31);
Line 13,197 ⟶ 15,294:
end;
end;
end eratos;</
=={{header|PL/M}}==
<
DECLARE PRIME$MAX LITERALLY '5000';
Line 13,260 ⟶ 15,357:
CALL BDOS(BDOS$EXIT, 0);
EOF</
{{out}}
<pre>2
Line 13,275 ⟶ 15,372:
=={{header|PL/SQL}}==
<
type array_of_booleans is varray(100000000) of boolean;
type table_of_integers is table of integer;
Line 13,311 ⟶ 15,408:
end find_primes;
end sieve_of_eratosthenes;
/</
Usage:
<
from table(sieve_of_eratosthenes.find_primes(30));
Line 13,342 ⟶ 15,439:
664579 3203324994356
Elapsed: 00:00:02.60</
=={{header|Pony}}==
<
use "collections"
Line 13,403 ⟶ 15,500:
env.out.print("Found " + count.string() + " primes to " + limit.string() + ".")
env.out.print("This took " + elpsd.string() + " milliseconds.")
end</
{{out}}
<pre>Primes to 100: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Line 13,420 ⟶ 15,517:
It is a waste not to do the trivial changes to the above code to sieve odds-only, which is about two and a half times faster due to the decreased number of culling operations; it doesn't really do much about the huge array problem though, other than to reduce it by a factor of two.
<
use "collections"
Line 13,479 ⟶ 15,576:
env.out.print("Found " + count.string() + " primes to " + limit.string() + ".")
env.out.print("This took " + elpsd.string() + " milliseconds.")
end</
The output is the same as the above except that it is about two and a half times faster due to that many less culling operations.
Line 13,501 ⟶ 15,598:
===Basic procedure===
It outputs immediately so that the number can be used by the pipeline.
<
{
$isprime = @{}
Line 13,512 ⟶ 15,609:
{ $isprime[$i] = $false }
}
}</
===Another implementation===
<syntaxhighlight lang="powershell">
function eratosthenes ($n) {
if($n -ge 1){
Line 13,533 ⟶ 15,630:
}
"$(eratosthenes 100)"
</syntaxhighlight>
<b>Output:</b>
<pre>
Line 13,541 ⟶ 15,638:
=={{header|Processing}}==
Calculate the primes up to 1000000 with Processing, including a visualisation of the process.
<
int maxx;
int maxy;
Line 13,589 ⟶ 15,686:
void plot(int pos, boolean active) {
set(pos%maxx, pos/maxx, active?#000000:#ffffff);
}</
As an additional visual effect, the layout of the pixel could be changed from the line-by-line layout to a spiral-like layout starting in the middle of the screen.
Line 13,595 ⟶ 15,692:
==={{header|Processing Python mode}}===
<
i = 2
Line 13,637 ⟶ 15,734:
def plot(pos, active):
set(pos % maxx, pos / maxx, color(0) if active else color(255))</
=={{header|Prolog}}==
===Using lists===
====Basic bounded sieve====
<
sieve(Xs, L).
Line 13,655 ⟶ 15,752:
; H3 is H2 + H,
( H1 =:= H2 -> filter(H, H3, T, R)
; filter(H, H3, [H1|T], R) ) ).</
{{out}}
Line 13,670 ⟶ 15,767:
This is actually the Euler's variant of the sieve of Eratosthenes, generating (and thus removing) each multiple only once, though a sub-optimal implementation.
<
range(X, X, [X]) :- !.
Line 13,683 ⟶ 15,780:
remove( _, [], [] ) :- !.
remove( [H | X], [H | Y], R ) :- !, remove(X, Y, R).
remove( X, [H | Y], [H | R]) :- remove(X, Y, R). </
Running in SWI Prolog,
Line 13,697 ⟶ 15,794:
We can stop early, with massive improvement in complexity (below ~ <i>n<sup>1.5</sup></i> inferences, empirically, vs. the ~ <i>n<sup>2</sup></i> of the above, in ''n'' primes produced; showing only the modified predicates):
<
sieve(X, [H | T], [H | T]) :- H*H > X, !.
sieve(X, [H | T], [H | S]) :- maplist( mult(H), [H | T], MS),
remove(MS, T, R), sieve(X, R, S).</
{{out}}
Line 13,713 ⟶ 15,810:
Optimized by stopping early, traditional sieve of Eratosthenes generating multiples by iterated addition.
<
range(X, X, [X]) :- !.
Line 13,728 ⟶ 15,825:
remove( [H | X], [H | Y], R ) :- !, remove(X, Y, R).
remove( [H | X], [G | Y], R ) :- H < G, !, remove(X, [G | Y], R).
remove( X, [H | Y], [H | R]) :- remove(X, Y, R). </
{{out}}
<pre>
% 140,654 inferences, 0.016 CPU in 0.011 seconds (142% CPU, 9016224 Lips)
X = [2, 3, 5, 7, 11, 13, 17, 19, 23|...],
N = 1000.
</pre>
====Sift the Two's and Sift the Three's====
Another version, based on Cloksin&Mellish p.175, modified to stop early as well as to work with odds only and use addition in the removing predicate, instead of the <code>mod</code> testing as the original was doing:
<syntaxhighlight lang="prolog">primes(N,[]):- N < 2, !.
primes(N,[2|R]):- ints(3,N,L), sift(N,L,R).
ints(A,B,[A|C]):- A=<B -> D is A+2, ints(D,B,C).
ints(_,_,[]).
sift(_,[],[]).
sift(N,[A|B],[A|C]):- A*A =< N -> rmv(A,B,D), sift(N,D,C)
; C=B.
rmv(A,B,D):- M is A*A, rmv(A,M,B,D).
rmv(_,_,[],[]).
rmv(P,M,[A|B],C):- ( M>A -> C=[A|D], rmv(P,M,B,D)
; M==A -> M2 is M+2*P, rmv(P,M2,B,C)
; M<A -> M2 is M+2*P, rmv(P,M2,[A|B],C)
).</syntaxhighlight>
Runs at about n^1.4 time empirically, producing 20,000 primes in 1.4 secs [https://swish.swi-prolog.org/p/modified_C&M_SoE.pl on the SWISH platform] as of 2021-11-26.
===Using lazy lists===
Line 13,743 ⟶ 15,858:
====Basic variant====
<
count(N, D, [N|T]):- freeze(T, (N2 is N+D, count(N2, D, T))).
Line 13,753 ⟶ 15,868:
remove([A|T],[B|S],R):- A < B -> remove(T,[B|S],R) ;
A=:=B -> remove(T,S,R) ;
R = [B|R2], freeze(R2, remove([A|T], S, R2)).</
{{out}}
Line 13,765 ⟶ 15,880:
====Optimized by postponed removal====
Showing only changed predicates.
<
freeze(PS, (primes(BPS), count(3, 1, NS), sieve(NS, BPS, 4, PS))).
Line 13,771 ⟶ 15,886:
N < Q -> PS = [N|PS2], freeze(PS2, sieve(NS, BPS, Q, PS2))
; BPS = [BP,BP2|BPS2], Q2 is BP2*BP2, count(Q, BP, MS),
remove(MS, NS, R), sieve(R, [BP2|BPS2], Q2, PS). </
{{out}}
Line 13,792 ⟶ 15,907:
to record integers that are found to be composite.
<
% that are less than or equal to N
sieve( N, [2|Rest]) :-
Line 13,827 ⟶ 15,942:
:- dynamic( composite/1 ).
</syntaxhighlight>
The above has been tested with SWI-Prolog and gprolog.
<
?- time( (sieve(100000,P), length(P,N), writeln(N), last(P, LP), writeln(LP) )).
Line 13,837 ⟶ 15,952:
N = 9592,
LP = 99991.
</syntaxhighlight>
==== Optimized approach====
[http://ideone.com/WDC7z Works with SWI-Prolog].
<
retractall(mult(_)),
sieve_O(3,N,PS).
Line 13,871 ⟶ 15,986:
:- dynamic( mult/1 ).
:- main(100000), main(1000000).</
Running it produces
<
[9592, 99991]
[78498, 999983]
Line 13,881 ⟶ 15,996:
%% stderr copy
% 293,176 inferences, 0.14 CPU in 0.14 seconds (101% CPU, 2094114 Lips)
% 3,122,303 inferences, 1.63 CPU in 1.67 seconds (97% CPU, 1915523 Lips)</
which indicates <i>~ N<sup>1.1</sup></i> [http://en.wikipedia.org/wiki/Analysis_of_algorithms#Empirical_orders_of_growth empirical orders of growth], which is consistent with the ''O(N log log N)'' theoretical runtime complexity.
Line 13,889 ⟶ 16,004:
Uses a ariority queue, from the paper "The Genuine Sieve of Eratosthenes" by Melissa O'Neill. Works with YAP (Yet Another Prolog)
<
prime(2).
Line 13,914 ⟶ 16,029:
adjust_heap(H2, N, H).
adjust_heap(H, N, H) :-
\+ min_of_heap(H, N, _).</
=={{header|PureBasic}}==
===Basic procedure===
<
If Nums(n)=0
m=n*n
Line 13,927 ⟶ 16,042:
Wend
EndIf
Next n</
===Working example===
<
Define l, n, m, lim
Line 13,966 ⟶ 16,081:
Print(#CRLF$+#CRLF$+"Press ENTER to exit"): Input()
CloseConsole()
EndIf</
Output may look like;
Line 13,991 ⟶ 16,106:
avoids explicit iteration in the interpreter, giving a further speed improvement.
<
multiples = set()
for i in range(2, n+1):
Line 13,998 ⟶ 16,113:
multiples.update(range(i*i, n+1, i))
print(list(eratosthenes2(100)))</
===Using array lookup===
The version below uses array lookup to test for primality. The function <tt>primes_upto()</tt> is a straightforward implementation of [http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Algorithm Sieve of Eratosthenes]algorithm. It returns prime numbers less than or equal to <tt>limit</tt>.
<
is_prime = [False] * 2 + [True] * (limit - 1)
for n in range(int(limit**0.5 + 1.5)): # stop at ``sqrt(limit)``
Line 14,008 ⟶ 16,123:
for i in range(n*n, limit+1, n):
is_prime[i] = False
return [i for i, prime in enumerate(is_prime) if prime]</
===Using generator===
The following code may be slightly slower than using the array/list as above, but uses no memory for output:
<
is_prime = [False] * 2 + [True] * (limit - 1)
for n in xrange(int(limit**0.5 + 1.5)): # stop at ``sqrt(limit)``
Line 14,019 ⟶ 16,134:
is_prime[i] = False
for i in xrange(limit + 1):
if is_prime[i]: yield i</
[2, 3, 5, 7, 11, 13]</
===Odds-only version of the array sieve above===
The following code is faster than the above array version using only odd composite operations (for a factor of over two) and because it has been optimized to use slice operations for composite number culling to avoid extra work by the interpreter:
<
if limit < 2: return []
if limit < 3: return [2]
Line 14,034 ⟶ 16,149:
s = p * (i + 1) + i
buf[s::p] = [False] * ((lmtbf - s) // p + 1)
return [2] + [i + i + 3 for i, v in enumerate(buf) if v]</
Note that "range" needs to be changed to "xrange" for maximum speed with Python 2.
Line 14,041 ⟶ 16,156:
The following code is faster than the above generator version using only odd composite operations (for a factor of over two) and because it has been optimized to use slice operations for composite number culling to avoid extra work by the interpreter:
<
yield 2
if limit < 3: return
Line 14,052 ⟶ 16,167:
buf[s::p] = [False] * ((lmtbf - s) // p + 1)
for i in range(lmtbf + 1):
if buf[i]: yield (i + i + 3)</
Note that this version may actually run slightly faster than the equivalent array version with the advantage that the output doesn't require any memory.
Line 14,061 ⟶ 16,176:
This uses a 235 factorial wheel for further reductions in operations; the same techniques can be applied to the array version as well; it runs slightly faster and uses slightly less memory as compared to the odds-only algorithms:
<
yield 2; yield 3; yield 5
if limit < 7: return
Line 14,080 ⟶ 16,195:
s += p * gaps[ci]; ci += 1
for i in range(lmtbf - 6 + (ndxs[(limit - 7) % 30])): # adjust for extras
if buf[i]: yield (30 * (i >> 3) + modPrms[i & 7])</
Note: Much of the time (almost two thirds for this last case for Python 2.7.6) for any of these array/list or generator algorithms is used in the computation and enumeration of the final output in the last line(s), so any slight changes to those lines can greatly affect execution time. For Python 3 this enumeration is about twice as slow as Python 2 (Python 3.3 slow and 3.4 slower) for an even bigger percentage of time spent just outputting the results. This slow enumeration means that there is little advantage to versions that use even further wheel factorization, as the composite number culling is a small part of the time to enumerate the results.
Line 14,091 ⟶ 16,206:
{{libheader|NumPy}}
Below code adapted from [http://en.literateprograms.org/Sieve_of_Eratosthenes_(Python,_arrays)#simple_implementation literateprograms.org] using [http://numpy.scipy.org/ numpy]
<
def primes_upto2(limit):
is_prime = numpy.ones(limit + 1, dtype=numpy.bool)
Line 14,097 ⟶ 16,212:
if is_prime[n]:
is_prime[n*n::n] = 0
return numpy.nonzero(is_prime)[0][2:]</
'''Performance note:''' there is no point to add wheels here, due to execution of <tt>p[n*n::n] = 0</tt> and <tt>nonzero()</tt> takes us almost all time.
Line 14,104 ⟶ 16,219:
===Using wheels with numpy===
Version with wheel based optimization:
<
#
def makepattern(smallprimes):
Line 14,123 ⟶ 16,238:
if isprime[n]:
isprime[n*n::n] = 0
return nonzero(isprime)[0]</
Examples:
<
array([ 2, 3, 5, ..., 999961, 999979, 999983])
>>> primes_upto3(10**7, smallprimes=(2,3)) # Wall time: '''2.13'''
Line 14,137 ⟶ 16,252:
array([ 2, 3, 5, ..., 9999971, 9999973, 9999991])
>>> primes_upto3(10**7) # Wall time: '''1.30'''
array([ 2, 3, 5, ..., 9999971, 9999973, 9999991])</
The above-mentioned examples demonstrate that the ''given'' wheel based optimization does not show significant performance gain.
Line 14,144 ⟶ 16,259:
{{works with|Python|2.6+, 3.x}}
<
# generates all prime numbers
Line 14,171 ⟶ 16,286:
yield i
i += 1</
Example:
<pre>
Line 14,192 ⟶ 16,307:
The adding of each discovered prime's incremental step info to the mapping should be '''''postponed''''' until the prime's ''square'' is seen amongst the candidate numbers, as it is useless before that point. This drastically reduces the space complexity from <i>O(n)</i> to <i>O(sqrt(n/log(n)))</i>, in ''<code>n</code>'' primes produced, and also lowers the run time complexity quite low ([http://ideone.com/VXep9F this test entry in Python 2.7] and [http://ideone.com/muuS4H this test entry in Python 3.x] shows about <i>~ n<sup>1.08</sup></i> [http://en.wikipedia.org/wiki/Analysis_of_algorithms#Empirical_orders_of_growth empirical order of growth] which is very close to the theoretical value of <i>O(n log(n) log(log(n)))</i>, in ''<code>n</code>'' primes produced):
{{works with|Python|2.6+, 3.x}}
<
yield 2; yield 3; yield 5; yield 7;
bps = (p for p in primes()) # separate supply of "base" primes (b.p.)
Line 14,215 ⟶ 16,330:
import itertools
def primes_up_to(limit):
return list(itertools.takewhile(lambda p: p <= limit, primes()))</
===Fast infinite generator using a wheel===
Although theoretically over three times faster than odds-only, the following code using a 2/3/5/7 wheel is only about 1.5 times faster than the above odds-only code due to the extra overheads in code complexity. The [http://ideone.com/LFaRnT test link for Python 2.7] and [http://ideone.com/ZAY0T2 test link for Python 3.x] show about the same empirical order of growth as the odds-only implementation above once the range grows enough so the dict operations become amortized to a constant factor.
{{works with|Python|2.6+, 3.x}}
<
for p in [2,3,5,7]: yield p # base wheel primes
gaps1 = [ 2,4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,8 ]
Line 14,249 ⟶ 16,364:
if nni > 47: nni = 0
n += gaps[ni]; ni = nni # advance on the wheel
for p, pi in wheel_prime_pairs(): yield p # strip out indexes</
Further gains of about 1.5 times in speed can be made using the same code by only changing the tables and a few constants for a further constant factor gain of about 1.5 times in speed by using a 2/3/5/7/11/13/17 wheel (with the gaps list 92160 elements long) computed for a slight constant overhead time as per the [http://ideone.com/4Ld26g test link for Python 2.7] and [http://ideone.com/72Dmyt test link for Python 3.x]. Further wheel factorization will not really be worth it as the gains will be small (if any and not losses) and the gaps table huge - it is already too big for efficient use by 32-bit Python 3 and the wheel should likely be stopped at 13:
<
whlPrms = [2,3,5,7,11,13,17] # base wheel primes
for p in whlPrms: yield p
Line 14,292 ⟶ 16,407:
n += gaps[ni]; ni = nni # advance on the wheel
for p, pi in wheel_prime_pairs(): yield p # strip out indexes
</syntaxhighlight>
Line 14,299 ⟶ 16,414:
=={{header|Quackery}}==
<
[ 2dup > while
+ 1 >>
Line 14,310 ⟶ 16,425:
number on the primes ancillary stack is set.
Initially all the bits are set except for 0 and 1,
which are not prime numbers by definition.
"eratosthenes" unsets all bits above those specified
by it's argument. )
[ bit ~
Line 14,317 ⟶ 16,434:
[ bit primes share & 0 != ] is isprime ( n --> b )
[ dup dup sqrt times
[ i^ 1+
dup isprime if
[ dup 2 **
[ dup -composite
over +
rot 2dup >
dip unrot until ]
drop ]
drop ]
drop
1+ bit 1 -
primes take &
primes put ] is eratosthenes ( n --> )
100 eratosthenes
100 times [ i^ isprime if [ i^ echo sp ] ]</
'''Output:'''
Line 14,338 ⟶ 16,458:
=={{header|R}}==
<
if (n < 2)
else {
primes <- rep(
primes[[1]] <-
for(i in seq(
primes[seq(i * i, n,
}
}
which(primes)
}
}
sieve(1000)</
{{out}}
Line 14,367 ⟶ 16,488:
'''Alternate Odds-Only Version'''
<
if (n < 2) return(
lmt <- (sqrt(n) - 1) / 2
sz <- (n - 1) / 2
Line 14,385 ⟶ 16,506:
}
sieve(1000)</
{{out}}
Line 14,393 ⟶ 16,514:
===Imperative versions===
Ugly imperative version:
<
(define (sieve n)
Line 14,405 ⟶ 16,526:
(reverse primes))
(sieve 100)</
A little nicer, but still imperative:
<
(define (sieve n)
(define primes (make-vector (add1 n) #t))
Line 14,418 ⟶ 16,539:
#:when (vector-ref primes n))
n))
(sieve 100)</
Imperative version using a bit vector:
<
(require data/bit-vector)
;; Returns a list of prime numbers up to natural number limit
Line 14,434 ⟶ 16,555:
(for/list ([i (bit-vector-length bv)] #:unless (bit-vector-ref bv i)) i))
(eratosthenes 100)
</syntaxhighlight>
{{output}}
Line 14,443 ⟶ 16,564:
These examples use infinite lists (streams) to implement the sieve of Eratosthenes in a functional way, and producing all prime numbers. The following functions are used as a prefix for pieces of code that follow:
<
(define (ints-from i d) (cons i (ints-from (+ i d) d)))
(define (after n l f)
Line 14,456 ⟶ 16,577:
(cond [(< x1 x2) (cons x1 (union (cdr l1) l2 ))]
[(> x1 x2) (cons x2 (union l1 (cdr l2)))]
[else (cons x1 (union (cdr l1) (cdr l2)))])))</
==== Basic sieve ====
<
(define x (car l))
(cons x (sieve (diff (cdr l) (ints-from (+ x x) x)))))
(define primes (sieve (ints-from 2 1)))
(!! (take 25 primes))</
Runs at ~ n^2.1 [http://en.wikipedia.org/wiki/Analysis_of_algorithms#Empirical_orders_of_growth empirically], for ''n <= 1500'' primes produced.
Line 14,471 ⟶ 16,592:
Note that the first number, 2, and its multiples stream <code>(ints-from 4 2)</code> are handled separately to ensure that the non-primes list is never empty, which simplifies the code for <code>union</code> which assumes non-empty infinite lists.
<
(let ([x (car l)] [np (car non-primes)])
(cond [(= x np) (sieve (cdr l) (cdr non-primes))] ; else x < np
[else (cons x (sieve (cdr l) (union (ints-from (* x x) x)
non-primes)))])))
(define primes (cons 2 (sieve (ints-from 3 1) (ints-from 4 2))))</
==== Basic sieve Optimized with postponed processing ====
Since a prime's multiples that count start from its square, we should only start removing them when we reach that square.
<
(define p (car prs))
(define q (* p p))
(after q l (λ(t) (sieve (diff t (ints-from q p)) (cdr prs)))))
(define primes (cons 2 (sieve (ints-from 3 1) primes)))</
Runs at ~ n^1.4 up to n=10,000. The initial 2 in the self-referential primes definition is needed to prevent a "black hole".
Line 14,491 ⟶ 16,612:
Since prime's multiples that matter start from its square, we should only add them when we reach that square.
<
(after q l
(λ(t)
Line 14,499 ⟶ 16,620:
(define primes (cons 2
(diff (ints-from 3 1)
(composites (ints-from 4 2) 9 (cdr primes)))))</
==== Implementation of Richard Bird's algorithm ====
Line 14,505 ⟶ 16,626:
Appears in [http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf M.O'Neill's paper]. Achieves on its own the proper postponement that is specifically arranged for in the version above (with <code>after</code>), and is yet more efficient, because it folds to the right and so builds the right-leaning structure of merges at run time, where the more frequently-producing streams of multiples appear <i>higher</i> in that structure, so the composite numbers produced by them have less <code>merge</code> nodes to percolate through:
<
(cons 2 (diff (ints-from 3 1)
(foldr (λ(p r) (define q (* p p))
(cons q (union (ints-from (+ q p) p) r)))
'() primes))))</
=== Using threads and channels ===
Line 14,515 ⟶ 16,636:
Same algorithm as [[#With merged composites|"merged composites" above]] (without the postponement optimization), but now using threads and channels to produce a channel of all prime numbers (similar to newsqueak). The macro at the top is a convenient wrapper around definitions of channels using a thread that feeds them.
<
(define-syntax (define-thread-loop stx)
(syntax-case stx ()
Line 14,541 ⟶ 16,662:
(out! x) (let loop () (out! (channel-get l)) (loop)))
(define primes (cons 2 (sieve (ints-from 3 1) (ints-from 4 2))))
(for/list ([i 25] [x (in-producer channel-get eof primes)]) x)</
=== Using generators ===
Line 14,547 ⟶ 16,668:
Yet another variation of the same algorithm as above, this time using generators.
<
(require racket/generator)
(define (ints-from i d)
Line 14,567 ⟶ 16,688:
(define (cons x l) (generator () (yield x) (let loop () (yield (l)) (loop))))
(define primes (cons 2 (sieve (ints-from 3 1) (ints-from 4 2))))
(for/list ([i 25] [x (in-producer primes)]) x)</
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku"
my @is-prime = False, False, slip True xx $limit - 1;
Line 14,585 ⟶ 16,706:
}
(sieve 100).join(",").say;</
=== A set-based approach ===
More or less the same as the first Python example:
<syntaxhighlight lang="raku"
# Requires n(1 - 1/(log(n-1))) storage
my $multiples = set();
Line 14,601 ⟶ 16,722:
}
say flat eratsieve(100);</
This gives:
Line 14,612 ⟶ 16,733:
''Note: while this is "incorrect" by a strict interpretation of the rules, it is being left as an interesting example''
<syntaxhighlight lang="raku"
gather {
# create an iterator from 2 to $n (inclusive)
Line 14,632 ⟶ 16,753:
}
put primes( 100 );</
Which prints
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
=={{header|RATFOR}}==
<syntaxhighlight lang="ratfor">
program prime
#
define(true,1)
define(false,0)
#
integer loop,loop2,limit,k,primes,count
integer isprime(1000)
limit = 1000
count = 0
for (loop=1; loop<=limit; loop=loop+1)
{
isprime(loop) = true
}
isprime(1) = false
for (loop=2; loop<=limit; loop=loop+1)
{
if (isprime(loop) == true)
{
count = count + 1
for (loop2=loop*loop; loop2 <= limit; loop2=loop2+loop)
{
isprime(loop2) = false
}
}
}
write(*,*)
write(*,101) count
101 format('There are ',I12,' primes.')
count = 0
for (loop=1; loop<=limit; loop=loop+1)
if (isprime(loop) == true)
{
Count = count + 1
write(*,'(I6,$)')loop
if (mod(count,10) == 0) write(*,*)
}
write(*,*)
end
</syntaxhighlight>
=={{header|Red}}==
<syntaxhighlight lang="red">
primes: function [n [integer!]][
poke prim: make bitset! n 1 true
r: 2 while [r * r <= n][
repeat q n / r - 1 [poke prim q + 1 * r true]
until [not pick prim r: r + 1]
]
collect [repeat i n [if not prim/:i [keep i]]]
]
primes 100
== [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
</syntaxhighlight>
=={{header|Refal}}==
<syntaxhighlight lang="refal">$ENTRY Go {
= <Print <Primes 100>>;
};
Primes {
s.N = <Sieve <Iota 2 s.N>>;
};
Iota {
s.End s.End = s.End;
s.Start s.End = s.Start <Iota <+ 1 s.Start> s.End>;
};
Cross {
s.Step e.List = <Cross (s.Step 1) s.Step e.List>;
(s.Step s.Skip) = ;
(s.Step 1) s.Item e.List = X <Cross (s.Step s.Step) e.List>;
(s.Step s.N) s.Item e.List = s.Item <Cross (s.Step <- s.N 1>) e.List>;
};
Sieve {
= ;
X e.List = <Sieve e.List>;
s.N e.List = s.N <Sieve <Cross s.N e.List>>;
};</syntaxhighlight>
{{out}}
<pre>2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97</pre>
=={{header|REXX}}==
Line 14,643 ⟶ 16,860:
As the stemmed array gets heavily populated, the number of entries ''may'' slow down the REXX interpreter substantially,
<br>depending upon the efficacy of the hashing technique being used for REXX variables (setting/retrieving).
<
parse arg H .; if H=='' | H=="," then H= 200 /*optain optional argument from the CL.*/
w= length(H); @prime= right('prime', 20) /*W: is used for aligning the output.*/
Line 14,654 ⟶ 16,871:
end /*j*/ /* ─── */
say /*stick a fork in it, we're all done. */
say right(#, 1+w+length(@prime) ) 'primes found up to and including ' H</
'''output''' when using the input default of: <tt> 200 </tt>
<pre style="height:45ex">
Line 14,713 ⟶ 16,930:
Also added is a final message indicating the number of primes found.
<
parse arg H .; if H=='' then H=200 /*let the highest number be specified. */
tell=h>0; H=abs(H); w=length(H) /*a negative H suppresses prime listing*/
Line 14,736 ⟶ 16,953:
.: parse arg n; b=n%cw; r=n//cw+1;_=x2b(c2x(@.b));@.b=x2c(b2x(left(_,r-1)'1'substr(_,r+1)));return
s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1) /*pluralizer.*/
th: procedure; parse arg x; x=abs(x); return word('th st nd rd',1+x//10*(x//100%10\==1)*(x//10<4))</
{{out|output|text= when using the input default of: <tt> 200 </tt>}}
<pre style="height:45ex">
Line 14,814 ⟶ 17,031:
It also uses a short-circuit test for striking out composites ≤ √{{overline| target }}
<
parse arg H .; if H=='' | H=="," then H= 200 /*obtain the optional argument from CL.*/
w= length(H); @prime= right('prime', 20) /*w: is used for aligning the output. */
Line 14,829 ⟶ 17,046:
end /*j*/ /* ─── */
say /*stick a fork in it, we're all done. */
say right(#, 1 + w + length(@prime) ) 'primes found up to and including ' H</
{{out|output|text= is identical to the first (non-wheel) version; program execution is over ''twice'' as fast.}}
Line 14,835 ⟶ 17,052:
===Wheel Version restructured===
<
* 21.07.2012 Walter Pachl derived from above Rexx version
* avoid symbols @ and # (not supported by ooRexx)
Line 14,863 ⟶ 17,080:
np=np+1
Say ' prime number' right(np,w) " --> " right(prime,w)
Return</
'''output''' is mostly identical to the above versions.
=={{header|Ring}}==
<
limit = 100
sieve = list(limit)
Line 14,876 ⟶ 17,093:
if sieve[i] = 0 see "" + i + " " ok
next
</syntaxhighlight>
Output:
<pre>
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
</pre>
=={{header|RPL}}==
This is a direct translation from Wikipedia. The variable <code>i</code> has been renamed <code>ii</code> to avoid confusion with the language constant <code>i</code>=√ -1
{{works with|Halcyon Calc|4.2.8}}
{| class="wikitable"
! RPL code
! Comment
|-
|
≪ → n
≪ { } n + 1 CON 'A' STO
2 n √ '''FOR''' ii
'''IF''' A ii GET '''THEN'''
ii SQ n '''FOR''' j
'A' j 0 PUT ii '''STEP'''
'''END'''
'''NEXT'''
{ }
2 n '''FOR''' ii '''IF''' A ii GET '''THEN''' ii + '''END NEXT'''
'A' PURGE
≫ ≫ '<span style="color:blue">SIEVE</span>' STO
|
<span style="color:blue">SIEVE</span> ''( n -- { prime_numbers } )''
let A be an array of Boolean values, indexed by 2 to n,
initially all set to true.
for i = 2, 3, 4, ..., not exceeding √n do
if A[i] is true
for j = i^2, i^2+i,... not exceeding n do
set A[j] := false
return all i such that A[i] is true.
|}
100 <span style="color:blue">SIEVE</span>
{{out}}
<pre>
1: { 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 }
</pre>
Latest RPL versions allow to remove some slow <code>FOR..NEXT</code> loops and use local variables only.
{{works with|HP|49}}
« 'X' DUP 1 4 PICK 1 SEQ DUP → n a seq123
« 2 n √ '''FOR''' ii
'''IF''' a ii GET '''THEN'''
ii SQ n '''FOR''' j
'a' j 0 PUT ii '''STEP'''
'''END'''
'''NEXT'''
a seq123 IFT TAIL
» » '<span style="color:blue">SIEVE</span>' STO
{{works with|HP|49}}
=={{header|Ruby}}==
''eratosthenes'' starts with <code>nums = [nil, nil, 2, 3, 4, 5, ..., n]</code>, then marks ( the nil setting ) multiples of <code>2, 3, 5, 7, ...</code> there, then returns all non-nil numbers which are the primes.
<
nums = [nil, nil, *2..n]
(2..Math.sqrt(n)).each do |i|
Line 14,892 ⟶ 17,163:
end
p eratosthenes(100)</
<pre>[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]</pre>
Line 14,903 ⟶ 17,174:
* Both inner loops skip multiples of 2 and 3.
<
# For odd i, if i is prime, nums[i >> 1] is true.
# Set false for all multiples of 3.
Line 14,945 ⟶ 17,216:
end
p eratosthenes2(100)</
This simple benchmark compares ''eratosthenes'' with ''eratosthenes2''.
<
Benchmark.bmbm {|x|
x.report("eratosthenes") { eratosthenes(1_000_000) }
x.report("eratosthenes2") { eratosthenes2(1_000_000) }
}</
''eratosthenes2'' runs about 4 times faster than ''eratosthenes''.
Line 14,960 ⟶ 17,231:
[[MRI]] 1.9.x implements the sieve of Eratosthenes at file [http://redmine.ruby-lang.org/projects/ruby-19/repository/entry/lib/prime.rb prime.rb], <code>class EratosthensesSeive</code> (around [http://redmine.ruby-lang.org/projects/ruby-19/repository/entry/lib/prime.rb#L421 line 421]). This implementation optimizes for space, by packing the booleans into 16-bit integers. It also hardcodes all primes less than 256.
<
p Prime::EratosthenesGenerator.new.take_while {|i| i <= 100}</
=={{header|Run BASIC}}==
<
dim flags(limit)
for i = 2 to limit
Line 14,971 ⟶ 17,242:
next k
if flags(i) = 0 then print i;", ";
next i</
<pre>Gimme the limit:?100
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, </pre>
Line 14,982 ⟶ 17,253:
A slightly more idiomatic, optimized and modern iterator output example.
<
const START: usize = 2;
if n < START {
Line 15,000 ⟶ 17,271:
.enumerate()
.filter_map(|(e, b)| if b { Some(e + START) } else { None })
}</
Notes:
Line 15,010 ⟶ 17,281:
===Sieve of Eratosthenes - No optimization===
<
let mut is_prime = vec![true; limit+1];
Line 15,033 ⟶ 17,304:
fn main() {
println!("{:?}", simple_sieve(100));
}</
{{out}}
<pre>[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]</pre>
Line 15,041 ⟶ 17,312:
The above code doesn't even do the basic optimizing of only culling composites by primes up to the square root of the range as allowed in the task; it also outputs a vector of resulting primes, which consumes memory. The following code fixes both of those, outputting the results as an Iterator:
<
use std::time::Instant;
Line 15,085 ⟶ 17,356:
let dur = secs * 1000 + millis;
println!("Culling composites took {} milliseconds.", dur);
}</
{{output}}
<pre>[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Line 15,097 ⟶ 17,368:
The following code improves the above code by sieving only odd composite numbers as 2 is the only even prime for a reduction in number of operations by a factor of about two and a half with reduction of memory use by a factor of two, and bit-packs the composite sieving array for a further reduction of memory use by a factor of eight and with some saving in time due to better CPU cache use for a given sieving range; it also demonstrates how to eliminate the redundant array bounds check:
<
if limit < 3 {
return if limit < 2 { Box::new(empty()) } else { Box::new(once(2)) }
Line 15,127 ⟶ 17,398:
Some((i + i + 3) as usize) } else { None } }
}))
}</
The above function can be used just by substituting "optimized_sieve" for "basic_sieve" in the previous "main" function, and the outputs are the same except that the time is only 1584 milliseconds, or about three times as fast.
Line 15,137 ⟶ 17,408:
While that above code is quite fast, as the range increases above the 10's of millions it begins to lose efficiency due to loss of CPU cache associativity as the size of the one-large-array used for culling composites grows beyond the limits of the various CPU caches. Accordingly the following page-segmented code where each culling page can be limited to not larger than the L1 CPU cache is about four times faster than the above for the range of one billion:
<
use std::rc::Rc;
use std::cell::RefCell;
Line 15,311 ⟶ 17,582:
let dur = secs * 1000 + millis;
println!("Culling composites took {} milliseconds.", dur);
}</
The output is about the same as the previous codes except much faster; as well as cache size improvements mentioned above, it has a population count primes counting function that is able to determine the number of found primes about twice as fast as using the Iterator count() method (commented out and labelled as "the slow way" in the main function).
Line 15,324 ⟶ 17,595:
=={{header|S-BASIC}}==
<
comment
Find primes up to the specified limit (here 1,000) using
Line 15,372 ⟶ 17,643:
end
</syntaxhighlight>
{{out}}
<pre>
Line 15,387 ⟶ 17,658:
The following defines an IML routine to compute the sieve, and as an example stores the primes below 1000 in a dataset.
<syntaxhighlight lang="text">proc iml;
start sieve(n);
a = J(n,1);
Line 15,403 ⟶ 17,674:
append from a;
close primes;
quit;</
=={{header|SASL}}==
{{incorrect|SASL|These use REM (division) testing and so are Trial Division algorithms, not Sieve of Eratosthenes.}}
Copied from SASL manual, top of page 36. This provides an infinite list.
<syntaxhighlight lang="sasl">
show primes
WHERE
Line 15,414 ⟶ 17,685:
sieve (p : x ) = p : sieve {a <- x; a REM p > 0}
?
</syntaxhighlight>
The limited list for the first 1000 numbers
<syntaxhighlight lang="sasl">
show primes
WHERE
Line 15,423 ⟶ 17,694:
sieve (p : x ) = p : sieve {a <- x; a REM p > 0}
?
</syntaxhighlight>
=={{header|Scala}}==
=== Genuine Eratosthenes sieve===
<
import scala.collection.parallel.mutable
import scala.compat.Platform
Line 15,449 ⟶ 17,720:
assert(sieveOfEratosthenes(15099480).size == 976729)
println(s"Successfully completed without errors. [total ${Platform.currentTime - executionStart} ms]")
}</
{{out}}
Line 15,460 ⟶ 17,731:
The following [['''odds-only''']] code is written in a very concise functional style (no mutable state other than the contents of the composites buffer and "higher order functions" for clarity), in this case using a Scala mutable BitSet:
<
def makeSoE_PrimesTo(top: Int): Iterator[Int] = {
val topNdx = (top - 3) / 2 //odds composite BitSet buffer offset down to 3
Line 15,468 ⟶ 17,739:
(0 to (Math.sqrt(top).toInt - 3) / 2).filterNot { cmpsts }.foreach { cullPrmCmpsts }
Iterator.single(2) ++ (0 to topNdx).filterNot { cmpsts }.map { pi => pi + pi + 3 } }
}</
In spite of being very concise, it is very much faster than the above code converted to odds-only due to the use of the BitSet instead of the hash table based Set (or ParSet), taking only a few seconds to enumerate the primes to 100 million as compared to the 10's of seconds to count the primes to above 15 million above.
Line 15,475 ⟶ 17,746:
The below [['''odds-only''']] code using a primitive array (bit packed) and tail recursion to avoid some of the enumeration delays due to nested complex "higher order" function calls is almost eight times faster than the above more functional code:
<
def makeSoE_PrimesTo(top: Int) = {
import scala.annotation.tailrec
Line 15,502 ⟶ 17,773:
Iterator.single(2) ++ Iterator.iterate(3)(p => getNxtPrmFrom(((p + 2) - 3) >>> 1)).takeWhile(_ <= top)
}
}</
It can be tested with the following code:
<
import SoEwithArray._
val top_num = 100000000
Line 15,515 ⟶ 17,786:
println(f"Found $count primes up to $top_num" + ".")
println("Using one large mutable Array and tail recursive loops.")
}</
To produce the following output:
Line 15,527 ⟶ 17,798:
The above code still uses an amount of memory proportional to the range of the sieve (although bit-packed as 8 values per byte). As well as only sieving odd candidates, the following code uses a fixed range buffer that is about the size of the CPU L2 cache plus only storage for the base primes up to the square root of the range for a large potential saving in RAM memory used as well as greatly reducing memory access times. The use of innermost tail recursive loops for critical loops where the majority of the execution time is spent rather than "higher order" functions from iterators also greatly reduces execution time, with much of the remaining time used just to enumerate the primes output:
<
import scala.annotation.tailrec
Line 15,618 ⟶ 17,889:
val (cnt, nlwp) = gen.next(); val nacc = acc + cnt
if (nlwp <= top) takeUpto(nacc) else nacc }; takeUpto(1) }
}</
As the above and all following sieves are "infinite", they all require an extra range limiting condition to produce a finite output, such as the addition of ".takeWhile(_ <= topLimit)" where "topLimit" is the specified range as is done in the following code:
<
import APFSoEPagedOdds._
countSoEPrimesTo(100)
Line 15,631 ⟶ 17,902:
val elpsd = System.currentTimeMillis() - strt
println(f"Found $cnt primes up to $top in $elpsd milliseconds.")
}</
which outputs the following:
Line 15,648 ⟶ 17,919:
The following code uses delayed recursion via Streams to implement the Richard Bird algorithm mentioned in the last part (the Epilogue) of [http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf M.O'Neill's paper], which is '''a true incremental Sieve of Eratosthenes'''. It is nowhere near as fast as the array based solutions due to the overhead of functionally chasing the merging of the prime multiple streams; this also means that the empirical performance is not according to the usual Sieve of Eratosthenes approximations due to this overhead increasing as the log of the sieved range, but it is much better than [[Primality_by_trial_division#Odds-Only_.22infinite.22_primes_generator_using_Streams_and_Co-Inductive_Streams|the "unfaithful" sieve]].
<
def oddPrimes: Stream[Int] = {
def merge(xs: Stream[Int], ys: Stream[Int]): Stream[Int] = {
Line 15,669 ⟶ 17,940:
}
2 #:: oddPrimes
}</
Now this algorithm doesn't really need the memoization and full laziness as offered by Streams, so an implementation and use of a Co-Inductive Stream (CIS) class is sufficient and reduces execution time by almost a factor of two:<
def primesBirdCIS: Iterator[Int] = {
Line 15,703 ⟶ 17,974:
Iterator.single(2) ++ Iterator.iterate(oddPrimes())(_.continue()).map(_.start)
}</
Further gains in performance for these last two implementations can be had by using further wheel factorization and "tree folding/merging" as per [http://www.haskell.org/haskellwiki/Primes#Tree_merging_with_Wheel this Haskell implementation].
Line 15,710 ⟶ 17,981:
As per [http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf the "unfaithful sieve" article linked above], the incremental "infinite" Sieve of Eratosthenes can be implemented using a hash table instead of a Priority Queue or Map (Binary Heap) as were used in that article. The following implementation postpones the adding of base prime representations to the hash table until necessary to keep the hash table small:
<
val nextComposites = scala.collection.mutable.HashMap[Int, Int]()
def oddPrimes: Iterator[Int] = {
Line 15,734 ⟶ 18,005:
}
List(2, 3).toIterator ++ oddPrimes
}</
The above could be implemented using Streams or Co-Inductive Streams to pass the continuation parameters as passed here in a tuple but there would be no real difference in speed and there is no need to use the implied laziness. As compared to the versions of the Bird (or tree folding) Sieve of Eratosthenes, this has the expected same computational complexity as the array based versions, but is about 20 times slower due to the constant overhead of processing the key value hashing. Memory use is quite low, only being the hash table entries for each of the base prime values less than the square root of the last prime enumerated multiplied by the size of each hash entry (about 12 bytes in this case) plus a "load factor" percentage overhead in hash table size to minimize hash collisions (about twice as large as entries actually used by default on average).
Line 15,745 ⟶ 18,016:
===Tail-recursive solution===
{{Works with|Scheme|R<math>^5</math>RS}}
<
(define (sieve n)
(define (aux u v)
Line 15,765 ⟶ 18,036:
; (2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97)
; > (length (sieve 10000000))
; 664579</
===Simpler, non-tail-recursive solution===
<
(define (iota start stop stride)
(if (> start stop)
Line 15,790 ⟶ 18,061:
(display (primes 100))
(newline)</
Output:
<syntaxhighlight lang="text">(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97)</
===Optimised using an odds-wheel===
Optimised using a pre-computed wheel based on 2 (i.e. odds only):
<
(let ((stop (sqrt limit)))
(define (sieve lst)
Line 15,805 ⟶ 18,076:
(display (primes-wheel-2 100))
(newline)</
Output:
<syntaxhighlight lang="text">(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97)</
===Vector-based===
Vector-based (faster), works with R<math>^5</math>RS:
<
(define (initialize! v)
(define (iter v n) (if (>= n (vector-length v))
Line 15,853 ⟶ 18,124:
(initialize! v)
(vector-set! v 1 0) ; 1 is not a prime
(remove zero? (vector->list (iter v 2)))))</
===SICP-style streams===
Using SICP-style ''head''-forced streams. Works with MIT-Scheme, Chez Scheme, – or any other Scheme, if writing out by hand the expansion of the only macro here, <code>s-cons</code>, with explicit lambda. Common functions:
<
(define (head s) (car s))
(define (tail s) ((cdr s)))
Line 15,889 ⟶ 18,160:
((< h1 h2) (s-cons h1 (s-union (tail s1) s2 )))
((< h2 h1) (s-cons h2 (s-union s1 (tail s2))))
(else (s-cons h1 (s-union (tail s1) (tail s2)))))))</
====The simplest, naive sieve====
Very slow, running at ~ <i>n<sup>2.2</sup></i>, empirically, and worsening:
<
(let ((p (head s)))
(s-cons p
(sieve (s-diff s (from-By p p))))))
(define primes (sieve (from-By 2 1)))</
====Bounded, stopping early====
Stops at the square root of the upper limit ''m'', running at about ~ <i>n<sup>1.4</sup></i> in ''n'' primes produced, empirically. Returns infinite stream
of numbers which is only valid up to ''m'', includes composites above it:
<
(define (sieve s)
(let ((p (head s)))
Line 15,909 ⟶ 18,180:
(sieve (s-diff (tail s)
(from-By (* p p) p))))))))
(sieve (from-By 2 1)))</
====Combined multiples sieve====
Archetypal, straightforward approach by Richard Bird, presented in [http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf Melissa E. O'Neill article]. Uses <code>s-linear-join</code>, i.e. right fold, which is less efficient and of worse time complexity than the ''tree''-folding that follows. Does not attempt to conserve space by arranging for the additional inner feedback loop, as is done in the tree-folding variant below.
<
(define (mults p) (from-By (* p p) p))
(define primes ;; primes are
Line 15,924 ⟶ 18,195:
(s-cons (head (head sts))
(s-union (tail (head sts))
(s-linear-join (tail sts)))))</
Here is a version of the same sieve, which is self contained with all the requisite functions wrapped in the overall function; optimized further. It works with odd primes only, and arranges for a separate primes feed for the base primes separate from the output stream, ''calculated recursively'' by the recursive call to "oddprms" in forming "cmpsts". It also ''"fuses"'' two functions, <code>s-diff</code> and <code>from-By</code>, into one, <code>minusstrtat</code>:
<
(define (mltpls p)
(define pm2 (* p 2))
Line 15,950 ⟶ 18,221:
(define (cmpsts) (mrgmltpls (allmltpls (oddprms)))) ;; internal define's are mutually recursive
(define (oddprms) (cons 3 (lambda () (minusstrtat 5 (cmpsts)))))
(cons 2 (lambda () (oddprms))))</
It can be tested with the following code:
<
(let nxtprm ((cnt 0) (ps (birdPrimes)))
(if (< cnt n) (nxtprm (+ cnt 1) ((cdr ps))) (car ps))))
(nthPrime 1000000)</
{{output}}
Line 15,967 ⟶ 18,238:
The most efficient. Finds composites as a tree of unions of each prime's multiples.
<
;;;; runs in ~ n^1.15 run time in producing n = 100K .. 1M primes
(define (primes-stream)
Line 15,989 ⟶ 18,260:
(s-union (tail (head sts))
(head (tail sts))))
(pairs (tail (tail sts)))))</
[http://ideone.com/Uuil5M Print 10 last primes] of the first thousand primes:
Line 15,999 ⟶ 18,270:
This can be also accomplished by the following self contained code which follows the format of the <code>birdPrimes</code> code above with the added "pairs" function integrated into the "mrgmltpls" function:
<
(define (mltpls p)
(define pm2 (* p 2))
Line 16,025 ⟶ 18,296:
(define (cmpsts) (mrgmltpls (allmltpls (oddprms)))) ;; internal define's are mutually recursive
(define (oddprms) (cons 3 (lambda () (minusstrtat 5 (cmpsts)))))
(cons 2 (lambda () (oddprms))))</
It can be tested with the same code as the self-contained Richard Bird sieve, just by calling <code>treemergePrimes</code> instead of <code>birdPrimes</code>.
Line 16,031 ⟶ 18,302:
===Generators===
<
(lambda ()
(let ((ans n))
Line 16,055 ⟶ 18,326:
x)))
(define primes (sieve (integers 2))) </
=={{header|Scilab}}==
<
a = ~zeros(n, 1)
a(1) = %f
Line 16,076 ⟶ 18,347:
sum(sieve(1000))
// 168, the number of primes below 1000</
=={{header|Scratch}}==
<syntaxhighlight lang="scratch">
when clicked
broadcast: fill list with zero (0) and wait
Line 16,122 ⟶ 18,393:
set k to (k + 1)
{end repeat}
</syntaxhighlight>
===Comments===
Line 16,138 ⟶ 18,409:
=={{header|Seed7}}==
The program below computes the number of primes between 1 and 10000000:
<
const func set of integer: eratosthenes (in integer: n) is func
Line 16,160 ⟶ 18,431:
begin
writeln(card(eratosthenes(10000000)));
end func;</
Original source: [http://seed7.sourceforge.net/algorith/math.htm#sieve_of_eratosthenes]
=={{header|SETL}}==
<syntaxhighlight lang="setl">program eratosthenes;
print(sieve 100);
op sieve(n);
numbers := [1..n];
numbers(1) := om;
loop for i in [2..floor sqrt n] do
loop for j in [i*i, i*i+i..n] do
numbers(j) := om;
end loop;
end loop;
return [n : n in numbers | n /= om];
end op;
end program;</syntaxhighlight>
{{out}}
<pre>[2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]</pre>
=={{header|Sidef}}==
{{trans|Raku}}
<
var sieve_arr = [false, false, (limit-1).of(true)...]
gather {
Line 16,180 ⟶ 18,469:
}
say sieve(100).join(",")</
{{out}}
<pre>
Line 16,187 ⟶ 18,476:
Alternative implementation:
<
var composite = []
for n in (2 .. limit.isqrt) {
Line 16,197 ⟶ 18,486:
}
say sieve(100).join(",")</
=={{header|Simula}}==
{{works with|Simula-67}}
<
INTEGER ARRAY t(0:1000);
INTEGER i,j,k;
Line 16,228 ⟶ 18,517:
OutInt(i,5); OutImage
END
END</
{{out}}
<pre style="height:20ex"> 2
Line 16,252 ⟶ 18,541:
997</pre>
===A Concurrent Prime Sieve===
<
! A CONCURRENT PRIME SIEVE ;
Line 16,360 ⟶ 18,649:
END;
END;
</syntaxhighlight>
Output:
<pre>
Line 16,409 ⟶ 18,698:
=={{header|Smalltalk}}==
A simple implementation that you can run in a workspace. It finds all the prime numbers up to and including <i>limit</i>—for the sake of example, up to and including 100.
<
limit := 100.
potentialPrimes := Array new: limit.
Line 16,424 ⟶ 18,713:
Transcript show: testNumber asString; cr
]
]</
=={{header|SNOBOL4}}==
Line 16,430 ⟶ 18,719:
Using strings instead of arrays, and the square/sqrt optimizations.
<
sieve i = lt(i,n - 1) i + 1 :f(sv1)
str = str (i + 1) ' ' :(sieve)
Line 16,446 ⟶ 18,735:
* # Test and display
output = sieve(100)
end</
Output:
<pre>2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97</pre>
=={{header|SparForte}}==
As a structured script.
<syntaxhighlight lang="ada">#!/usr/local/bin/spar
pragma annotate( summary, "sieve" );
pragma annotate( description, "The Sieve of Eratosthenes is a simple algorithm that" );
pragma annotate( description, "finds the prime numbers up to a given integer. Implement ");
pragma annotate( description, "this algorithm, with the only allowed optimization that" );
pragma annotate( description, "the outer loop can stop at the square root of the limit," );
pragma annotate( description, "and the inner loop may start at the square of the prime" );
pragma annotate( description, "just found. That means especially that you shouldn't" );
pragma annotate( description, "optimize by using pre-computed wheels, i.e. don't assume" );
pragma annotate( description, "you need only to cross out odd numbers (wheel based on" );
pragma annotate( description, "2), numbers equal to 1 or 5 modulo 6 (wheel based on 2" );
pragma annotate( description, "and 3), or similar wheels based on low primes." );
pragma annotate( see_also, "http://rosettacode.org/wiki/Sieve_of_Eratosthenes" );
pragma annotate( author, "Ken O. Burtch" );
pragma license( unrestricted );
pragma restriction( no_external_commands );
procedure sieve is
last_bool : constant positive := 20;
type bool_array is array(2..last_bool) of boolean;
a : bool_array;
test_num : positive;
-- limit : positive := positive(numerics.sqrt(float(arrays.last(a))));
-- n : positive := 2;
begin
for i in arrays.first(a)..last_bool loop
a(i) := true;
end loop;
for num in arrays.first(a)..last_bool loop
if a(num) then
test_num := num * num;
while test_num <= last_bool loop
a(test_num) := false;
test_num := @ + num;
end loop;
end if;
end loop;
for i in arrays.first(a)..last_bool loop
if a(i) then
put_line(i);
end if;
end loop;
end sieve;</syntaxhighlight>
=={{header|Standard ML}}==
Works with SML/NJ. This uses BitArrays which are available in SML/NJ. The algorithm is the one on wikipedia, referred to above. Limit: Memory, normally. When more than 20 petabyte of memory available, this code will have its limitation at a maximum integer around 1.44*10E17, due to the maximum list length in SMLNJ. Using two extra loops, however, bit arrays can simply be stored to disk and processed in multiple lists. With a tail recursive wrapper function as well, the upper limit will be determined by available disk space only.
<syntaxhighlight lang="standard ml">
val segmentedSieve = fn N =>
(* output : list of {segment=bit segment, start=number at startposition segment} *)
Line 16,562 ⟶ 18,902:
end;
</syntaxhighlight>
Example, segment size 120 million, prime numbers up to 2.5 billion:
<syntaxhighlight lang="standard ml">
-val writeSegment = fn L : {segment:BitArray.array, start:IntInf.int} list => fn NthSegment =>
let
Line 16,586 ⟶ 18,926:
</syntaxhighlight>
=={{header|Stata}}==
A program to create a dataset with a variable p containing primes up to a given number.
<
args n
clear
Line 16,609 ⟶ 18,949:
qui keep if a
drop a
end</
Example call
<
list in 1/10 // show only the first ten primes
Line 16,629 ⟶ 18,969:
9. | 23 |
10. | 29 |
+----+</
=== Mata ===
<
real colvector sieve(real scalar n) {
real colvector a
Line 16,657 ⟶ 18,997:
4 | 7 |
+-----+
end</
=={{header|Swift}}==
<
let max = 1_000_000
let maxroot = Int(sqrt(
let startingPoint = Date()
Line 16,684 ⟶ 19,024:
print("\(count) primes found under \(max)")
print("\(startingPoint.timeIntervalSinceNow * -1) seconds")</
{{output}}
<pre>78498 primes found under 1000000
Line 16,694 ⟶ 19,034:
The most obvious two improvements are to sieve for only odds as two is the only even prime and to make the sieving array bit-packed so that instead of a whole 8-bit byte per number representation there, each is represented by just one bit; these two changes improved memory use by a factor of 16 and the better CPU cache locality more than compensates for the extra code required to implement bit packing as per the following code:
<
LazyMapSequence<UnfoldSequence<Int, (Int?, Bool)>, Int> {
Line 16,716 ⟶ 19,056:
return ni > lmti ? nil : ni
}).lazy.map { $0 < 0 ? 2 : $0 + $0 + 3 }
}</
the output for the same testing (with `soePackedOdds` substituted for `primes`) is the same except that it is about 1.5 times faster or only 1200 cycles per prime.
Line 16,725 ⟶ 19,065:
To use Swift's "higher order functions" on the generated `Sequence`'s effectively, one needs unbounded (or only by the numeric range chosen for the implementation) sieves. Many of these are incremental sieves that, instead of buffering a series of culled arrays, records the culling structure of the culling base primes (which should be a secondary stream of primes for efficiency) and produces the primes incrementally through reference and update of that structure. Various structures may be chosen for this, as in a MinHeap Priority Queue, a Hash Dictionary, or a simple List tree structure as used in the following code:
<
func soeTreeFoldingOdds() -> UnfoldSequence<Int, (Int?, Bool)> {
Line 16,799 ⟶ 19,139:
print("Found \(answr) primes to \(range).")
print(String(format: "This test took %.3f milliseconds.", elpsd * 1000))</
The output is the same as for the above except that it is much slower at about 56,000 CPU clock cycles per prime even just sieving to ten million due to the many memory allocations/de-allocations. It also has a O(n (log n) (log (log n))) asymptotic computational complexity (with the extra "log n" factor) that makes it slower with increasing range. This makes this algorithm only useful up to ranges of a few million although it is adequate to solve trivial problems such as Euler Problem 10 of summing all the primes to two million.
Line 16,808 ⟶ 19,148:
As the above code is slow due to memory allocations/de-allocations and the inherent extra "log n" term in the complexity, the following code uses a Hash Dictionary which has an average of O(1) access time (without the "log n" and uses mutability for increased seed so is in no way purely functional:
<
var bp = 5; var q = 25
var bps: UnfoldSequence<Int, Int>.Iterator? = nil
Line 16,834 ⟶ 19,174:
defer { n += 2 }; return n
})
}</
It can be substituted in the above code just by substituting the `soeDictOdds` in three places in the testing code with the same output other than it is over four times faster or about 12,500 CPU clock cycles per prime.
Line 16,841 ⟶ 19,181:
An unbounded array-based algorithm can be written that combines the excellent cache locality of the second bounded version above but is unbounded by producing a sequence of sieved bit-packed arrays that are CPU cache size as required with a secondary stream of base primes used in culling produced in the same fashion, as in the following code:
<
typealias Prime = UInt64
Line 17,155 ⟶ 19,495:
print("Found \(answr) primes up to \(range).")
print(String(format: "This test took %.3f milliseconds.", elpsd * 1000))</
{{output}}
<pre>The first 25 primes are:
Line 17,167 ⟶ 19,507:
=={{header|Tailspin}}==
<
templates sieve
def limit: $;
Line 17,191 ⟶ 19,531:
1000 -> sieve ...-> '$; ' -> !OUT::write
</syntaxhighlight>
{{out}}
<pre>
Line 17,198 ⟶ 19,538:
Better version using the mutability of the @-state to just update a primality flag
<
templates sieve
def limit: $;
Line 17,212 ⟶ 19,552:
1000 -> sieve... -> '$; ' -> !OUT::write
</syntaxhighlight>
{{out}}
<pre>
Line 17,219 ⟶ 19,559:
=={{header|Tcl}}==
<
proc sieve n {
Line 17,244 ⟶ 19,584:
}
puts [sieve 100] ;# 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97</
Line 17,250 ⟶ 19,590:
=={{header|TI-83 BASIC}}==
<
N→Dim(L1)
For(I,2,N)
Line 17,269 ⟶ 19,609:
End
End
ClrList L1</
=={{header|UNIX Shell}}==
Line 17,276 ⟶ 19,616:
{{works with|Korn Shell}}
{{works with|Zsh}}
<
typeset -a a
typeset i j
Line 17,295 ⟶ 19,635:
}
primes 1000</
{{Out}}
Line 17,305 ⟶ 19,645:
{{works with|Bourne Shell}}
<
LIMIT=1000
Line 17,347 ⟶ 19,687:
eval \\$p$i && echo $i
i=\`expr $i + 1\`
done`</
===With piping===
Line 17,359 ⟶ 19,699:
{{works with|Bourne Shell}}
<
seq 2 1000
}
Line 17,377 ⟶ 19,717:
}
sourc | sink</
This version works by piping 1s and 0s through ''sed''. The string of 1s and 0s represents the array of primes.
{{works with|Bourne Shell}}
<
fill () {
# This pipeline would begin
Line 17,414 ⟶ 19,754:
}
prime 1000</
==={{header|C Shell}}===
{{trans|CMake}}
<
@ limit = 80
Line 17,445 ⟶ 19,785:
endif
@ i += 1
end</
=={{header|Ursala}}==
{{incorrect|Ursala|It probably (remainder) uses rem testing and so is a trial division algorithm, not a sieve of Eratosthenes.}}
with no optimizations
<
sieve = ~<{0,1}&& iota; @NttPX ~&r->lx ^/~&rhPlC remainder@rlX~|@r</
test program:
<
example = sieve 50</
<2,3,5,7,11,13,17,19,23,29,31,37,41,43,47>
=={{header|Vala}}==
{{libheader|Gee}}Without any optimizations:
<
ArrayList<int> primes(int limit){
Line 17,498 ⟶ 19,838:
stdout.printf("\n");
}</
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
=={{header|VAX Assembly}}==
<
0000 0000 2 .entry main,0
7E 7CFD 0002 3 clro -(sp) ;result buffer
Line 17,530 ⟶ 19,870:
0046 27
0001E892 0046 28 bits: .blkl <n+2+31>/32
E892 29 .end main</
=={{header|VBA}}==
Using Excel<
'BRRJPA
'Prime calculation for VBA_Excel
Line 17,563 ⟶ 19,903:
Next a
End Sub </
=={{header|VBScript}}==
To run in console mode with cscript.
<syntaxhighlight lang="vb">
Dim sieve()
If WScript.Arguments.Count>=1 Then
Line 17,588 ⟶ 19,928:
If sieve(i) Then WScript.Echo i
Next
</syntaxhighlight>
=={{header|Vedit macro language}}==
Line 17,628 ⟶ 19,968:
=={{header|Visual Basic}}==
'''Works with:''' VB6
<
Dim sieve() As Boolean
Dim n As Integer, i As Integer, j As Integer
Line 17,646 ⟶ 19,986:
If sieve(i) Then Debug.Print i
Next i
End Sub 'Eratost</
=={{header|Visual Basic .NET}}==
<
Console.WriteLine("Enter number to search to: ")
limit = Console.ReadLine
Line 17,666 ⟶ 20,006:
Console.WriteLine(n)
End If
Next n</
===Alternate===
Since the sieves are being removed only above the current iteration, the separate loop for display is unnecessary. And no '''Math.Sqrt()''' needed. Also, input is from command line parameter instead of Console.ReadLine(). Consolidated ''If'' block with ''For'' statement into two ''Do'' loops.
<
Sub Main(args() As String)
Dim lmt As Integer = 500, n As Integer = 2, k As Integer
Line 17,684 ⟶ 20,024:
Loop while n <= lmt
End Sub
End Module</
=={{header|V (Vlang)}}==
{{trans|go}}
===Basic sieve of array of booleans===
<syntaxhighlight lang="v (vlang)">fn main() {
limit := 201 // means sieve numbers < 201
// sieve
mut c := []bool{len: limit} // c for composite. false means prime candidate
c[1] = true // 1 not considered prime
mut p := 2
for {
// first allowed optimization: outer loop only goes to sqrt(limit)
p2 := p * p
if p2 >= limit {
break
}
// second allowed optimization: inner loop starts at sqr(p)
for i := p2; i < limit; i += p {
c[i] = true // it's a composite
}
// scan to get next prime for outer loop
for {
p++
if !c[p] {
break
}
}
}
// sieve complete. now print a representation.
for n in 1..limit {
if c[n] {
print(" .")
} else {
print("${n:3}")
}
if n%20 == 0 {
println("")
}
}
}</syntaxhighlight>
Output:
<pre>
. 2 3 . 5 . 7 . . . 11 . 13 . . . 17 . 19 .
. . 23 . . . . . 29 . 31 . . . . . 37 . . .
41 . 43 . . . 47 . . . . . 53 . . . . . 59 .
61 . . . . . 67 . . . 71 . 73 . . . . . 79 .
. . 83 . . . . . 89 . . . . . . . 97 . . .
101 .103 . . .107 .109 . . .113 . . . . . . .
. . . . . .127 . . .131 . . . . .137 .139 .
. . . . . . . .149 .151 . . . . .157 . . .
. .163 . . .167 . . . . .173 . . . . .179 .
181 . . . . . . . . .191 .193 . . .197 .199 .
</pre>
=={{header|Vorpal}}==
<
p = new()
p.fill(0, m, 1, true)
Line 17,709 ⟶ 20,104:
}
self.print_primes(100)</
primes: 25 in 100
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
Line 17,759 ⟶ 20,154:
=={{header|Xojo}}==
Place the following in the '''Run''' event handler of a Console application:
<
Dim s As String
Dim t As Double
Line 17,791 ⟶ 20,186:
If Not sieve(i) Then Print(Str(i))
Next
s = Input</
{{out}}
Line 17,820 ⟶ 20,215:
This version uses a dynamic array and can use (a lot) less memory. It's (a lot) slower too.
Since Booleans are manually set to True, the algorithm makes more sense.
<
Dim s As String
Dim t As Double
Line 17,858 ⟶ 20,253:
If sieve(i) Then Print(Str(i))
Next
s = Input</
{{out}}
Line 17,885 ⟶ 20,280:
...
</pre>
=={{header|Woma}}==
<syntaxhighlight lang="woma">(sieve(n = /0 -> int; limit = /0 -> int; is_prime = [/0] -> *)) *
i<@>range(n*n, limit+1, n)
is_prime = is_prime[$]i,False
<*>is_prime
(primes_upto(limit = 4 -> int)) list(int)
primes = [] -> list
f = [False, False] -> list(bool)
t = [True] -> list(bool)
u = limit - 1 -> int
tt = t * u -> list(bool)
is_prime = flatten(f[^]tt) -> list(bool)
limit_sqrt = limit ** 0.5 -> float
iter1 = int(limit_sqrt + 1.5) -> int
n<@>range(iter1)
is_prime[n]<?>is_prime = sieve(n, limit, is_prime)
i,prime<@>enumerate(is_prime)
prime<?>primes = primes[^]i
<*>primes</syntaxhighlight>
=={{header|Wren}}==
<
if (n < 2) return []
var comp = List.filled(n-1, false)
Line 17,911 ⟶ 20,330:
}
System.print(sieveOfE.call(100))</
{{out}}
Line 17,919 ⟶ 20,338:
=={{header|XPL0}}==
<
int Size, Prime, I, Kill;
char Flag;
Line 17,935 ⟶ 20,354:
];
];
]</
2
3
Line 17,946 ⟶ 20,365:
=={{header|Yabasic}}==
<
// ---------------------------
Line 17,998 ⟶ 20,417:
print "time: ", t, "\n"
print peek("millisrunning")</
=={{header|Zig}}==
<syntaxhighlight lang="zig">
const std = @import("std");
const stdout = std.io.getStdOut().outStream();
Line 18,032 ⟶ 20,451:
try stdout.print("\n", .{});
}
</syntaxhighlight>
{{out}}
<pre>
Line 18,057 ⟶ 20,476:
{{trans|BCPL}}
Includes the iterator, as with the BCPL Odds-only bit packed sieve. Since it's not much extra code, the sieve object also includes methods for getting the size and testing for membership.
<syntaxhighlight lang="zig">
const std = @import("std");
const heap = std.heap;
Line 18,218 ⟶ 20,637:
}
};
</syntaxhighlight>
{{Out}}
<pre>
There are 168 primes < 1000
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229
233 239 241 251 257 263 269 271 277 281
283 293 307 311 313 317 331 337 347 349
353 359 367 373 379 383 389 397 401 409
419 421 431 433 439 443 449 457 461 463
467 479 487 491 499 503 509 521 523 541
547 557 563 569 571 577 587 593 599 601
607 613 617 619 631 641 643 647 653 659
661 673 677 683 691 701 709 719 727 733
739 743 751 757 761 769 773 787 797 809
811 821 823 827 829 839 853 857 859 863
877 881 883 887 907 911 919 929 937 941
947 953 967 971 977 983 991 997
</pre>
===Optimized version===
<syntaxhighlight lang="zig">
const stdout = @import("std").io.getStdOut().writer();
const lim = 1000;
const n = lim - 2;
var primes: [n]?usize = undefined;
pub fn main() anyerror!void {
var i: usize = 0;
var m: usize = 0;
while (i < n) : (i += 1) {
primes[i] = i + 2;
}
i = 0;
while (i < n) : (i += 1) {
if (primes[i]) |prime| {
m += 1;
try stdout.print("{:5}", .{prime});
if (m % 10 == 0) try stdout.print("\n", .{});
var j: usize = i + prime;
while (j < n) : (j += prime) {
primes[j] = null;
}
}
}
try stdout.print("\n", .{});
}
</syntaxhighlight>
{{Out}}
<pre>
$ zig run sieve.zig
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
Line 18,242 ⟶ 20,715:
=={{header|zkl}}==
<
composite:=Data(limit+1).fill(1); // bucket of bytes set to 1 (prime)
(2).pump(limit.toFloat().sqrt()+1, Void, // Void==no results, just loop
Line 18,249 ⟶ 20,722:
(2).filter(limit-1,composite.get); // bytes still 1 are prime
}
sieve(53).println();</
The pump method is just a loop, passing results from action to action
and collecting the results (ie a minimal state machine). Pumping to Void
|