packages feed

cdar-mBound-0.1.0.0: bench/bench.hs

import Control.Concurrent
import Control.Monad ()
import Criterion.Main

import Data.Bits
import Data.Ratio
import Data.CDAR

logMap :: (Fractional a) => Rational -> a -> a
logMap c x = (fromRational c)*x*(1-x)

logMap2 :: Approx -> Approx
logMap2 Bottom = Bottom
logMap2 (Approx mb m e s) =
    let one = bit (-s)
        t = abs (bit (-s-1) - m)
    in boundErrorTerm $
       if t >= e
       then approxMB mb (m*(one-m)-e^2) (e * abs (one-2*m)) (2*s)
       else approxMB mb (bit (-2*s - 2)) ((t + e)^2) (2*s)

orbit :: Fractional a => Rational -> [a]
orbit c = iterate (logMap c) (fromRational (1%8))

orbit2 :: Rational -> [CR]
orbit2 c = iterate (((fromRational c)*) . CR . fmap logMap2 . unCR) (fromRational (1%8))

suite :: [Benchmark]
suite = [
    bgroup "Logistic 4" [
      bench "Double" $ nf (!! 10000) (orbit 4 :: [Double])
    , bench "CR" $ nf (require 10 . (!! 10000)) (orbit 4 :: [CR])
    , bench "CR (2)" $ nf (require 10 . (!! 10000)) (orbit2 4 :: [CR])
    ],
    bgroup "Logistic 3.5" [
      bench "Double" $ nf (!! 10000) (orbit (7%2) :: [Double])
    , bench "CR" $ nf (require 10 . (!! 10000)) (orbit (7%2) :: [CR])
    , bench "CR (2)" $ nf (require 10 . (!! 10000)) (orbit2 (7%2) :: [CR])
    ],
    bgroup "Logistic 3" [
      bench "Double" $ nf (!! 10000) (orbit 3 :: [Double])
    , bench "CR" $ nf (require 10 . (!! 10000)) (orbit 3 :: [CR])
    , bench "CR (2)" $ nf (require 10 . (!! 10000)) (orbit2 3 :: [CR])
    ]
  ]

