packages feed

real-dice-0.1.0.0: test/RealDice/RNGSpec.hs

{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}

{-# HLINT ignore "Use camelCase" #-}
module RealDice.RNGSpec
  ( returns_many_unique_integers,
    returns_many_unique_rolls,
    returns_0_for_inputs_under_1,
    returns_many_unique_floats,
    returns_floats_between_0_and_1,
    returns_many_unique_doubles,
    returns_doubles_between_0_and_1,
  )
where

import Control.Monad.State
import RealDice.DieSpec (returns_0_for_inputs_under_1, returns_many_unique_rolls)
import RealDice.RNG (RDGen, mkRDGen, randomDouble, randomFloat, randomIntR)
import Test.QuickCheck

data RandomState where
  RandomState :: {generator :: RDGen} -> RandomState

generateRandomNumbers :: Int -> [Int]
generateRandomNumbers n =
  evalState (generateRandomNumbersSinglePass 10 []) (RandomState (mkRDGen n))

generateRandomNumbersSinglePass :: Int -> [Int] -> State RandomState [Int]
generateRandomNumbersSinglePass 0 generatedNumbers = return generatedNumbers
generateRandomNumbersSinglePass i generatedNumbers = do
  randomSt <- get
  let (randomInteger, gen') = randomIntR (0, 1000) (generator randomSt)
  put RandomState {generator = gen'}
  generateRandomNumbersSinglePass (i - 1) (randomInteger : generatedNumbers)

returns_many_unique_integers :: Int -> Property
returns_many_unique_integers n =
  n > 0 ==>
    head (generateRandomNumbers n) `notElem` tail (generateRandomNumbers n)

generateRandomFloats :: Int -> [Float]
generateRandomFloats n =
  evalState (generateRandomFloatsSinglePass 10 []) (RandomState (mkRDGen n))

generateRandomFloatsSinglePass :: Int -> [Float] -> State RandomState [Float]
generateRandomFloatsSinglePass 0 generatedNumbers = return generatedNumbers
generateRandomFloatsSinglePass i generatedNumbers = do
  randomSt <- get
  let (randomFloat', gen') = randomFloat 4 (generator randomSt)
  put RandomState {generator = gen'}
  generateRandomFloatsSinglePass (i - 1) (randomFloat' : generatedNumbers)

returns_many_unique_floats :: Int -> Property
returns_many_unique_floats n =
  n > 0 ==>
    head (generateRandomFloats n) `notElem` tail (generateRandomFloats n)

returns_floats_between_0_and_1 :: Int -> Property
returns_floats_between_0_and_1 n =
  n > 0 ==>
    all (\x -> x >= 0 && x <= 1) (generateRandomFloats n)

generateRandomDoubles :: Int -> [Double]
generateRandomDoubles n =
  evalState (generateRandomDoublesSinglePass 10 []) (RandomState (mkRDGen n))

generateRandomDoublesSinglePass :: Int -> [Double] -> State RandomState [Double]
generateRandomDoublesSinglePass 0 generatedDoubles = return generatedDoubles
generateRandomDoublesSinglePass i generatedDoubles = do
  randomSt <- get
  let (randomDouble', gen') = randomDouble 4 (generator randomSt)
  put RandomState {generator = gen'}
  generateRandomDoublesSinglePass (i - 1) (randomDouble' : generatedDoubles)

returns_many_unique_doubles :: Int -> Property
returns_many_unique_doubles n =
  n > 0 ==>
    head (generateRandomDoubles n) `notElem` tail (generateRandomDoubles n)

returns_doubles_between_0_and_1 :: Int -> Property
returns_doubles_between_0_and_1 n =
  n > 0 ==>
    all (\x -> x >= 0 && x <= 1) (generateRandomDoubles n)