//Following is the Haskell code from which this algorithm was adapted:
//from http://w...content-available-to-author-only...l.org/haskellwiki/Prime_numbers#Tree_merging_with_Wheel
//As a reference, here is the fastest pure functional sieve in Haskell produced to date:
//
//primesTMWE = 2:3:5:7: gapsW 11 wheel (joinT3 $ rollW 11 wheel primes')
// where
// primes' = 11: gapsW 13 (tail wheel) (joinT3 $ rollW 11 wheel primes')
//
//gapsW k ws@(w:t) cs@(c:u) | k==c = gapsW (k+w) t u
// | True = k : gapsW (k+w) t cs
//rollW k ws@(w:t) ps@(p:u) | k==p = scanl (\c d->c+p*d) (p*p) ws
// : rollW (k+w) t u
// | True = rollW (k+w) t ps
//joinT3 ((x:xs): ~(ys:zs:t)) = x : union xs (union ys zs) //NOTE: '~' means deferred evaluation
// `union` joinT3 (pairs t)
//wheel = 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:wheel
//
//union (x:xs) (y:ys) = case (compare x y) of
// LT -> x : union xs (y:ys)
// EQ -> x : union xs ys
// GT -> y : union (x:xs) ys
//union xs [] = xs
//union [] ys = ys
//
//pairs ((x:xs):ys:t) = (x : union xs ys) : pairs t
type prmstate = struct val p:uint32 val pi:byte new (prm,pndx) = { p = prm; pi = pndx } end
type prmsSeqDesc = struct val v:prmstate val cont:unit->prmsSeqDesc new(ps,np) = { v = ps; cont = np } end
type cmpststate = struct val cv:uint32 val ci:byte val cp:uint32 new (strt,ndx,prm) = {cv = strt;ci = ndx;cp = prm} end
type cmpstsSeqDesc = struct val v:cmpststate val cont:unit->cmpstsSeqDesc new (cs,nc) = { v = cs; cont = nc } end
type allcmpsts = struct val v:cmpstsSeqDesc val cont:unit->allcmpsts new (csd,ncsdf) = { v=csd;cont=ncsdf } end
let primesTFOWSE =
let whlptrn = [| 2uy;4uy;2uy;4uy;6uy;2uy;6uy;4uy;2uy;4uy;6uy;6uy;2uy;6uy;4uy;2uy;6uy;4uy;6uy;8uy;4uy;2uy;4uy;2uy;
4uy;8uy;6uy;4uy;6uy;2uy;4uy;6uy;2uy;6uy;6uy;4uy;2uy;4uy;6uy;2uy;6uy;4uy;2uy;4uy;2uy;10uy;2uy;10uy |]
let inline whladv i = if i < 47uy then i + 1uy else 0uy
let inline advmltpl c ci p = cmpststate (c + uint32 whlptrn.[int ci] * p,whladv ci,p)
let rec pmltpls cs = cmpstsSeqDesc(cs,fun() -> pmltpls (advmltpl cs.cv cs.ci cs.cp))
let rec allmltpls (psd:prmsSeqDesc) =
allcmpsts(pmltpls (cmpststate(psd.v.p*psd.v.p,psd.v.pi,psd.v.p)),fun() -> allmltpls (psd.cont()))
let rec (^) (xs:cmpstsSeqDesc) (ys:cmpstsSeqDesc) = //union op for SeqDesc's
match compare xs.v.cv ys.v.cv with
| -1 -> cmpstsSeqDesc (xs.v,fun() -> xs.cont() ^ ys)
| 0 -> cmpstsSeqDesc (xs.v,fun() -> xs.cont() ^ ys.cont())
| _ -> cmpstsSeqDesc(ys.v,fun() -> xs ^ ys.cont()) //must be greater than
let rec pairs (csdsd:allcmpsts) =
let ys = csdsd.cont in
allcmpsts(cmpstsSeqDesc(csdsd.v.v,fun()->csdsd.v.cont()^ys().v),fun()->pairs (ys().cont()))
let rec joinT3 (csdsd:allcmpsts) = cmpstsSeqDesc(csdsd.v.v,fun()->
let ys = csdsd.cont() in let zs = ys.cont() in (csdsd.v.cont()^(ys.v^zs.v))^joinT3 (pairs (zs.cont())))
let rec mkprimes (ps:prmstate) (csd:cmpstsSeqDesc) =
let nxt = ps.p + uint32 whlptrn.[int ps.pi]
if ps.p >= csd.v.cv then mkprimes (prmstate(nxt,whladv ps.pi)) (csd.cont()) //minus function
else prmsSeqDesc(prmstate(ps.p,ps.pi),fun() -> mkprimes (prmstate(nxt,whladv ps.pi)) csd)
let rec baseprimes = prmsSeqDesc(prmstate(11u,0uy),fun() -> mkprimes (prmstate(13u,1uy)) initcmpsts)
and initcmpsts = joinT3 (allmltpls baseprimes)
let genseq sd = Seq.unfold (fun (psd:prmsSeqDesc) -> Some(psd.v.p,psd.cont())) sd
seq { yield 2u; yield 3u; yield 5u; yield 7u; yield! mkprimes (prmstate(11u,0uy)) initcmpsts |> genseq }
primesTFOWSE |> Seq.nth 100000 |> printfn "%A"