File: RangeTest.hs

package info (click to toggle)
haskell-random 1.2.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 296 kB
  • sloc: haskell: 2,696; makefile: 3
file content (138 lines) | stat: -rw-r--r-- 9,133 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
module RangeTest (main) where

import Control.Monad
import System.Random
import Data.Int
import Data.Word
import Foreign.C.Types

-- Take many measurements and record the max/min/average random values.
approxBounds ::
  (RandomGen g, Random a, Ord a, Num a) =>
  (g -> (a,g)) -> Int -> a -> (a,a) -> g -> ((a,a,a),g)
-- Here we do a little hack to essentially pass in the type in the last argument:
approxBounds nxt iters unused (explo,exphi) initrng =
   if False
   then ((unused,unused,unused),undefined)
--   else loop initrng iters 100 (-100) 0 -- Oops, can't use minBound/maxBound here.
   else loop initrng iters exphi explo 0
 where
  loop rng 0 mn mx sum' = ((mn,mx,sum'),rng)
  loop rng  n mn mx sum' =
    case nxt rng of
      (x, rng') -> loop rng' (n-1) (min x mn) (max x mx) (x+sum')


-- We check that:
--     (1) all generated numbers are in bounds
--     (2) we get "close" to the bounds
-- The with (2) is that we do enough trials to ensure that we can at
-- least hit the 90% mark.
checkBounds ::
  (Real a, Show a, Ord a) =>
  String -> (Bool, a, a) -> ((a,a) -> StdGen -> ((a, a, t), StdGen)) -> IO ()
checkBounds msg (exclusive,lo,hi) fun = do
  -- (lo,hi) is [inclusive,exclusive)
  putStr $ msg ++ ":  "
  (mn,mx,_) <- getStdRandom (fun (lo,hi))
  when (mn < lo) $ error $ "broke lower bound: " ++ show mn
  when (mx > hi) $ error $ "broke upper bound: " ++ show mx
  when (exclusive && mx >= hi)$ error$ "hit upper bound: " ++ show mx

  let epsilon = 0.1 * (toRational hi - toRational lo)

  when (toRational (hi - mx) > epsilon) $ error $ "didn't get close enough to upper bound: "++ show mx
  when (toRational (mn - lo) > epsilon) $ error $ "didn't get close enough to lower bound: "++ show mn
  putStrLn "Passed"

boundedRange :: (Num a, Bounded a) => (Bool, a, a)
boundedRange  = ( False, minBound, maxBound )

trials :: Int
trials = 5000

-- Keep in mind here that on some architectures (e.g. ARM) CChar, CWchar, and CSigAtomic
-- are unsigned
main :: IO ()
main =
 do
    checkBounds "Int"     boundedRange   (approxBounds random trials (undefined::Int))
    checkBounds "Integer" (False, fromIntegral (minBound::Int), fromIntegral (maxBound::Int))
                                         (approxBounds random trials (undefined::Integer))
    checkBounds "Int8"    boundedRange   (approxBounds random trials (undefined::Int8))
    checkBounds "Int16"   boundedRange   (approxBounds random trials (undefined::Int16))
    checkBounds "Int32"   boundedRange   (approxBounds random trials (undefined::Int32))
    checkBounds "Int64"   boundedRange   (approxBounds random trials (undefined::Int64))
    checkBounds "Word"    boundedRange   (approxBounds random trials (undefined::Word))
    checkBounds "Word8"   boundedRange   (approxBounds random trials (undefined::Word8))
    checkBounds "Word16"  boundedRange   (approxBounds random trials (undefined::Word16))
    checkBounds "Word32"  boundedRange   (approxBounds random trials (undefined::Word32))
    checkBounds "Word64"  boundedRange   (approxBounds random trials (undefined::Word64))
    checkBounds "Double"  (False,0.0,1.0) (approxBounds random trials (undefined::Double))
    checkBounds "Float"   (False,0.0,1.0) (approxBounds random trials (undefined::Float))

    checkBounds "CChar"      boundedRange (approxBounds random trials (undefined:: CChar))
    checkBounds "CSChar"     boundedRange (approxBounds random trials (undefined:: CSChar))
    checkBounds "CUChar"     boundedRange (approxBounds random trials (undefined:: CUChar))
    checkBounds "CShort"     boundedRange (approxBounds random trials (undefined:: CShort))
    checkBounds "CUShort"    boundedRange (approxBounds random trials (undefined:: CUShort))
    checkBounds "CInt"       boundedRange (approxBounds random trials (undefined:: CInt))
    checkBounds "CUInt"      boundedRange (approxBounds random trials (undefined:: CUInt))
    checkBounds "CLong"      boundedRange (approxBounds random trials (undefined:: CLong))
    checkBounds "CULong"     boundedRange (approxBounds random trials (undefined:: CULong))
    checkBounds "CPtrdiff"   boundedRange (approxBounds random trials (undefined:: CPtrdiff))
    checkBounds "CSize"      boundedRange (approxBounds random trials (undefined:: CSize))
    checkBounds "CWchar"     boundedRange (approxBounds random trials (undefined:: CWchar))
    checkBounds "CSigAtomic" boundedRange (approxBounds random trials (undefined:: CSigAtomic))
    checkBounds "CLLong"     boundedRange (approxBounds random trials (undefined:: CLLong))
    checkBounds "CULLong"    boundedRange (approxBounds random trials (undefined:: CULLong))
    checkBounds "CIntPtr"    boundedRange (approxBounds random trials (undefined:: CIntPtr))
    checkBounds "CUIntPtr"   boundedRange (approxBounds random trials (undefined:: CUIntPtr))
    checkBounds "CIntMax"    boundedRange (approxBounds random trials (undefined:: CIntMax))
    checkBounds "CUIntMax"   boundedRange (approxBounds random trials (undefined:: CUIntMax))

  -- Then check all the range-restricted versions:
    checkBounds "Int R"     (False,-100,100)  (approxBounds (randomR (-100,100)) trials (undefined::Int))
    checkBounds "Integer R"
      (False,-100000000000000000000,100000000000000000000)
      (approxBounds (randomR (-100000000000000000000,100000000000000000000)) trials (undefined::Integer))
    checkBounds "Int8 R"    (False,-100,100)  (approxBounds (randomR (-100,100)) trials (undefined::Int8))
    checkBounds "Int8 Rsmall" (False,-50,50)  (approxBounds (randomR (-50,50))   trials (undefined::Int8))
    checkBounds "Int8 Rmini"    (False,3,4)   (approxBounds (randomR (3,4))      trials (undefined::Int8))
    checkBounds "Int8 Rtrivial" (False,3,3)   (approxBounds (randomR (3,3))      trials (undefined::Int8))

    checkBounds "Int16 R"   (False,-100,100)  (approxBounds (randomR (-100,100)) trials (undefined::Int16))
    checkBounds "Int32 R"   (False,-100,100)  (approxBounds (randomR (-100,100)) trials (undefined::Int32))
    checkBounds "Int64 R"   (False,-100,100)  (approxBounds (randomR (-100,100)) trials (undefined::Int64))
    checkBounds "Word R"    (False,0,200)     (approxBounds (randomR (0,200))    trials (undefined::Word))
    checkBounds "Word8 R"   (False,0,200)     (approxBounds (randomR (0,200))    trials (undefined::Word8))
    checkBounds "Word16 R"  (False,0,200)     (approxBounds (randomR (0,200))    trials (undefined::Word16))
    checkBounds "Word32 R"  (False,0,200)     (approxBounds (randomR (0,200))    trials (undefined::Word32))
    checkBounds "Word64 R"  (False,0,200)     (approxBounds (randomR (0,200))    trials (undefined::Word64))
    checkBounds "Double R" (False,10.0,77.0)  (approxBounds (randomR (10,77)) trials (undefined::Double))
    checkBounds "Float R"  (False,10.0,77.0)  (approxBounds (randomR (10,77)) trials (undefined::Float))

    checkBounds "CChar R"   (False,0,100)        (approxBounds (randomR (0,100))    trials (undefined:: CChar))
    checkBounds "CSChar R"  (False,-100,100)     (approxBounds (randomR (-100,100)) trials (undefined:: CSChar))
    checkBounds "CUChar R"  (False,0,200)        (approxBounds (randomR (0,200))    trials (undefined:: CUChar))
    checkBounds "CShort R"  (False,-100,100)     (approxBounds (randomR (-100,100)) trials (undefined:: CShort))
    checkBounds "CUShort R" (False,0,200)        (approxBounds (randomR (0,200))    trials (undefined:: CUShort))
    checkBounds "CInt R"    (False,-100,100)     (approxBounds (randomR (-100,100)) trials (undefined:: CInt))
    checkBounds "CUInt R"   (False,0,200)        (approxBounds (randomR (0,200))    trials (undefined:: CUInt))
    checkBounds "CLong R"   (False,-100,100)     (approxBounds (randomR (-100,100)) trials (undefined:: CLong))
    checkBounds "CULong R"     (False,0,200)     (approxBounds (randomR (0,200))    trials (undefined:: CULong))
    checkBounds "CPtrdiff R"   (False,-100,100)  (approxBounds (randomR (-100,100)) trials (undefined:: CPtrdiff))
    checkBounds "CSize R"      (False,0,200)     (approxBounds (randomR (0,200))    trials (undefined:: CSize))
    checkBounds "CWchar R"     (False,0,100)     (approxBounds (randomR (0,100))    trials (undefined:: CWchar))
    checkBounds "CSigAtomic R" (False,0,100)     (approxBounds (randomR (0,100))    trials (undefined:: CSigAtomic))
    checkBounds "CLLong R"     (False,-100,100)  (approxBounds (randomR (-100,100)) trials (undefined:: CLLong))
    checkBounds "CULLong R"    (False,0,200)     (approxBounds (randomR (0,200))    trials (undefined:: CULLong))
    checkBounds "CIntPtr R"    (False,-100,100)  (approxBounds (randomR (-100,100)) trials (undefined:: CIntPtr))
    checkBounds "CUIntPtr R"   (False,0,200)     (approxBounds (randomR (0,200))    trials (undefined:: CUIntPtr))
    checkBounds "CIntMax R"    (False,-100,100)  (approxBounds (randomR (-100,100)) trials (undefined:: CIntMax))
    checkBounds "CUIntMax R"   (False,0,200)     (approxBounds (randomR (0,200))    trials (undefined:: CUIntMax))

-- Untested:
-- instance Random Char where
-- instance Random Bool where
-- instance Random Integer where