fork(1) download
  1. -- from http://w...content-available-to-author-only...l.org/haskellwiki/Prime_numbers#Using_ST_Array
  2.  
  3. {-# OPTIONS -O2 -optc-O3 #-}
  4. import Data.Word
  5. import Control.Monad
  6. import Control.Monad.ST
  7. import Data.Array.ST
  8. import Data.Array.Unboxed
  9. import Data.Array.Base
  10.  
  11. primesUA :: () -> [Word32]
  12. primesUA () = do
  13. let pgSZBTS = 262144 * 8
  14. let sieveUA :: (Integral t, Integral t1) => t -> [t1] -> ST s (STUArray s Int Bool)
  15. sieveUA low bps = do
  16. let nxt = (fromIntegral low) + (fromIntegral pgSZBTS)
  17. buf <- newArray (0,pgSZBTS - 1) True :: ST s (STUArray s Int Bool)
  18. let cullUAbase i = do
  19. let p = i + i + 3
  20. strt = p * (i + 1) + i
  21. let cull j = do
  22. if j >= pgSZBTS then cullUAbase (i + 1)
  23. else do
  24. unsafeWrite buf j False
  25. cull (j + p)
  26. when (strt < pgSZBTS) $ do
  27. e <- unsafeRead buf i
  28. if e then cull strt else cullUAbase (i + 1)
  29. let cullUA ~(p:t) = do
  30. let bp = (fromIntegral p)
  31. i = (bp - 3) `div` 2
  32. s = bp * (i + 1) + i
  33. let cull j = do
  34. if j >= pgSZBTS then cullUA t
  35. else do
  36. unsafeWrite buf j False
  37. cull (j + (fromIntegral p))
  38. when (s < nxt) $ do
  39. let strt = do
  40. if s >= low then fromIntegral (s - low)
  41. else do
  42. let b = (low - s) `rem` bp
  43. if b == 0 then 0 else fromIntegral (bp - b)
  44. cull strt
  45. if low <= 0 then cullUAbase 0 else cullUA bps
  46. return buf
  47. let sieveList low bps = do
  48. [2 * ((fromIntegral i) + low) + 3 | (i,True) <- assocs $ runSTUArray $ sieveUA low bps]
  49. let sieve low bps = do
  50. (sieveList low bps) ++ sieve (low + (fromIntegral pgSZBTS)) bps
  51. let primes' = ((sieveList 0 []) ++ sieve (fromIntegral pgSZBTS) primes') :: [Word32]
  52. 2 : sieve 0 primes'
  53.  
  54. main = do
  55. x <- read `fmap` getLine -- 1mln 2mln 10mln 100mln
  56. -- 0.02 0.03 0.13 1.13 seconds
  57. print (length (takeWhile ((>=) (fromIntegral x)) (primesUA ())))
Success #stdin #stdout 11.67s 9376KB
stdin
1000000000
stdout
50847534