module Main where import Data.Array import Data.Array.IO import Control.Monad import Control.Monad.Fix import System ioaA a s = ioaA' 1 s 0 where ioaA' i s acc | i > sz = return acc | True = do v <- readArray a i writeArray a i (v / s) ioaA' (i+1) s $! (v + acc) (_, sz) = Data.Array.IO.bounds a ioaACPS a s = ioaACPS' 1 s id where (_, sz) = Data.Array.IO.bounds a ioaACPS' i s acc | i > sz = return (acc 0) | True = do v <- readArray a i writeArray a i (v/s) ioaACPS' (i+1) s (\x -> v + acc x) main = do [method,n] <- getArgs (a::IOArray Int Double) <- newListArray (1::Int,read n) [(1::Double)..read n] if method == "fix" then mfix (\ ~s -> ioaA a s) >> return () else if method == "cps" then mfix (\ ~s -> ioaACPS a s) >> return () else if method == "loop" then normLoop a else norm a return () norm a = do t <- foldM (\t i -> (t+) `liftM` readArray a i) 0 [1..sz] mapM_ (\i -> readArray a i >>= writeArray a i . (/t)) [1..sz] where (_,sz) = Data.Array.IO.bounds a normLoop a = do t <- normLoop' 1 0 normLoop'' 1 t where normLoop' i acc | i > sz = return acc | True = do v <- readArray a i normLoop' (i+1) $! (v + acc) normLoop'' i t | i > sz = return () | True = do v <- readArray a i writeArray a i (v/t) normLoop'' (i+1) t (_, sz) = Data.Array.IO.bounds a {- | FIXIO | TWO LOOPS | fix cpsfix | map/fold loop unboxed-m/f unboxed-loop --------+--------------------+-------------------------------------------------- 100000 | 0.71 1.37 | 1.60 1.61 0.90 0.42 250000 | 6.51 5.74 | 7.48 7.24 2.90 1.22 500000 | 23.88 21.32 | 25.35 26.38 7.51 2.27 1000000 | 92.72 79.16 | 97.83 105.73 21.78 4.54 -}