1 {-# LANGUAGE CPP #-}
3 import System.Random
4 import Data.Int
5 import Data.Word
6 import Data.Bits
7 import Foreign.C.Types
9 -- Take many measurements and record the max/min/average random values.
10 approxBounds :: (RandomGen g, Random a, Ord a, Num a) =>
11 (g -> (a,g)) -> Int -> a -> (a,a) -> g -> ((a,a,a),g)
12 -- Here we do a little hack to essentiall pass in the type in the last argument:
13 approxBounds nxt iters unused (explo,exphi) initrng =
14 if False
15 then ((unused,unused,unused),undefined)
16 -- else loop initrng iters 100 (-100) 0 -- Oops, can't use minBound/maxBound here.
17 else loop initrng iters exphi explo 0 -- Oops, can't use minBound/maxBound here.
18 where
19 loop rng 0 mn mx sum = ((mn,mx,sum),rng)
20 loop rng n mn mx sum =
21 case nxt rng of
22 (x, rng') -> loop rng' (n-1) (min x mn) (max x mx) (x+sum)
25 -- We check that:
26 -- (1) all generated numbers are in bounds
27 -- (2) we get "close" to the bounds
28 -- The with (2) is that we do enough trials to ensure that we can at
29 -- least hit the 90% mark.
30 checkBounds:: (Real a, Show a, Ord a) =>
31 String -> (Bool, a, a) -> ((a,a) -> StdGen -> ((a, a, t), StdGen)) -> IO ()
32 checkBounds msg (exclusive,lo,hi) fun =
33 -- (lo,hi) is [inclusive,exclusive)
34 do putStr\$ msg
35 -- ++ ", expected range " ++ show (lo,hi)
36 ++ ": "
37 (mn,mx,sum) <- getStdRandom (fun (lo,hi))
38 when (mn < lo)\$ error\$ "broke lower bound: " ++ show mn
39 when (mx > hi) \$ error\$ "broke upper bound: " ++ show mx
40 when (exclusive && mx > hi)\$ error\$ "hit upper bound: " ++ show mx
42 let epsilon = 0.1 * (toRational hi - toRational lo)
44 when (toRational (hi - mx) > epsilon)\$ error\$ "didn't get close enough to upper bound: "++ show mx
45 when (toRational (mn - lo) > epsilon)\$ error\$ "didn't get close enough to lower bound: "++ show mn
46 putStrLn "Passed"
48 intRange bits = ( False, 0 - x - x, x - 1 + x)
49 where x = 2 ^ (bits-2)
51 wordRange bits = ( False, 0, x - 1 + x )
52 where x = 2 ^ (bits-1)
54 trials = 5000
55 nb = bitSize (0::Int) -- Native bits
57 main =
58 do
59 checkBounds "Int" (intRange nb) (approxBounds random trials (undefined::Int))
60 checkBounds "Integer" (intRange nb) (approxBounds random trials (undefined::Integer))
61 -- checkBounds "Integer Rbig" (False,-(2^500), 2^500) (approxBounds (randomR (-(2^500), 2^500)) trials (undefined::Integer))
62 -- checkBounds "Integer RbigPos" (False,1,2^5000) (approxBounds (randomR (1,2^5000)) trials (undefined::Integer))
63 checkBounds "Int8" (intRange 8) (approxBounds random trials (undefined::Int8))
64 checkBounds "Int16" (intRange 16) (approxBounds random trials (undefined::Int16))
65 checkBounds "Int32" (intRange 32) (approxBounds random trials (undefined::Int32))
66 checkBounds "Int64" (intRange 64) (approxBounds random trials (undefined::Int64))
67 checkBounds "Word" (wordRange nb ) (approxBounds random trials (undefined::Word))
68 checkBounds "Word8" (wordRange 8) (approxBounds random trials (undefined::Word8))
69 checkBounds "Word16" (wordRange 16) (approxBounds random trials (undefined::Word16))
70 checkBounds "Word32" (wordRange 32) (approxBounds random trials (undefined::Word32))
71 checkBounds "Word64" (wordRange 64) (approxBounds random trials (undefined::Word64))
72 checkBounds "Double" (True,0.0,1.0) (approxBounds random trials (undefined::Double))
73 checkBounds "Float" (True,0.0,1.0) (approxBounds random trials (undefined::Float))
75 checkBounds "CChar" (intRange 8) (approxBounds random trials (undefined:: CChar))
76 checkBounds "CSChar" (intRange 8) (approxBounds random trials (undefined:: CSChar))
77 checkBounds "CUChar" (wordRange 8) (approxBounds random trials (undefined:: CUChar))
78 checkBounds "CShort" (intRange 16) (approxBounds random trials (undefined:: CShort))
79 checkBounds "CUShort" (wordRange 16) (approxBounds random trials (undefined:: CUShort))
80 checkBounds "CInt" (intRange 32) (approxBounds random trials (undefined:: CInt))
81 checkBounds "CUInt" (wordRange 32) (approxBounds random trials (undefined:: CUInt))
82 checkBounds "CLong" (intRange nb) (approxBounds random trials (undefined:: CLong))
83 checkBounds "CULong" (wordRange nb) (approxBounds random trials (undefined:: CULong))
84 checkBounds "CPtrdiff" (intRange nb) (approxBounds random trials (undefined:: CPtrdiff))
85 checkBounds "CSize" (wordRange nb) (approxBounds random trials (undefined:: CSize))
86 checkBounds "CWchar" (intRange 32) (approxBounds random trials (undefined:: CWchar))
87 checkBounds "CSigAtomic" (intRange 32) (approxBounds random trials (undefined:: CWchar))
88 checkBounds "CLLong" (intRange 64) (approxBounds random trials (undefined:: CLLong))
89 checkBounds "CULLong" (wordRange 64) (approxBounds random trials (undefined:: CULLong))
90 checkBounds "CIntPtr" (intRange nb) (approxBounds random trials (undefined:: CIntPtr))
91 checkBounds "CUIntPtr" (wordRange nb) (approxBounds random trials (undefined:: CUIntPtr))
92 checkBounds "CIntMax" (intRange 64) (approxBounds random trials (undefined:: CIntMax))
93 checkBounds "CUIntMax" (wordRange 64) (approxBounds random trials (undefined:: CUIntMax))
95 -- Then check all the range-restricted versions:
96 checkBounds "Int R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined::Int))
97 checkBounds "Integer R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined::Integer))
98 checkBounds "Int8 R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined::Int8))
99 checkBounds "Int8 Rsmall" (False,-50,50) (approxBounds (randomR (-50,50)) trials (undefined::Int8))
100 checkBounds "Int8 Rmini" (False,3,4) (approxBounds (randomR (3,4)) trials (undefined::Int8))
101 checkBounds "Int8 Rtrivial" (False,3,3) (approxBounds (randomR (3,3)) trials (undefined::Int8))
103 checkBounds "Int16 R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined::Int16))
104 checkBounds "Int32 R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined::Int32))
105 checkBounds "Int64 R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined::Int64))
106 checkBounds "Word R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined::Word))
107 checkBounds "Word8 R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined::Word8))
108 checkBounds "Word16 R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined::Word16))
109 checkBounds "Word32 R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined::Word32))
110 checkBounds "Word64 R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined::Word64))
111 checkBounds "Double R" (True,10.0,77.0) (approxBounds (randomR (10,77)) trials (undefined::Double))
112 checkBounds "Float R" (True,10.0,77.0) (approxBounds (randomR (10,77)) trials (undefined::Float))
114 checkBounds "CChar R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CChar))
115 checkBounds "CSChar R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CSChar))
116 checkBounds "CUChar R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined:: CUChar))
117 checkBounds "CShort R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CShort))
118 checkBounds "CUShort R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined:: CUShort))
119 checkBounds "CInt R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CInt))
120 checkBounds "CUInt R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined:: CUInt))
121 checkBounds "CLong R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CLong))
122 checkBounds "CULong R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined:: CULong))
123 checkBounds "CPtrdiff R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CPtrdiff))
124 checkBounds "CSize R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined:: CSize))
125 checkBounds "CWchar R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CWchar))
126 checkBounds "CSigAtomic R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CWchar))
127 checkBounds "CLLong R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CLLong))
128 checkBounds "CULLong R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined:: CULLong))
129 checkBounds "CIntPtr R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CIntPtr))
130 checkBounds "CUIntPtr R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined:: CUIntPtr))
131 checkBounds "CIntMax R" (False,-100,100) (approxBounds (randomR (-100,100)) trials (undefined:: CIntMax))
132 checkBounds "CUIntMax R" (False,0,200) (approxBounds (randomR (0,200)) trials (undefined:: CUIntMax))
134 -- Untested:
135 -- instance Random Char where
136 -- instance Random Bool where