{-# OPTIONS_GHC -O2 #-}
module Main where
import Data. List hiding ( union)
import Data. Array. Unboxed
primesSA = 2 : prs ( )
where
prs ( ) = 3 : sieve ( prs ( ) ) 3 [ ]
sieve ( p:ps) x fs = [ i* 2 + x | ( i, True) <- assocs a]
++ sieve ps ( p* p) ( ( p, 0 ) :
[ ( s
, rem ( y
- q
) s
) | ( s
, y
) <- fs
] ) where
a = accumArray ( \ b c -> False) True ( 1 , q- 1 )
[ ( i, ( ) ) | ( s, y) <- fs, i <- [ y+ s, y+ s+ s.. q] ]
-- bprimes !! 400000 -- 100k:1.04-200k:2.69=n^1.37 -- ghc 7.6.3 !!
-- 400k:7.35=n^1.45
-- primes !! 1000000 -- 200k:0.32-400k:0.83=n^1.38 -- CONSTANT
-- 1mln:2.51=n^1.21
-- 2mln:5.72=n^1.19 -- MEMORY !!!
primesSA !! 10000000 -- 400k:0.43-1mln:1.12=n^1.04
-- 2mln:2.26=n^1.01 9.3M
-- 4mln:5.10=n^1.17(1.09) 9.4M
-- 10mn:13.01=n^1.02(1.09,1.07) 9.4M
bprimes
:: [ Int ] -- Richard Bird's sieve bprimes = _ Y $ ( 2 :) . minus [ 3 .. ] .
foldr ( \p r
-> p
* p : union
[ p
* p
+ p
, p
* p
+ 2 * p
.. ] r
) [ ]
primes
= [ 2 , 3 , 5 , 7 ] ++ _ Y
( ( 11 :
) . tail . minus
( scanl ( + ) 11 wh11
) . foldi ( \( x:xs) r -> x : union xs r)
. map ( \
( w
, p
) -> scanl ( \c d
-> c
+ p
* d
) ( p
* p
) w
)
wh3 = 2 :wh3 -- ([3],2) {1*2,2*3}
wh5 = 2 :4 :wh5 -- ([5,7],6) {2*4,6*5}
wh7 = 4 :2 :4 :2 :4 :6 :2 :6 :wh7 -- ([7,11,13,17,19,23,29,31],30) {8*6,30*7}
wh11 = 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 :6 :4 :6 :2 :4 :6 :2 :6 :6 :4 :2 :4 :6 :2 :6 :4 :2 :4 :2 :10 :2 :10 :wh11
_ Y g = g ( _ Y g) -- multistage with non-sharing fixpoint combinator
-- = g (fix g) -- two stages with sharing fixpoint combinator
foldi f ( h:t) = f h . foldi f . unfoldr ( \( a:b:c) -> Just( f a b, c) ) $ t
union a b
= ordzipBy
id ( :
) ( :
) ( :
) a b
minus a b
= ordzipBy
id ( :
) skip skip a b
equalsBy k a b = ordzipBy k skip ( :) skip a b
skip a b = b -- skip a = [] ; emit a = [a]
ordzipBy k f g h a b = loop a b where -- concat$unfoldr pull(a,b)
loop a
@ ( x:t
) b
@ ( y:r
) = case compare ( k x
) y
of LT -> f x ( loop t b) -- Just(f x,(t,b))
EQ -> g x ( loop t r) -- Just(g x,(t,r))
GT -> h y ( loop a r) -- Just(h y,(a,r))
ey0jIE9QVElPTlNfR0hDIC1PMiAjLX0KbW9kdWxlIE1haW4gd2hlcmUKaW1wb3J0IERhdGEuTGlzdCBoaWRpbmcgKHVuaW9uKQppbXBvcnQgRGF0YS5BcnJheS5VbmJveGVkCiAKcHJpbWVzU0EgOjogW0ludF0KcHJpbWVzU0EgPSAyIDogcHJzICgpCiAgd2hlcmUgCiAgICBwcnMgKCkgPSAzIDogc2lldmUgKHBycyAoKSkgMyBbXQogICAgc2lldmUgKHA6cHMpIHggZnMgPSBbaSoyICsgeCB8IChpLFRydWUpIDwtIGFzc29jcyBhXSAKICAgICAgICAgICAgICAgICAgICAgICAgKysgc2lldmUgcHMgKHAqcCkgKChwLDApIDogCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWyhzLCByZW0gKHktcSkgcykgfCAocyx5KSA8LSBmc10pCiAgICAgd2hlcmUKICAgICAgcSA9IChwKnAteClgZGl2YDIKICAgICAgYSA6OiBVQXJyYXkgSW50IEJvb2wKICAgICAgYSA9IGFjY3VtQXJyYXkgKFwgYiBjIC0+IEZhbHNlKSBUcnVlICgxLHEtMSkKICAgICAgICAgICAgICAgICAgICAgWyhpLCgpKSB8IChzLHkpIDwtIGZzLCBpIDwtIFt5K3MsIHkrcytzLi5xXV0KCm1haW4gPSBwcmludCAkIAogICAgICAgICAtLSAgYnByaW1lcyAhISAgIDQwMDAwMCAtLSAxMDBrOjEuMDQtMjAwazoyLjY5PW5eMS4zNyAgLS0gZ2hjIDcuNi4zICEhCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tICAgICAgICAgICA0MDBrOjcuMzU9bl4xLjQ1ICAKICAgICAgICAgLS0gIHByaW1lcyAgISEgIDEwMDAwMDAgLS0gMjAwazowLjMyLTQwMGs6MC44Mz1uXjEuMzggIC0tIENPTlNUQU5UCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tICAgICAgICAgICAxbWxuOjIuNTE9bl4xLjIxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tICAgICAgICAgICAybWxuOjUuNzI9bl4xLjE5ICAtLSAgIE1FTU9SWSAhISEKICAgICAgICAgICAgcHJpbWVzU0EgISEgMTAwMDAwMDAgLS0gNDAwazowLjQzLTFtbG46MS4xMj1uXjEuMDQgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tICAgICAgICAgICAybWxuOjIuMjY9bl4xLjAxICAgICAgOS4zTQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtLSAgICAgICAgICAgNG1sbjo1LjEwPW5eMS4xNygxLjA5KSAgICA5LjRNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tICAgICAgICAgIDEwbW46MTMuMDE9bl4xLjAyKDEuMDksMS4wNykgIDkuNE0KYnByaW1lcyA6OiBbSW50XSAgLS0gUmljaGFyZCBCaXJkJ3Mgc2lldmUKYnByaW1lcyA9IF9ZICQgKDI6KSAuIG1pbnVzIFszLi5dIC4gCiAgICAgICAgICAgICAgZm9sZHIgKFxwIHItPiBwKnAgOiB1bmlvbiBbcCpwK3AsIHAqcCsyKnAuLl0gcikgW10KCnByaW1lcyA6OiBbSW50XQpwcmltZXMgPSBbMiwzLDUsN10gKysgX1kgKCgxMTopIC4gdGFpbCAuIG1pbnVzIChzY2FubCAoKykgMTEgd2gxMSkgCiAgICAgICAgICAgICAgIC4gZm9sZGkgKFwoeDp4cykgciAtPiB4IDogdW5pb24geHMgcikKICAgICAgICAgICAgICAgLiBtYXAgKFwodyxwKS0+IHNjYW5sIChcYyBkLT4gYyArIHAqZCkgKHAqcCkgdykKICAgICAgICAgICAgICAgLiBlcXVhbHNCeSBzbmQgKHRhaWxzIHdoMTEgYHppcGAgc2NhbmwgKCspIDExIHdoMTEpKQoKd2gzICA9IDI6d2gzICAgICAgICAgICAgICAgICAtLSAgKFszXSwyKSAgICAgICAgICAgICAgICB7MSoyLDIqM30Kd2g1ICA9IDI6NDp3aDUgICAgICAgICAgICAgICAtLSAgKFs1LDddLDYpICAgICAgICAgICAgICAgICAgezIqNCw2KjV9CndoNyAgPSA0OjI6NDoyOjQ6NjoyOjY6d2g3ICAgLS0gIChbNywxMSwxMywxNywxOSwyMywyOSwzMV0sMzApICB7OCo2LDMwKjd9CndoMTEgPSAyOjQ6Mjo0OjY6Mjo2OjQ6Mjo0OjY6NjoyOjY6NDoyOjY6NDo2Ojg6NDoyOjQ6MjogIAogICAgICAgNDo4OjY6NDo2OjI6NDo2OjI6Njo2OjQ6Mjo0OjY6Mjo2OjQ6Mjo0OjI6MTA6MjoxMDp3aDExCgpfWSBnID0gZyAoX1kgZykgICAgICAgIC0tIG11bHRpc3RhZ2Ugd2l0aCBub24tc2hhcmluZyBmaXhwb2ludCBjb21iaW5hdG9yCiAgICAgLS0gPSBnIChmaXggZykgICAgLS0gdHdvIHN0YWdlcyB3aXRoIHNoYXJpbmcgZml4cG9pbnQgY29tYmluYXRvcgoKZm9sZGkgZiAoaDp0KSA9IGYgaCAuIGZvbGRpIGYgLiB1bmZvbGRyIChcKGE6YjpjKS0+SnVzdChmIGEgYixjKSkgJCB0Cgp1bmlvbiAgICAgIGEgYiA9IG9yZHppcEJ5IGlkICAoOikgICg6KSAgKDopICBhIGIKbWludXMgICAgICBhIGIgPSBvcmR6aXBCeSBpZCAgKDopIHNraXAgc2tpcCAgYSBiCmVxdWFsc0J5IGsgYSBiID0gb3JkemlwQnkgayAgIHNraXAgKDopIHNraXAgIGEgYgpza2lwICAgICAgIGEgYiA9IGIgICAgICAgICAgICAgICAgICAgICAgIC0tIHNraXAgYSA9IFtdIDsgZW1pdCBhID0gW2FdCgpvcmR6aXBCeSBrIGYgZyBoIGEgYiA9IGxvb3AgYSBiIHdoZXJlICAgIC0tIGNvbmNhdCR1bmZvbGRyIHB1bGwoYSxiKQogIGxvb3AgYUAoeDp0KSBiQCh5OnIpID0gY2FzZSBjb21wYXJlIChrIHgpIHkgb2YKICAgIExUIC0+IGYgeCAobG9vcCB0IGIpICAgICAgICAgICAgICAgICAtLSBKdXN0KGYgeCwodCxiKSkKICAgIEVRIC0+IGcgeCAobG9vcCB0IHIpICAgICAgICAgICAgICAgICAtLSBKdXN0KGcgeCwodCxyKSkKICAgIEdUIC0+IGggeSAobG9vcCBhIHIpICAgICAgICAgICAgICAgICAtLSBKdXN0KGggeSwoYSxyKSk=