| 1 | {-# LANGUAGE BangPatterns #-} |
|---|
| 2 | {-# OPTIONS_GHC -fno-warn-unused-do-bind #-} |
|---|
| 3 | module Main (main) where |
|---|
| 4 | |
|---|
| 5 | import System.Environment (getArgs) |
|---|
| 6 | import Data.Array.Unboxed |
|---|
| 7 | import Data.Array.Base (unsafeAt) |
|---|
| 8 | import System.Random |
|---|
| 9 | import System.CPUTime |
|---|
| 10 | import Control.Monad (when) |
|---|
| 11 | import Control.Exception (evaluate) |
|---|
| 12 | import Text.Printf |
|---|
| 13 | import GHC.Real |
|---|
| 14 | |
|---|
| 15 | import Implementation |
|---|
| 16 | |
|---|
| 17 | test :: (Rational -> Double) -> UArray Int Int -> Int -> Double |
|---|
| 18 | test conv arr len = loop len 0.0 |
|---|
| 19 | where |
|---|
| 20 | rat :: Int -> Rational |
|---|
| 21 | rat k = fromIntegral n :% (fromIntegral n * fromIntegral d + 1) |
|---|
| 22 | where |
|---|
| 23 | !n = arr `unsafeAt` (2*k) |
|---|
| 24 | !d = arr `unsafeAt` (2*k+1) |
|---|
| 25 | loop 0 !acc = acc + conv (rat 0) |
|---|
| 26 | loop k acc = loop (k-1) (acc + conv (rat k)) |
|---|
| 27 | |
|---|
| 28 | main :: IO () |
|---|
| 29 | main = do |
|---|
| 30 | args <- getArgs |
|---|
| 31 | let size = |
|---|
| 32 | case args of |
|---|
| 33 | ("-bd":sz:_) -> read sz |
|---|
| 34 | _ -> 200000 |
|---|
| 35 | sg <- getStdGen |
|---|
| 36 | let iarr = mkIArr size sg |
|---|
| 37 | !ds = test (recip . fromRationalDouble . recip) iarr size |
|---|
| 38 | when (ds == 0) (putStrLn "Jackpot Double") |
|---|
| 39 | sequence_ |
|---|
| 40 | [ bench "New fromRational :: Rational -> Double" |
|---|
| 41 | (test fromRationalDouble iarr size) |
|---|
| 42 | , bench "Old fromRational :: Rational -> Double" |
|---|
| 43 | (test fromRational iarr size) |
|---|
| 44 | -- Now for Float -> Double |
|---|
| 45 | , bench "New fromRational :: Rational -> Float" |
|---|
| 46 | (fest fromRationalFloat iarr size) |
|---|
| 47 | , bench "Old fromRational :: Rational -> Float" |
|---|
| 48 | (fest fromRational iarr size) |
|---|
| 49 | ] |
|---|
| 50 | |
|---|
| 51 | fest :: (Rational -> Float) -> UArray Int Int -> Int -> Float |
|---|
| 52 | fest conv arr len = loop len 0.0 |
|---|
| 53 | where |
|---|
| 54 | rat :: Int -> Rational |
|---|
| 55 | rat k = fromIntegral n :% (fromIntegral n * fromIntegral d + 1) |
|---|
| 56 | where |
|---|
| 57 | !n = arr `unsafeAt` (2*k) |
|---|
| 58 | !d = arr `unsafeAt` (2*k+1) |
|---|
| 59 | loop 0 !acc = acc + conv (rat 0) |
|---|
| 60 | loop k acc = loop (k-1) (acc + conv (rat k)) |
|---|
| 61 | |
|---|
| 62 | mkIArr :: Int -> StdGen -> UArray Int Int |
|---|
| 63 | mkIArr num = array (0,2*num+1) . zip [0 .. 2*num+1] . randomRs (2, maxBound-1) |
|---|
| 64 | |
|---|
| 65 | prec :: Double |
|---|
| 66 | prec = 1e-12 |
|---|
| 67 | |
|---|
| 68 | bench :: String -> a -> IO () |
|---|
| 69 | bench name val = do |
|---|
| 70 | t0 <- getCPUTime |
|---|
| 71 | evaluate val |
|---|
| 72 | t1 <- getCPUTime |
|---|
| 73 | printf "%s:\n took %14.8fs\n" name (fromInteger (t1-t0)*prec) |
|---|