newSuite :: [Benchmark]
newSuite =
  [ bgroup "expappr"
    [ bench "double" $ nf exp (1 :: Double)
    , bench "B40" $ nf (expBinarySplittingA 40) 1
    , bench "T40" $ nf (expTaylorA 40) 1
    , bench "T'40" $ nf expTaylorA' (setMB 40 1)
    , bench "CR40" $ nf (require 40 . expCR) 1
    , bench "B400" $ nf (expBinarySplittingA 400) 1
    , bench "T400" $ nf (expTaylorA 400) 1
    , bench "T'400" $ nf expTaylorA' (setMB 400 1)
    , bench "CR400" $ nf (require 400 . expCR) 1
    , bench "B4000" $ nf (expBinarySplittingA 4000) 1
    , bench "T4000" $ nf (expTaylorA 4000) 1
    , bench "T'4000" $ nf (expTaylorA') (setMB 4000 1)
    , bench "CR4000" $ nf (require 4000 . expCR) 1
    ]
  , bgroup "logappr"
    [ bench "doubleLog" $ nf log (1.5 :: Double)
    , bench "40B" $ nf (logBinarySplittingA 40) (Approx 10 3 0 (-1))
    , bench "40T" $ nf (logTaylorA 40) (Approx 10 3 0 (-1))
    -- , bench "40agm" $ nf (logAgmA (-40)) (Approx 10 3 0 (-1))
    , bench "400B" $ nf (logBinarySplittingA 400) (Approx 10 3 0 (-1))
    , bench "400T" $ nf (logTaylorA 400) (Approx 10 3 0 (-1))
    -- , bench "400agm" $ nf (logAgmA (-400)) (Approx 10 3 0 (-1))
    , bench "4000B" $ nf (logBinarySplittingA 4000) (Approx 10 3 0 (-1))
    , bench "4000T" $ nf (logTaylorA 4000) (Approx 10 3 0 (-1))
    -- , bench "4000agm" $ nf (logAgmA (-4000)) (Approx 10 3 0 (-1))
    ]
  , bgroup "exp"
    [ bench "double" $ nf exp (1 :: Double)
    , bench "40" $ nf (require 40 . exp) 1
    , bench "400" $ nf (require 400 . exp) 1
    ]
  , bgroup "log"
    [ bench "double" $ nf log (2 :: Double)
    , bench "40" $ nf (require 40 . log) 2
    , bench "400" $ nf (require 400 . log) 2
    ]
  , bgroup "sin"
    [ bench "double" $ nf sin (1 :: Double)
    , bench "40" $ nf (require 40 . sin) 1
    , bench "40T" $ nf sinTaylorA (setMB 40 1)
    , bench "40CR" $ nf (require 40 . sinCR) 1
    , bench "400" $ nf (require 400 . sin) 1
    , bench "400T" $ nf sinTaylorA (setMB 400 1)
    , bench "400CR" $ nf (require 400 . sinCR) 1
--    , bench "4000" $ nf (require 4000 . sin) 1
    , bench "4000T" $ nf sinTaylorA (setMB 4000 1)
    , bench "4000CR" $ nf (require 4000 . sinCR) 1
    ]
  , bgroup "cos"
    [ bench "double" $ nf cos (1 :: Double)
    , bench "40" $ nf (require 40 . cos) 1
    , bench "400" $ nf (require 400 . cos) 1
    ]
  , bgroup "atan"
    [ bench "double" $ nf atan (1 :: Double)
    , bench "40" $ nf (require 40 . atan) 1
    , bench "400" $ nf (require 400 . atan) 1
    ]
  , bgroup "pi"
    [ bench "double" $ nf (\_ -> pi :: Double) (1 :: Double)
    , bench "40" $ nf (\_ -> require 40 $ pi) 1
    , bench "400" $ nf (\_ -> require 400 $ pi) 1
    ]
  , env setupEnvPi $ \ ~(pi40,pi400,pi4000) ->
    bgroup "ccc2015"
    [ bench "pi D" $ nf (\_ -> pi :: Double) (1 :: Double)
    , bench "pi 40" $ nf (\_ -> require 40 $ pi) 1
    , bench "pi 400" $ nf (\_ -> require 400 $ pi) 1
    , bench "pi 4000" $ nf (\_ -> require 4000 $ pi) 1
    , bench "+ D" $ nf (\x -> x+x) (pi :: Double)
    , bench "+ 40" $ nf (\x -> x+x) pi40
    , bench "+ 400" $ nf (\x -> x+x) pi400
    , bench "+ 4000" $ nf (\x -> x+x) pi4000
    , bench "* D" $ nf (\x -> x*x) (pi :: Double)
    , bench "* 40" $ nf (\x -> x*x) pi40
    , bench "* 400" $ nf (\x -> x*x) pi400
    , bench "* 4000" $ nf (\x -> x*x) pi4000
    , bench "* D" $ nf (1/) (pi :: Double)
    , bench "* 40" $ nf (1/) pi40
    , bench "* 400" $ nf (1/) pi400
    , bench "* 4000" $ nf (1/) pi4000
    , bench "exp D" $ nf exp (1 :: Double)
    , bench "exp 40" $ nf (require 40 . exp) 1
    , bench "exp 400" $ nf (require 400 . exp) 1
    , bench "exp 4000" $ nf (require 4000 . exp) 1
    , bench "log D" $ nf log (2 :: Double)
    , bench "log 40" $ nf (require 40 . log) 2
    , bench "log 400" $ nf (require 400 . log) 2
    , bench "log 4000" $ nf (require 4000 . log) 2
    , bench "sin D" $ nf sin (1 :: Double)
    , bench "sin 40" $ nf (require 40 . sinCR) 1
    , bench "sin 400" $ nf (require 400 . sinCR) 1
    , bench "sin 4000" $ nf (require 4000 . sinCR) 1
    , bench "cos D" $ nf cos (1 :: Double)
    , bench "cos 40" $ nf (require 40 . cosCR) 1
    , bench "cos 400" $ nf (require 400 . cosCR) 1
    , bench "cos 4000" $ nf (require 4000 . cosCR) 1
    , bench "atan D" $ nf atan (1 :: Double)
    , bench "atan 40" $ nf (require 40 . atanCR) 1
    , bench "atan 400" $ nf (require 400 . atanCR) 1
    , bench "atan 4000" $ nf (require 4000 . atanCR) 1
    ]
  , env setupEnv $ \ ~(pi1,pi2) ->
    bgroup "elementary Approx"
    [ bench "+ double" $ nf (\x -> x+x) (pi :: Double)
    , bench "* double" $ nf (\x -> x*x) (pi :: Double)
    , bench "rec double" $ nf (1/) (pi :: Double)
    , bench "sqrt double" $ nf (sqrt) (pi :: Double)
    , bench "+ 50" $ nf (\x -> x+x) pi1
    , bench "* 50" $ nf (\x -> x*x) pi1
    , bench "rec 50" $ nf recipA (setMB 50 pi1)
    , bench "sqrt 50" $ nf sqrtA (setMB 50 pi1)
    , bench "log 50" $ nf (logA) (setMB 50 pi1)
    , bench "+ 1000" $ nf (\x -> x+x) pi2
    , bench "* 1000" $ nf (\x -> x*x) pi2
    , bench "rec 1000" $ nf recipA (setMB 1000 pi2)
    , bench "sqrt 1000" $ nf sqrtA (setMB 1000 pi2)
    , bench "sqrtRec 1000" $ nf (sqrtRecA 1000) pi2
    , bench "log 1000" $ nf logA (setMB 1000 pi2)
    ]
  ]

setupEnv :: IO (Approx, Approx)
setupEnv = return . (\a -> (limitAndBound 50 a, a)) . limitAndBound 1000 . require 1000 $ pi
setupEnvPi :: IO (Approx, Approx, Approx)
setupEnvPi = return . (\a -> (limitAndBound 40 a, limitAndBound 400 a, limitAndBound 4000 a)) . require 4000 $ pi

threadSuite :: MVar Approx -> MVar Approx -> [Benchmark]
threadSuite u v =
  [ bgroup "thread"
    [ bench "communicate" $ nfIO (do putMVar u (Approx 30 145324626 123 (-30)); a <- takeMVar v; return a)
    ]
  ]

main :: IO ()
main = defaultMain $ newSuite -- ++ suite

{- Are threads making criterion confused, times seem ok, but reported as unreliable.

threadSuite :: MVar Approx -> MVar Approx -> [Benchmark]
threadSuite u v =
  [ bgroup "thread"
    [ bench "communicate" $ nfIO (do putMVar u pi2; a <- takeMVar v; return a)
    ]
  ]

main :: IO ()
main = do
  u <- newEmptyMVar
  v <- newEmptyMVar
  forkIO $ server u v
  defaultMain $ threadSuite u v
  where server u v = forever $ do
          a <- takeMVar u
          putMVar v (a + 1)
-}