Here, if (Haskell's) pure arrays are considered clean (they should, IMO). The complexity is obviously O (n log (log n)), provided that accumArray really spends O (1) time for each index it accumArray , as it should be:
import Data.Array.Unboxed import Data.List (tails, inits) ps = 2 : [n | (r:q:_, px) <- (zip . tails . (2:) . map (^2)) ps (inits ps), (n,True) <- assocs ( accumArray (\_ _ -> False) True (r+1,q-1) [(m,()) | p <- px, let s=(r+p)`div`p*p, m <- [s,s+p..q-1]] :: UArray Int Bool )]
Calculates primes by segments between consecutive squares of primes ( map (^2) bit map (^2) ), generating composites, listing multiple growing prime prefixes (bit inits ) just like any regular Eratosthenes sieve, by repeating the addition.
So, prime numbers {2,3} are used to sift a segment from 10 to 24; {2,3,5} from 26 to 48; and so on. See also .
In addition, the Python syntactic generator solution can be considered functional. Python dict extremely effective, empirically , although I'm not sure about the exact cost of the multiplication scheme used for over-production to avoid duplication of composites.
update: testing really gives favorable results, as expected:
{- original heap tweaked nested-feed array-based (3*p,p) (p*p,2*p) JBwoVL abPSOx 6Uv0cL 2x speed-up another 3x+ speed-up n^ n^ n^ n^ 100K: 0.78s 0.38s 0.13s 0.065s 200K: 2.02s 1.37 0.97s 1.35 0.29s 1.16 0.13s 1.00 400K: 5.05s 1.32 2.40s 1.31 0.70s 1.27 0.29s 1.16 800K: 12.37s 1.29 1M: 2.10s 1.20 0.82s 1.13 2M: 1.71s 1.06 4M: 3.72s 1.12 10M: 9.84s 1.06 overall in the tested range: 1.33 1.21 1.09 -}
with empirical growth orders calculated to obtain n primes, where O (n log log n) is usually considered as n 1.05 ... 1.10 and O (n log n log log n) as n 1.20 ... 1.25 .
The nested-feed option implements a deferral method (as also seen in the Python answer above) that provides a quadratic reduction in heap size, which obviously has a noticeable effect on empirical complexity, even if it does not achieve even better results for the array on based on this answer, which is capable of producing 10 million primes in less than 10 seconds on ideone.com (with a total growth rate of only n 1.09 in the test range).
( "original heap" is of course the code from another answer here).