packages feed

padic-0.1.0.0: bench/Bench.hs

{-# language TypeApplications #-}
{-# language DataKinds #-}
{-# language TypeFamilies #-}
{-# language TypeOperators #-}
{-# language FlexibleContexts #-}

import Criterion.Main
import qualified Math.NumberTheory.Padic.Fixed as F
import Math.NumberTheory.Padic
import Data.Maybe
import Data.Mod
import Data.List (transpose)

addBench :: (Show n, Num n) => n -> Int -> Int
addBench w n = length $ show (w + sum (take n (fib 0 1)))

mulBench :: (Show n, Num n) => n -> Integer -> Int
mulBench w n = let M ((x:_):_) = fibM n in length (show (w + x))

divBench :: (Show a, Num a) => a -> a -> Int -> String
divBench r w n = show (product $ take n $ logistic r w)

fib a b = a : fib b (a + b)
 
fibM 0 = I
fibM n = M [[1,1],[1,0]] <> fibM (n-1)

logistic r = iterate (\x -> r*x*(1-x))
  

divMaybe a b | isInvertible b = Just (a `div` b)
             | otherwise = Nothing

fracMaybe a b | isInvertible b = Just (a / b)
              | otherwise = Nothing

data M a = I | M ![[a]]

dot a b = sum $! zipWith (*) a b                 

instance Num a => Semigroup (M a) where
  I <> x = x
  x <> I = x
  M a <> M b = M $ [ [ dot x y | y <- transpose b ] | x <- a ]

instance Num a => Monoid (M a) where
    mempty = I

addN = 400
mulN = 400
divN = 100
    
suite :: [Benchmark]
suite =
  [ bgroup
      "add"
      [ bench "Integer" $ whnf (addBench (0 :: Integer)) addN
      , bench "Mod 2^20" $ whnf (addBench (0 :: Mod 2199023255552)) addN
      , bench "Z 2" $ whnf (addBench (0 :: Z' 2 20)) addN
      , bench "Z 13" $ whnf (addBench (0 :: Z' 13 20)) addN
      , bench "Z 251" $ whnf (addBench (0 :: Z' 251 20)) addN
      , bench "F.Z 2" $ whnf (addBench (0 :: F.Z' 2 20)) addN
      , bench "F.Z 2 100" $ whnf (addBench (0 :: F.Z' 2 1000)) addN
      , bench "F.Z 13" $ whnf (addBench (0 :: F.Z' 13 20)) addN
      , bench "F.Z 251" $ whnf (addBench (0 :: F.Z' 251 20)) addN
      , bench "Q 2" $ whnf (addBench (0 :: Q' 2 20)) addN
      , bench "Q 2 100" $ whnf (addBench (0 :: Q' 2 100)) addN
      , bench "Q 13" $ whnf (addBench (0 :: Q' 13 20)) addN
      , bench "Q 251" $ whnf (addBench (0 :: Q' 251 20)) addN
      , bench "F.Q 2" $ whnf (addBench (0 :: F.Q' 2 20)) addN
      , bench "F.Q 2 100" $ whnf (addBench (0 :: F.Q' 2 100)) addN
      , bench "F.Q 13" $ whnf (addBench (0 :: F.Q' 13 20)) addN
      , bench "F.Q 251" $ whnf (addBench (0 :: F.Q' 251 20)) addN
     ]
  , bgroup
      "mul"
      [ bench "Integer" $ whnf (mulBench (0 :: Integer)) mulN
      , bench "Mod 2^20" $ whnf (mulBench (0 :: Mod 2199023255552)) mulN
      , bench "Z 2" $ whnf (mulBench (0 :: Z' 2 20)) mulN
      , bench "Z 2 100" $ whnf (mulBench (0 :: Z' 2 100)) mulN
      , bench "Z 13" $ whnf (mulBench (0 :: Z' 13 20)) mulN
      , bench "Z 251" $ whnf (mulBench (0 :: Z' 251 20)) mulN
      , bench "F.Z 2" $ whnf (mulBench (0 :: F.Z' 2 20)) mulN
      , bench "F.Z 2 100" $ whnf (mulBench (0 :: F.Z' 2 100)) mulN
      , bench "F.Z 13" $ whnf (mulBench (0 :: F.Z' 13 20)) mulN
      , bench "F.Z 251" $ whnf (mulBench (0 :: F.Z' 251 20)) mulN
      , bench "Q 2" $ whnf (mulBench (0 :: Q' 2 20)) mulN
      , bench "Q 2 100" $ whnf (mulBench (0 :: Q' 2 100)) mulN
      , bench "Q 13" $ whnf (mulBench (0 :: Q' 13 20)) mulN
      , bench "Q 251" $ whnf (mulBench (0 :: Q' 251 20)) mulN
      , bench "F.Q 2" $ whnf (mulBench (0 :: F.Q' 2 20)) mulN
      , bench "F.Q 2 100" $ whnf (mulBench (0 :: F.Q' 2 100)) mulN
      , bench "F.Q 13" $ whnf (mulBench (0 :: F.Q' 13 20)) mulN
      , bench "F.Q 251" $ whnf (mulBench (0 :: F.Q' 251 20)) mulN
      ]
  , bgroup
      "div"
      [ bench "Double" $ whnf (divBench (13 / 5) (4 / 3 :: Double)) divN
      , bench "Z 2" $ whnf (divBench (13 `div` 5) (5 `div` 3 :: Z 2)) divN
      , bench "Z 17" $ whnf (divBench (13 `div` 4) (4 `div` 3 :: Z 17)) divN
      , bench "Z 251" $ whnf (divBench (13 `div` 4) (4 `div` 3 :: Z 251)) divN
      , bench "F.Z 2" $ whnf (divBench (13 `div` 5) (4 `div` 3 :: F.Z 2)) divN
      , bench "F.Z 13" $ whnf (divBench (13 `div` 4) (4 `div` 3 :: F.Z 13)) divN
      , bench "F.Z 251" $ whnf (divBench (13 `div` 4) (4 `div` 3 :: F.Z 251)) divN
      , bench "Q 2" $ whnf (divBench (13 / 4) (4 / 3 :: Q 2)) divN
      , bench "Q 13" $ whnf (divBench (13 / 4) (4 / 3 :: Q 13)) divN
      , bench "Q 251" $ whnf (divBench (13 / 4) (4 / 3 :: Q 251)) divN
      , bench "F.Q 2" $ whnf (divBench (13 / 4) (4 / 3 :: F.Q 2)) divN
      , bench "F.Q 13" $ whnf (divBench (13 / 4) (4 / 3 :: F.Q 13)) divN
      , bench "F.Q 251" $ whnf (divBench (13 / 4) (4 / 3 :: F.Q 251)) divN
      ]
  ]

main :: IO ()
main = defaultMain suite