| 1 | |
|---|
| 2 | module Main (main) where |
|---|
| 3 | |
|---|
| 4 | import Numeric |
|---|
| 5 | import System.IO |
|---|
| 6 | import Control.Concurrent |
|---|
| 7 | |
|---|
| 8 | subtotal :: MVar Double -> Double -> Double -> Double -> IO () |
|---|
| 9 | subtotal result posn max step = do |
|---|
| 10 | let answer = puretotal posn max step 0.0 |
|---|
| 11 | putMVar result (4.0 * answer / max) |
|---|
| 12 | |
|---|
| 13 | puretotal :: Double -> Double -> Double -> Double -> Double |
|---|
| 14 | puretotal posn max step sum = |
|---|
| 15 | if posn > max then |
|---|
| 16 | sum |
|---|
| 17 | else |
|---|
| 18 | let x = (posn - 0.5) / max |
|---|
| 19 | y = sqrt (1.0 - x * x) |
|---|
| 20 | newpos = posn + step |
|---|
| 21 | newsum = sum + y |
|---|
| 22 | in seq newsum (seq newpos (puretotal newpos max step newsum)) |
|---|
| 23 | |
|---|
| 24 | main :: IO () |
|---|
| 25 | main = do |
|---|
| 26 | hSetBuffering stdout NoBuffering |
|---|
| 27 | putStr "Terms? " |
|---|
| 28 | max <- readLn :: IO Double |
|---|
| 29 | putStr "Tasks? " |
|---|
| 30 | step <- readLn :: IO Double |
|---|
| 31 | ls <- spawn 1.0 max step [] |
|---|
| 32 | answer <- gather ls 0.0 |
|---|
| 33 | putStrLn $ (showFFloat (Just 12) answer) "" |
|---|
| 34 | |
|---|
| 35 | spawn :: Double -> Double -> Double -> [MVar Double] -> IO [MVar Double] |
|---|
| 36 | spawn posn max step ls = do |
|---|
| 37 | if posn > step then do |
|---|
| 38 | return ls |
|---|
| 39 | else do |
|---|
| 40 | reply <- newEmptyMVar :: IO (MVar Double) |
|---|
| 41 | forkIO $ subtotal reply posn max step |
|---|
| 42 | let newposn = posn + 1.0 |
|---|
| 43 | newls = reply : ls |
|---|
| 44 | seq newposn seq newls spawn newposn max step newls |
|---|
| 45 | |
|---|
| 46 | gather :: [MVar Double] -> Double -> IO Double |
|---|
| 47 | gather [] sum = do |
|---|
| 48 | return sum |
|---|
| 49 | gather (item : rest) sum = do |
|---|
| 50 | term <- takeMVar item |
|---|
| 51 | let newsum = sum + term |
|---|
| 52 | seq newsum gather rest newsum |
|---|