{-# LANGUAGE Rank2Types #-} module Blocks where import Control.Monad import Control.Monad.ST import Data.Vector.Unboxed.Mutable import System.CPUTime import System.Random.Mersenne -- Some conveniences for doing evil stuff in the ST monad. -- All the tests get run in IO, but uvector stuff happens -- in ST, so we temporarily coerce. clock :: IO Integer clock = getCPUTime -- Strategies for filling the initial arrays rand :: (MTRandom e) => MTGen -> Int -> IO e rand g _ = random g ascend :: Num e => Int -> IO e ascend = return . fromIntegral descend :: Num e => e -> Int -> IO e descend m n = return $ m - fromIntegral n modulo :: Integral e => e -> Int -> IO e modulo m n = return $ fromIntegral n `mod` m -- This is the worst case for the median-of-three quicksort -- used in the introsort implementation. medianKiller :: Integral e => e -> Int -> IO e medianKiller m n' | n < k = return $ if even n then n + 1 else n + k | otherwise = return $ (n - k + 1) * 2 where n = fromIntegral n' k = m `div` 2 {-# INLINE medianKiller #-} initialize :: (Unbox e) => MVector RealWorld e -> Int -> (Int -> IO e) -> IO () initialize arr len fill = init $ len - 1 where init n = fill n >>= unsafeWrite arr n >> when (n > 0) (init $ n - 1) {-# INLINE initialize #-} speedTest :: (Unbox e) => Int -> (Int -> IO e) -> (MVector RealWorld e -> IO ()) -> IO Integer speedTest n fill algo = do arr <- new n initialize arr n fill t0 <- clock algo arr t1 <- clock return $ t1 - t0 {-# INLINE speedTest #-}