-
Notifications
You must be signed in to change notification settings - Fork 1
/
Fib.hs
143 lines (120 loc) · 2.72 KB
/
Fib.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
module Main where
import Control.Parallel
import Control.Monad.Par
import Control.Monad
import Control.Concurrent
import Data.IORef
fib1 :: Integer -> Integer
fib1 0 = 1
fib1 1 = 1
fib1 n = fib1 (n-1) + fib1 (n-2)
-- ghc --make -threaded -fforce-recomp -O -rtsopts Fib.hs && ./Fib +RTS -N1 -sstderr
fib2 :: Integer -> Integer
fib2 0 = 1
fib2 1 = 1
fib2 n =
let lado1 = fib2 (n-1)
lado2 = fib2 (n-2)
in lado1 + lado2
fib3 :: Integer -> Integer
fib3 0 = 1
fib3 1 = 1
fib3 n =
let lado1 = fib3 (n-1)
lado2 = fib3 (n-2)
-- in lado1 `par` lado2 `pseq` lado1 + lado2
in par lado1 (pseq lado2 (lado1 + lado2))
fib4 :: Integer -> Integer
fib4 0 = 1
fib4 1 = 1
fib4 n =
let lado1 = fib4 (n-1)
lado2 = fib4 (n-2)
final = lado1 + lado2
in if n > 30
then lado1 `par` lado2 `pseq` final
else final
-- fib4 40 = 165580141
fib5 :: Integer -> Integer
fib5 = runPar . fib5'
fib5' :: Integer -> Par Integer
fib5' 0 = return 1
fib5' 1 = return 1
fib5' n = do
lado1 <- new
lado2 <- new
fork $ fib5' (n-1) >>= put lado1
fork $ fib5' (n-2) >>= put lado2
l1 <- get lado1
l2 <- get lado2
return $ l1 + l2
-- fib5 40 = 165580141
fib6 :: Integer -> Integer
fib6 = runPar . fib6'
fib6' :: Integer -> Par Integer
fib6' 0 = return 1
fib6' 1 = return 1
fib6' n =
if n > 30
then do
lado1 <- new
lado2 <- new
fork $ fib6' (n-1) >>= put lado1
fork $ fib6' (n-2) >>= put lado2
l1 <- get lado1
l2 <- get lado2
return $ l1 + l2
else do
l1 <- fib6' (n-1)
l2 <- fib6' (n-2)
return $ l1 + l2
-- fib5 40 = 165580141
fib7 :: Integer -> Integer
fib7 = runPar . fib7'
fib7' :: Integer -> Par Integer
fib7' 0 = return 1
fib7' 1 = return 1
fib7' n =
if n > 30
then do
lado1 <- spawn (fib7' (n-1))
lado2 <- spawn (fib7' (n-2))
l1 <- get lado1
l2 <- get lado2
return $ l1 + l2
else do
l1 <- fib7' (n-1)
l2 <- fib7' (n-2)
return $ l1 + l2
-- fib7 40 = 165580141
fib n =
let fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
in fibs !! n
data Fib =
Fib {
number :: !Integer -- n
, fibN1 :: !Integer -- fib $ n - 1
, fibN :: !Integer -- fib n
}
initial :: Fib
initial = Fib 0 0 1
advance :: Fib -> Fib
advance (Fib n fn1 fn) = Fib (n+1) fn (fn1 + fn)
fib8 :: Int -> Integer
fib8 n = fibN (iterate advance initial !! n)
calcFibForever :: IORef Fib -> IO ThreadId
calcFibForever var =
forkIO $
forever $ do
v <- readIORef var
writeIORef var $! advance v
fibAfter :: Int -> IO Integer
fibAfter seconds = do
var <- newIORef initial
threadId <- calcFibForever var
threadDelay (seconds * 10^6)
killThread threadId
ret <- readIORef var
return (number ret)
-- main = fibAfter 10 >>= print
main = print =<< fibAfter 10