Portability | CPP, FFI |
---|---|
Stability | experimental |
Maintainer | Don Stewart <dons@galois.com> |
Tested with: GHC 6.8.2
Generate pseudo-random numbers using the SIMD-oriented Fast Mersenne Twister(SFMT)
pseudorandom number generator. This is a much faster generator than
the default System.Random
generator for Haskell (~50x faster
generation for Doubles, on a core 2 duo), however, it is not
nearly as flexible.
This library may be compiled with the '-f use_sse2' or '-f use_altivec' flags to configure, on intel and powerpc machines respectively, to enable high performance vector instructions to be used. This typically results in a 2-3x speedup in generation time.
This will work for newer intel chips such as Pentium 4s, and Core, Core2* chips.
The random number generator
A single, global SIMD fast mersenne twister random number generator This generator is evidence that you have initialised the generator,
Initialising the generator
newMTGen :: Maybe Word32 -> IO MTGenSource
Return an initialised SIMD Fast Mersenne Twister. The generator is initialised based on the clock time, if Nothing is passed as a seed. For deterministic behaviour, pass an explicit seed.
Due to the current SFMT library being vastly impure, currently only a single generator is allowed per-program. Attempts to reinitialise it will fail.
Random values of various types
Instances MTRandom for Word, Word64, Word32, Word16, Word8 all return, quickly, a random inhabintant of that type, in its full range. Similarly for Int types.
Int and Word will be 32 bits on a 32 bit machine, and 64 on a 64 bit machine. The double precision will be 32 bits on a 32 bit machine, and 53 on a 64 bit machine.
The MTRandom instance for Double returns a Double in the interval [0,1). The Bool instance takes the lower bit off a random word.
Given an initialised SFMT generator, the MTRandom allows the programmer to extract values of a variety of types.
Minimal complete definition: random
.
The same as randomR
, but using a default range determined by the type:
randoms :: MTGen -> IO [a]Source
Plural variant of random
, producing an infinite list of
random values instead of returning a new generator.
A variant of random
that uses the global random number generator
(see System.Random).
Essentially a convenience function if you're already in IO.
Note that there are performance penalties calling randomIO in an
inner loop, rather than random
applied to a global generator. The
cost comes in retrieving the random gen from an IORef, which is
non-trivial. Expect a 3x slow down in speed of random generation.
There is a single, implicit, global random number generator of type
StdGen
, held in some global variable maintained by the IO
monad. It is
initialised automatically in some system-dependent fashion. To get
deterministic behaviour, use setStdGen
.
getStdRandom :: (MTGen -> IO a) -> IO aSource
Uses the supplied function to get a value from the current global
random generator, and updates the global generator with the new
generator returned by the function. For example, rollDice
gets a
random integer between 1 and 6:
rollDice :: IO Int rollDice = getMTRandom (randomR (1,6))
Miscellaneous
Returns the identification string for the SMFT version. The string shows the word size, the Mersenne exponent, and all parameters of this generator.
An example, calculation of pi via a monte carlo method:
import System.Random.Mersenne import System.Environment
We'll roll the dice lim
times,
main = do [lim] <- mapM readIO =<< getArgs
Now, define a loop that runs this many times, plotting a x
and y
position, then working out if its in and outside the circle.
The ratio of inside/total points at then gives us an approximation
of pi.
let go :: Int -> Int -> IO Double go throws ins | throws >= lim = return ((4 * fromIntegral ins) / (fromIntegral throws)) | otherwise = do x <- random g :: IO Double y <- random g :: IO Double if x * x + y * y < 1 then go (throws+1) $! ins + 1 else go (throws+1) ins
Compiling this, '-fexcess-precision', for accurate Doubles,
$ ghc -fexcess-precision -fvia-C pi.hs -o pi $ ./pi 10000000 3.1417304