{-# OPTIONS_GHC -Wall -fno-warn-name-shadowing #-}
{-
Parallel Fibonacci, using the Par monad, with thresholding.

Compile:  ghc -O2 -threaded -rtsopts -o pfib2 pfib2.hs
Run:      ./pfib2 43 33  +RTS -N4 -s
-}
	

module Main where

import Control.Monad.Par.Scheds.Trace
  -- gives slightly better results than Control.Monad.Par with monad-par-0.3.4

import System.Environment

fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = nf1+nf2+1
        where nf1 = fib (n-1)
              nf2 = fib (n-2)
          
pfibT :: Int -> Int -> Par Int
pfibT t n | n<=1 = return 1                -- base case
pfibT t n | n<t  = return (fib n)          -- switch to seq case
pfibT t n | otherwise =
            do
              nv1 <- spawn (pfibT t (n-1))  -- start a parallel task & return an IVar
              nv2 <- spawn (pfibT t (n-2))  -- start a parallel task & return an IVar
              nf1 <- get nv1                -- get the result (when available)
              nf2 <- get nv2                -- get the result (when available)
              return (nf1+nf2+1)
	
main = do args <- getArgs
          let 
            n = read (args!!0) :: Int
            t = read (args!!1) :: Int
          putStr ("paralllel fib " ++ (show n) ++ " (with a threshold of " ++ (show t) ++") = ")
          let res = runPar $ pfibT t n
          putStrLn (show res)
