1
{-# LANGUAGE BangPatterns #-}
2
-- A basic correctness and performance test for mersenne-random-pure64.
4
-- Copyright (c) 2008, Don Stewart <dons@galois.com>
6
import Control.Exception
12
import System.Environment
15
import qualified System.Random as Old
16
import qualified System.Random.Mersenne as Unsafe
18
import System.Random.Mersenne.Pure64
19
import System.Random.Mersenne.Pure64.Base
20
import Control.Concurrent
21
import Control.Concurrent.MVar
28
let diff = (fromIntegral (end - start)) / (10^12)
29
printf "Computation time: %0.3f sec\n" (diff :: Double)
36
c_init_genrand64_unsafe seed
37
let g = pureMT (fromIntegral seed)
39
------------------------------------------------------------------------
41
s <- newMVar 0 :: IO (MVar Int)
42
putStr "Calibrating ... " >> hFlush stdout
46
let (!_, !g') = randomWord64 g
51
threadDelay (1000 * 1000)
53
lim <- readMVar s -- 1 sec worth of generation
54
putStrLn $ "done. Using N=" ++ show lim
58
putStr $ "Checking against released mt19937-64.c to depth " ++ show m ++ " "
66
------------------------------------------------------------------------
68
equivalent !g !n | n > 0 = do
70
i' <- c_genrand64_int64_unsafe
71
d' <- c_genrand64_real2_unsafe
73
let (i, g') = randomWord64 g
74
(d, g'') = randomDouble g'
76
if i == fromIntegral i' && d == realToFrac d'
77
then do when (n `rem` 500000 == 0) $ putChar '.' >> hFlush stdout
80
else do print $ "Failed! " ++ show ((i,i') , (d,d'))
83
equivalent g _ = do putStrLn "Matches model!"
86
------------------------------------------------------------------------
87
-- compare with System.Random
89
-- overhead cause by random's badness
93
putStrLn $ "System.Random"
94
let g = Old.mkStdGen 5
95
let go :: Old.StdGen -> Int -> Int -> Int
99
let (a, g') = Old.random g
100
in go g' (n+1) (if a > acc then a else acc)
104
putStrLn $ "System.Random with our generator"
106
let go :: PureMT -> Int -> Int -> Int
110
let (a,g') = Old.random g
111
in go g' (n+1) (if a > acc then a else acc)
115
putStrLn $ "System.Random.Mersenne.Pure"
117
let go :: PureMT -> Int -> Int -> Int
121
let (a',g') = randomWord64 g
123
in go g' (n+1) (if a > acc then a else acc)
127
putStrLn $ "System.Random.Mersenne.Pure generating Double"
129
let go :: PureMT -> Int -> Double -> Double
133
let (a, g') = randomDouble g
134
in go g' (n+1) (if a > acc then a else acc)
138
putStrLn $ "System.Random.Mersenne.Pure (unique state)"
139
c_init_genrand64_unsafe 5
140
let go :: Int -> Int -> IO Int
142
| n >= lim = return acc
144
a' <- c_genrand64_int64_unsafe
145
let a = fromIntegral a'
146
go (n+1) (if a > acc then a else acc)
150
putStrLn $ "System.Random.Mersenne.Unsafe"
151
g <- Unsafe.newMTGen (Just 5)
153
let go :: Int -> Int -> IO Int
155
| n >= lim = return acc
158
go (n+1) (if a > acc then a else acc)
163
-- printf "MT is %s times faster generating %s\n" (show $x`div`y) (show (typeOf ty))