Sieve of Pritchard: Difference between revisions

include rephrasing of Mike Day's performance optimization
(include rephrasing of Mike Day's performance optimization)
Line 163:
 
=={{header|J}}==
Implementation:<syntaxhighlight lang="j">pritchard=model: {{
<syntaxhighlight lang="j">pritchard=: {{N=. y
spokes=. $.6$4{.1
primesroot=. 2,>.@%: p=.3N
spokes=. $.6$4{.1
while. y > #spokes do.
primes,1+}=.,I.spokes ''
p=. 0
while. y > #spokesp<:root do.
primes=. primes, p=. 2+(}.spokes) i.1 NB. find next prime
rim=. #spokes NB. "length" of "circumference" of wheel
spokes=. (yN<.p*rim)$spokes NB. roll next larger wheel
NB. remove multiples of this next prime:
spokes=. 8 $.0 ((#~spokes) y(>#]) _1+p*1+i.rim)} spokes NB. remove newly recognized prime from wheel
end.
N (>:#]) primes,1+}.,I.spokes
while. y > p*p do.
primes=. primes, p=. 2+(}.spokes) i.1 NB. find next prime
spokes=. 0 ((#~ y>])_1+p*1+i.rim)} spokes NB. scrub it out of wheel
end.
primes,1+}.,I.spokes
}}</syntaxhighlight>
 
Line 182:
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</syntaxhighlight>
 
However, this approach exhibits performance problems when N is large.
This task exposed a bug in J's implementation of X i. Y when X is an empty sparse array. To avoid/work-around this bug, we initialize <code>spokes</code> and <code>primes</code> with the values that they would have had after the first two iterations of this algorithm if <code>i.</code> would have worked properly. (The bug has been fixed, but the fix is not yet widely deployed. (We could also have used a dense array instead of a sparse array, but it's probably more "in spirit with the design of this task" to "hard code" the first two rounds and use sparse arrays than it would be to use dense arrays for the wheels.))
 
A faster approach recognizes when the wheel is large enough and treats all subsequent "next primes" specially:
 
<syntaxhighlight lang="j">pr =: {{N=.y
root=. <.%:N NB. performance optimzation
circumference=. 1
spokes=. ,1
primes=. ''
while. yN > p*pL=. circumference do.
primes=. primes, p =. 2+(}.spokes)1{ i.spokes,L+1 NB. find next prime from sieve
circumference=. N <. p * L NB. next larger wheel:
spokes=. circumference (>:#]), spokes +/~ L * i.circumference >.@% L
NB. remove multiples of this next prime:
spokes=. spokes -. p * spokes ( [{.~ >:@:(I.-(-.@e.)~))circumference<.@%p
end.
NB. set up for optimized version of above code
comb=. root (>#]) }. spokes NB. candidate next primes to consider
discardp=. discard=. '' NB. what we'll be eliminating
for_p. comb do.
if. p e. comb =. comb (-. }.) discardp do.
NB. remove multiples of this next prime:
discardp=. p * spokes ( [{.~ >:@:(I.-(-.@e.)~))circumference<.@%p
discard =. discard, discardp
end.
end.
primes,comb,}.spokes-.discard
}}</lang>
 
Here, <code>pr 150</code> gives the same result as <code>pritchard 150</code> but <code>pr 1e7</code> takes well under a second.
 
=={{header|Julia}}==
6,951

edits