-- | Test standard RandomGen interface of Random123-backed generators.
module TestRandomGen (test_randomgen) where
import System.Random
import Test.Framework (testGroup)
import Test.Framework.Providers.HUnit
import Test.HUnit
import System.Random.Random123
-- Expected mean and standard deviation for a list of uniformly distributed random floats
num_floats = 10000
e_mean = 0.5
e_var = 1 / 12
e_std = sqrt e_var
e_mean_std = e_std / sqrt (fromIntegral num_floats)
e_std_std = sqrt ((e_var ** 2) / (fromIntegral num_floats - 1) * 2)
-- Functions to calculate mean and stddev of a list (not very effective)
mean xs = sum xs / fromIntegral (length xs)
std xs = sqrt (sum xsquares / fromIntegral (length xs)) where
xmean = mean xs
xsquares = map (\x -> (x - xmean) ** 2) xs
-- Check that mean and stddev of a generated list are inside [-5,5] sigma interval
-- around their expected values (chance of failure ~1e-6).
test_gen32_mean = (xmean < e_mean + 5 * e_std && xmean > e_mean - 5 * e_std) @?= True where
gen = mkCBRNG32 123456
floats = take num_floats (randoms gen :: [Float])
xmean = mean floats
test_gen32_std = (xstd < e_std + 5 * e_std_std && xstd > e_std - 5 * e_std_std) @?= True where
gen = mkCBRNG32 123456
floats = take num_floats (randoms gen :: [Float])
xstd = std floats
test_gen64_mean = (xmean < e_mean + 5 * e_std && xmean > e_mean - 5 * e_std) @?= True where
gen = mkCBRNG64 123456
floats = take num_floats (randoms gen :: [Float])
xmean = mean floats
test_gen64_std = (xstd < e_std + 5 * e_std_std && xstd > e_std - 5 * e_std_std) @?= True where
gen = mkCBRNG64 123456
floats = take num_floats (randoms gen :: [Float])
xstd = std floats
test_randomgen = testGroup "RandomGen" [
testCase "Default 32-bit (mean of array of floats)" test_gen32_mean,
testCase "Default 32-bit (std of array of floats)" test_gen32_std,
testCase "Default 64-bit (mean of array of floats)" test_gen64_mean,
testCase "Default 64-bit (std of array of floats)" test_gen64_std
]