{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveGeneric #-}

module Test.Tasty.Bench.Utils (
  Measurement (..),
  measRelStDev,
  measure,
  traceShowM',
) where

import Control.DeepSeq (NFData)
import GHC.Generics (Generic)
import Test.Tasty (Timeout)
import Test.Tasty.Bench (Benchmarkable, RelStDev (..), measureCpuTimeAndStDev)
import Text.Printf (printf)

#ifdef DEBUG
import Debug.Trace
#endif

-- | Represents a time measurement for a given problem's size.
data Measurement = Measurement
  { Measurement -> Double
measTime :: !Double
  , Measurement -> Double
measStDev :: !Double
  }
  deriving (Measurement -> Measurement -> Bool
(Measurement -> Measurement -> Bool)
-> (Measurement -> Measurement -> Bool) -> Eq Measurement
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Measurement -> Measurement -> Bool
== :: Measurement -> Measurement -> Bool
$c/= :: Measurement -> Measurement -> Bool
/= :: Measurement -> Measurement -> Bool
Eq, Eq Measurement
Eq Measurement =>
(Measurement -> Measurement -> Ordering)
-> (Measurement -> Measurement -> Bool)
-> (Measurement -> Measurement -> Bool)
-> (Measurement -> Measurement -> Bool)
-> (Measurement -> Measurement -> Bool)
-> (Measurement -> Measurement -> Measurement)
-> (Measurement -> Measurement -> Measurement)
-> Ord Measurement
Measurement -> Measurement -> Bool
Measurement -> Measurement -> Ordering
Measurement -> Measurement -> Measurement
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Measurement -> Measurement -> Ordering
compare :: Measurement -> Measurement -> Ordering
$c< :: Measurement -> Measurement -> Bool
< :: Measurement -> Measurement -> Bool
$c<= :: Measurement -> Measurement -> Bool
<= :: Measurement -> Measurement -> Bool
$c> :: Measurement -> Measurement -> Bool
> :: Measurement -> Measurement -> Bool
$c>= :: Measurement -> Measurement -> Bool
>= :: Measurement -> Measurement -> Bool
$cmax :: Measurement -> Measurement -> Measurement
max :: Measurement -> Measurement -> Measurement
$cmin :: Measurement -> Measurement -> Measurement
min :: Measurement -> Measurement -> Measurement
Ord, (forall x. Measurement -> Rep Measurement x)
-> (forall x. Rep Measurement x -> Measurement)
-> Generic Measurement
forall x. Rep Measurement x -> Measurement
forall x. Measurement -> Rep Measurement x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Measurement -> Rep Measurement x
from :: forall x. Measurement -> Rep Measurement x
$cto :: forall x. Rep Measurement x -> Measurement
to :: forall x. Rep Measurement x -> Measurement
Generic)

instance Show Measurement where
  show :: Measurement -> String
show (Measurement Double
t Double
err) = String -> Double -> Double -> String
forall r. PrintfType r => String -> r
printf String
"%.3g ± %.3g" Double
t Double
err

instance NFData Measurement

measure :: Timeout -> RelStDev -> Benchmarkable -> IO Measurement
measure :: Timeout -> RelStDev -> Benchmarkable -> IO Measurement
measure Timeout
x RelStDev
y Benchmarkable
z = (Double -> Double -> Measurement)
-> (Double, Double) -> Measurement
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Double -> Double -> Measurement
Measurement ((Double, Double) -> Measurement)
-> IO (Double, Double) -> IO Measurement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Timeout -> RelStDev -> Benchmarkable -> IO (Double, Double)
measureCpuTimeAndStDev Timeout
x RelStDev
y Benchmarkable
z

measRelStDev :: Measurement -> RelStDev
measRelStDev :: Measurement -> RelStDev
measRelStDev (Measurement Double
mean Double
stDev) = Double -> RelStDev
RelStDev (Double
stDev Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
mean)

traceShowM' :: (Applicative m, Show a) => a -> m ()
#ifdef DEBUG
traceShowM' = traceShowM
#else
traceShowM' :: forall (m :: * -> *) a. (Applicative m, Show a) => a -> m ()
traceShowM' = m () -> a -> m ()
forall a b. a -> b -> a
const (() -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
#endif