{-# LANGUAGE Rank2Types #-} module Blocks where import Control.Monad import Control.Monad.ST import Data.Array.Vector 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 :: ST s Integer clock = unsafeIOToST getCPUTime -- Strategies for filling the initial arrays rand :: (MTRandom e) => MTGen -> Int -> ST s e rand g _ = unsafeIOToST (random g) ascend :: Num e => Int -> ST s e ascend = return . fromIntegral descend :: Num e => e -> Int -> ST s e descend m n = return $ m - fromIntegral n modulo :: Integral e => e -> Int -> ST s 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 -> ST s 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 :: (UA e) => MUArr e s -> Int -> (Int -> ST s e) -> ST s () initialize arr len fill = init $ len - 1 where init n = fill n >>= writeMU arr n >> when (n > 0) (init $ n - 1) {-# INLINE initialize #-} speedTest :: (UA e) => Int -> (forall s. Int -> ST s e) -> (forall s. MUArr e s -> ST s ()) -> IO Integer speedTest n fill algo = stToIO $ do arr <- newMU n initialize arr n fill t0 <- clock algo arr t1 <- clock return $ t1 - t0 {-# INLINE speedTest #-}