What's the ideal implementation for the Sieve of Eratosthenes between Lists, Arrays, and Mutable Arrays?

后端 未结 3 393
感动是毒
感动是毒 2021-01-02 20:20

In Haskell, I\'ve found three simple implementations of the Sieve of Eratosthenes on the Rosetta Code page.

Now my question is, which one should be used in w

3条回答
  •  天命终不由人
    2021-01-02 20:55

    Mutable array will always be the winner in terms of performance (and you really should've copied the version that works on odds only as a minimum; it should be the fastest of the three - also because it uses Int and not Integer).

    For lists, tree-shaped merging incremental sieve should perform better than the one you show. You can always use it with takeWhile (< limit) if needed. I contend that it conveys the true nature of the sieve most clearly:

    import Data.List (unfoldr)
    
    primes :: [Int]         
    primes = 2 : _Y ((3 :) . gaps 5 . _U . map (\p -> [p*p, p*p+2*p..]))
    
    _Y g = g (_Y g)                                -- recursion 
    _U ((x:xs):t) = (x :) . union xs . _U          -- ~= nub . sort . concat
                          . unfoldr (\(a:b:c) -> Just (union a b, c)) $ t
    
    gaps k s@(x:xs) | k < x     = k : gaps (k+2) s   -- ~= [k,k+2..]\\s, when 
                    | otherwise =     gaps (k+2) xs  --  k<=x && null(s\\[k,k+2..])
    
    union a@(x:xs) b@(y:ys) = case compare x y of  -- ~= nub . sort .: (++)
             LT -> x : union  xs  b
             EQ -> x : union  xs ys
             GT -> y : union  a  ys
    

    _U reimplements Data.List.Ordered.unionAll, and gaps 5 is (minus [5,7..]), fused for efficiency, with minus and union from the same package.

    Of course nothing beats the brevity of Data.List.nubBy (((>1).).gcd) [2..] (but it's very slow).

    To your 1st new question: not. It does find the multiples by counting up, as any true sieve should (although "minus" on lists is of course under-performant; the above improves on that by re-arranging a linear subtraction chain ((((xs-a)-b)-c)- ... ) into a subtraction of tree-folded additions, xs-(a+((b+c)+...))).

提交回复
热议问题