| 1 | module Main (main) where |
|---|
| 2 | |
|---|
| 3 | import System.CPUTime |
|---|
| 4 | import System.Environment (getArgs) |
|---|
| 5 | import Text.Printf |
|---|
| 6 | import GHC.Real |
|---|
| 7 | import Data.Word |
|---|
| 8 | import Data.Int |
|---|
| 9 | |
|---|
| 10 | frecip :: Integral a => Ratio a -> Ratio a |
|---|
| 11 | frecip (0 :% _) = error "zero denominator" |
|---|
| 12 | frecip (x :% y) |
|---|
| 13 | | x < 0 = negate y :% negate x |
|---|
| 14 | | otherwise = y :% x |
|---|
| 15 | |
|---|
| 16 | makeSmall :: Integral a => Ratio a -> a |
|---|
| 17 | makeSmall (x :% y) = x `mod` 121 + y `mod` 97 |
|---|
| 18 | |
|---|
| 19 | fibs :: Integral a => [a] |
|---|
| 20 | fibs = 1 : 1 : go fibs (tail fibs) |
|---|
| 21 | where |
|---|
| 22 | go (x:xs) (y:ys) = x + y : go xs ys |
|---|
| 23 | |
|---|
| 24 | fibQuots :: Integral a => [Ratio a] |
|---|
| 25 | fibQuots = go fibs |
|---|
| 26 | where |
|---|
| 27 | go (x:(xs@(y:_))) = x :% y : go xs |
|---|
| 28 | |
|---|
| 29 | result :: Integral a => Int -> (Ratio a -> Ratio a) -> a |
|---|
| 30 | result k fun = sum . map (makeSmall . fun) $ take k fibQuots |
|---|
| 31 | |
|---|
| 32 | test :: Integral a => a -> Int -> IO () |
|---|
| 33 | test v k = do |
|---|
| 34 | u0 <- getCPUTime |
|---|
| 35 | print $ v + result k id |
|---|
| 36 | u1 <- getCPUTime |
|---|
| 37 | printf "id took %.6fs\n" (fromInteger (u1-u0) * (1e-12 :: Double)) :: IO () |
|---|
| 38 | t0 <- getCPUTime |
|---|
| 39 | print $ v + result k frecip |
|---|
| 40 | t1 <- getCPUTime |
|---|
| 41 | printf "frecip took %.6fs\n" (fromInteger (t1-t0) * (1e-12 :: Double)) :: IO () |
|---|
| 42 | t2 <- getCPUTime |
|---|
| 43 | print $ v + result k recip |
|---|
| 44 | t3 <- getCPUTime |
|---|
| 45 | printf "recip took %.6fs\n" (fromInteger (t3-t2) * (1e-12 :: Double)) |
|---|
| 46 | |
|---|
| 47 | main :: IO () |
|---|
| 48 | main = do |
|---|
| 49 | args <- getArgs |
|---|
| 50 | let (k,t) = case args of |
|---|
| 51 | (a:b:_) -> (read a, read b) |
|---|
| 52 | (a:_) -> (read a, 0) |
|---|
| 53 | _ -> (5000, 0) |
|---|
| 54 | case t of |
|---|
| 55 | 0 -> test (0 :: Integer) k |
|---|
| 56 | 1 -> test (0 :: Int) k |
|---|
| 57 | 2 -> test (0 :: Int64) k |
|---|
| 58 | 3 -> test (0 :: Word) k |
|---|
| 59 | 4 -> test (0 :: Word64) k |
|---|