{-# OPTIONS_GHC -O2 #-}
{- original tweaked nested-feed array-based
(3*p,p) (p*p,2*p) JBwoVL abPSOx
6Uv0cL 2x speed-up 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
-}
module Main where -- initial code from from stackoverflow.com/a/42122559
-- by stackoverflow.com/users/2144669/david-eisenstat
data Heap = Leaf !Nat !Nat
| Branch !Nat !Heap !Heap
top :: Heap -> Nat
top (Leaf n _) = n
top (Branch n _ _) = n
leaf :: Nat -> Heap -- tweak by stackoverflow.com/users/849891/will-ness:
leaf p = Leaf (p*p + 2*p) (2*p) -- wn
-- leaf p = Leaf (3 * p) p -- (original)
branch :: Heap -> Heap -> Heap
branch h1 h2
= Branch
(min (top h1
) (top h2
)) h1 h2
pop :: Heap -> Heap -- popAndReinsert, really
pop (Leaf n d) = Leaf (n + d) d -- wn
-- pop (Leaf n d) = Leaf (n + 2*d) d -- (original)
pop (Branch _ h1 h2)
= case compare (top h1
) (top h2
) of LT -> branch (pop h1) h2
EQ -> branch (pop h1) (pop h2)
GT -> branch h1 (pop h2)
push :: Nat -> Heap -> Heap
push p h@(Leaf _ _) = branch (leaf p) h
push p (Branch _ h1 h2) = branch (push p h2) h1
primes0 :: [Nat] -- original definition
primes0
= let helper n h
LT -> n : helper (n + 2) (push n h)
EQ -> helper (n + 2) (pop h)
GT -> helper n (pop h)
in 2 : 3 : helper 5 (leaf 3)
primes :: [Nat] -- nested primes feed chain by stackoverflow.com/users/849891/will-ness
primes -- for additional 3x+ speedup due to quadratic reduction in memory usage
= let -- and noticeable improvement in empirical orders of growth
helper n h q ps@(p:r)
| n
==q
= helper
(n
+ 2) (push p h
) (head r
^2) r
LT -> n : helper (n + 2) h q ps
EQ -> helper (n + 2) (pop h) q ps
GT -> helper n (pop h) q ps
-- ps = [5,7] ++ helper 11 (leaf 3) 25 ps
_Y g = g (_Y g) -- = g (g (g (g (...)))) = g . g . g . g . ....
in -- 2 : 3 : ps
2 : 3 : _Y (([5,7] ++) . helper 11 (leaf 3) 25)
main
= do (print $ primes
!! 1000000)