Portability | portable |
---|---|
Stability | experimental |
Maintainer | bos@serpentine.com |
Pseudo-random number generation. This module contains code for generating high quality random numbers that follow either a uniform or normal distribution.
The uniform PRNG uses Marsaglia's MWC256 (also known as MWC8222) multiply-with-carry generator, which has a period of 2^8222 and fares well in tests of randomness. It is also extremely fast, between 2 and 3 times faster than the Mersenne Twister.
- data Gen s
- type GenIO = Gen (PrimState IO)
- type GenST s = Gen (PrimState (ST s))
- data Seed
- class Unbox a => Variate a where
- normal :: PrimMonad m => Gen (PrimState m) -> m Double
- create :: PrimMonad m => m (Gen (PrimState m))
- initialize :: PrimMonad m => Vector Word32 -> m (Gen (PrimState m))
- withSystemRandom :: PrimMonad m => (Gen (PrimState m) -> m a) -> IO a
- save :: PrimMonad m => Gen (PrimState m) -> m Seed
- restore :: PrimMonad m => Seed -> m (Gen (PrimState m))
- uniformVector :: (PrimMonad m, Variate a) => Gen (PrimState m) -> Int -> m (Vector a)
Types
class Unbox a => Variate a whereSource
The class of types for which we can generate uniformly distributed random variates.
The uniform PRNG uses Marsaglia's MWC256 (also known as MWC8222) multiply-with-carry generator, which has a period of 2^8222 and fares well in tests of randomness. It is also extremely fast, between 2 and 3 times faster than the Mersenne Twister.
Note: Marsaglia's PRNG is not known to be cryptographically secure, so you should not use it for cryptographic operations.
uniform :: PrimMonad m => Gen (PrimState m) -> m aSource
Generate a single uniformly distributed random variate. The range of values produced varies by type:
- For fixed-width integral types, the type's entire range is used.
- For floating point numbers, the range (0,1] is used. Zero is
explicitly excluded, to allow variates to be used in
statistical calculations that require non-zero values
(e.g. uses of the
log
function). - The range of random
Integer
variates is the same as forInt
.
To generate a Float
variate with a range of [0,1), subtract
2**(-33). To do the same with Double
variates, subtract
2**(-53).
Variate Bool | |
Variate Double | |
Variate Float | |
Variate Int | |
Variate Int8 | |
Variate Int16 | |
Variate Int32 | |
Variate Int64 | |
Variate Word | |
Variate Word8 | |
Variate Word16 | |
Variate Word32 | |
Variate Word64 | |
(Variate a, Variate b) => Variate (a, b) | |
(Variate a, Variate b, Variate c) => Variate (a, b, c) | |
(Variate a, Variate b, Variate c, Variate d) => Variate (a, b, c, d) |
Other distributions
normal :: PrimMonad m => Gen (PrimState m) -> m DoubleSource
Generate a normally distributed random variate.
The implementation uses Doornik's modified ziggurat algorithm. Compared to the ziggurat algorithm usually used, this is slower, but generates more independent variates that pass stringent tests of randomness.
Creation
create :: PrimMonad m => m (Gen (PrimState m))Source
Create a generator for variates using a fixed seed.
initialize :: PrimMonad m => Vector Word32 -> m (Gen (PrimState m))Source
Create a generator for variates using the given seed, of which up to 256 elements will be used. For arrays of less than 256 elements, part of the default seed will be used to finish initializing the generator's state.
Examples:
initialize (singletonU 42)
initialize (toU [4, 8, 15, 16, 23, 42])
If a seed contains fewer than 256 elements, it is first used
verbatim, then its elements are xor
ed against elements of the
default seed until 256 elements are reached.
withSystemRandom :: PrimMonad m => (Gen (PrimState m) -> m a) -> IO aSource
Seed a PRNG with data from the system's fast source of pseudo-random numbers ("/dev/urandom" on Unix-like systems), then run the given action.
Note: on Windows, this code does not yet use the native Cryptographic API as a source of random numbers (it uses the system clock instead). As a result, the sequences it generates may not be highly independent.
State management
Helper functions
uniformVector :: (PrimMonad m, Variate a) => Gen (PrimState m) -> Int -> m (Vector a)Source
Generate a vector of pseudo-random variates. This is not
necessarily faster than invoking uniform
repeatedly in a loop,
but it may be more convenient to use in some situations.
References
- Doornik, J.A. (2005) An improved ziggurat method to generate normal random samples. Mimeo, Nuffield College, University of Oxford. http://www.doornik.com/research/ziggurat.pdf
- Doornik, J.A. (2007) Conversion of high-period random numbers to floating point. ACM Transactions on Modeling and Computer Simulation 17(1). http://www.doornik.com/research/randomdouble.pdf
- Marsaglia, G. (2003) Seeds for random number generators. Communications of the ACM 46(5):90–93. http://doi.acm.org/10.1145/769800.769827
- Thomas, D.B.; Leong, P.G.W.; Luk, W.; Villasenor, J.D. (2007). Gaussian random number generators. ACM Computing Surveys 39(4). http://www.cse.cuhk.edu.hk/~phwl/mt/public/archives/papers/grng_acmcs07.pdf