Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

genRange should be constant for a RandomGen - enforce this with types #38

Closed
wants to merge 10 commits into from
3 changes: 1 addition & 2 deletions Benchmark/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@


#OPTS= -O2 -Wall -XCPP
OPTS= -O2 -Wall -XCPP -Werror
OPTS= -O2 -Wall -XCPP

all: lib bench

Expand Down
42 changes: 42 additions & 0 deletions Benchmark/RandomnessTest2.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module Main where

import Control.Monad
import System.Random

-- splitN :: (RandomGen g) => Int -> g -> ([g], g)
splitN 0 g = ([], g)
splitN n g = (g1:l, g')
where
(l, g') = splitN (n-1) g2
(g1, g2) = split g

-- The funny splitting operation.
split' :: (RandomGen g) => g -> (g, g)
split' g = (g12, g21)
where
(g1, g2) = split g
(_, g12) = split g1
(g21, _) = split g2

-- This test checks if generators created by calling split 2 times are independent.
-- It generates pairs of integers from 0 to n-1, using split' to
-- generate both numbers using one seed. Then it counts how often the
-- two numbers are equal.
test :: (RandomGen g) => Int -> Int -> g -> Int
test numTests n g = equals
where
(gs, _) = splitN numTests g
equals = count id $ map single gs
count p l = length $ filter p l
single g' = (fst $ randomR (0, n-1) g1) == (fst $ randomR (0, n-1) g2)
where
(g1, g2) = split' g'

main = do
let g = mkStdGen 42
forM_ [2..15] $ \i -> do
let actual = test (i * 1000) i g
putStrLn $ "Generated " ++ show (i * 1000)
++ " pairs of numbers from 0 to " ++ show (i - 1)
++ " -- " ++ show actual ++ " pairs contained equal numbers "
++ "and we expected about 1000."
43 changes: 43 additions & 0 deletions Benchmark/RandomnessTest3.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module Main where

import Control.Monad
import System.Random.TF.Gen
import System.Random.TF.Instances

splitN :: (RandomGen g) => Int -> g -> ([g], g)
splitN 0 g = ([], g)
splitN n g = (g1:l, g')
where
(l, g') = splitN (n-1) g2
(g1, g2) = split g

-- The funny splitting operation.
split' :: (RandomGen g) => g -> (g, g)
split' g = (g12, g21)
where
(g1, g2) = split g
(_, g12) = split g1
(g21, _) = split g2

-- This test checks if generators created by calling split 2 times are independent.
-- It generates pairs of integers from 0 to n-1, using split' to
-- generate both numbers using one seed. Then it counts how often the
-- two numbers are equal.
test :: (RandomGen g) => Int -> Int -> g -> Int
test numTests n g = equals
where
(gs, _) = splitN numTests g
equals = count id $ map single gs
count p l = length $ filter p l
single g' = (fst $ randomR (0, n-1) g1) == (fst $ randomR (0, n-1) g2)
where
(g1, g2) = split' g'

main = do
let g = seedTFGen (42, 42, 42, 42)
forM_ [2..15] $ \i -> do
let actual = test (i * 1000) i g
putStrLn $ "Generated " ++ show (i * 1000)
++ " pairs of numbers from 0 to " ++ show (i - 1)
++ " -- " ++ show actual ++ " pairs contained equal numbers "
++ "and we expected about 1000."
13 changes: 10 additions & 3 deletions Benchmark/SimpleRNGBench.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import Prelude hiding (last,sum)
import BinSearch

#ifdef TEST_COMPETITORS
import System.Random.TF
import System.Random.Mersenne.Pure64
import System.Random.MWC
import Control.Monad.Primitive
Expand All @@ -44,11 +45,11 @@ import GHC.IO
-- Miscellaneous helpers:

-- Readable large integer printing:
commaint :: Integral a => a -> String
commaint :: (Show a, Integral a) => a -> String
commaint n =
reverse $ concat $
intersperse "," $
chunk 3 $
chunksOf 3 $
reverse (show n)

padleft :: Int -> String -> String
Expand Down Expand Up @@ -281,7 +282,13 @@ main = do
timeit th freq "System.Random.Mersenne.Pure64 Ints" gen_mt randInt2
timeit th freq "System.Random.Mersenne.Pure64 Floats" gen_mt randFloat2

-- gen_mwc <- create
let gen_tf = seedTFGen (0,1,2,3)
randInt4 = random :: RandomGen g => g -> (Int,g)
randFloat4 = random :: RandomGen g => g -> (Float,g)
timeit th freq "System.Random.TF next" gen_tf next
timeit th freq "System.Random.TF Ints" gen_tf randInt4
timeit th freq "System.Random.TF Floats" gen_tf randFloat4

withSystemRandom $ \ gen_mwc -> do
let randInt3 = random :: RandomGen g => g -> (Int,g)
randFloat3 = random :: RandomGen g => g -> (Float,g)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The API documentation can be found here:

A module supplying this interface is required for Haskell 98 (but not Haskell
2010). An older [version]
(http://www.haskell.org/ghc/docs/latest/html/libraries/haskell98/Random.html)
(https://downloads.haskell.org/~ghc/latest/docs/html/libraries/haskell98-2.0.0.3/Random.html)
of this library is included with GHC in the haskell98 package. This newer
version, with compatible api, is included in the [Haskell Platform]
(http://www.haskell.org/platform/contents.html).
Expand Down
Loading