NAME
Math::Random::MTwist - A fast stateful Mersenne Twister pseudo-random number generator.
SYNOPSIS
# object-oriented inteface
use Math::Random::MTwist;
my $mt = Math::Random::MTwist->new(); # seed from /dev/urandom
my $int = $mt->irand(); # [0 .. 2^64-1 or 2^32-1]
my $double = $mt->rand(73); # [0 .. 73)
$mt->goodseed(); # seed from /dev/random
$mt->savestate("/tmp/foobar"); # save current state to file
$mt->loadstate("/tmp/foobar"); # load past state from file
my @dist = map $mt->rd_triangular(1, 3, 2), 1 .. 1e3; # triangular dist.
# function-oriented interface (OO interface may be used in parallel)
use Math::Random::MTwist qw(seed32 seedfull
timeseed fastseed goodseed bestseed);
use Math::Random::MTwist qw(:seed) # gives you all of the above
use Math::Random::MTwist qw(srand rand rand32 irand irand32 irand64);
use Math::Random::MTwist qw(:rand); # gives you all of the above
use Math::Random::MTwist qw(rd_exponential rd_triangular rd_normal ...);
use Math::Random::MTwist qw(:dist); # gives you all of the above
use Math::Random::MTwist qw(savestate loadstate getstate setstate);
use Math::Random::MTwist qw(:state); # gives you all of the above
use Math::Random::MTwist qw(:all); # import all functions
DESCRIPTION
Math::Random::MTwist is a Perl interface to Geoff Kuenning's mtwist C library. It provides several seeding methods and various random number distributions.
All functions are available through a function-oriented interface and an object-oriented interface. The function-oriented interface maintains a single global state while the OO interface gives you an individual state per instance.
The function-oriented interface provides drop-in replacements for Perl's built-in rand()
and srand()
functions.
If you use
the module with an import list, the global state is seeded automatically using fastseed()
. In this case, if you need the MT_
constants, you must import them explicitly through the :DEFAULT
tag.
CONSTRUCTOR
- new(), new($seed)
-
Takes an optional argument specifying the seed. If you omit the seed,
MT_FASTSEED
is the default.The seed can be a number (will be coerced to an unsigned 32-bit integer), an array reference holding up to 624 such numbers (missing values are padded with zeros, excess values are ignored) or one of the special values
MT_TIMESEED
,MT_FASTSEED
,MT_GOODSEED
orMT_BESTSEED
that choose one of the corresponding seeding methods (see below).Each instance maintains an individual PRNG state allowing multiple independent random number streams.
SEEDING
- seed32($number)
-
Seeds the generator with
$number
, coercing it to an unsigned 32-bit integer. Calls mtwist'smts_seed32new()
. Returns the seed. - srand(), srand($number)
-
Calls
seed32
if$number
is given,fastseed()
otherwise. Returns the seed. - seedfull($seeds)
-
Seeds the generator with up to 624 numbers from the array reference
$seeds
. The values are coerced to unsigned 32-bit integers. Missing values are taken as zero, excess values are ignored. Calls mtwist'smts_seedfull()
. Returns nothing. - fastseed()
-
Seeds the generator with 4 bytes read from
/dev/urandom
if available, otherwise from the system time (see details undertimeseed()
). Calls mtwist'smts_seed()
. Returns the seed.This method is called by
new(MT_FASTSEED)
. - goodseed()
-
Seeds the generator with 4 bytes read from
/dev/random
if available, otherwise from the system time (see details undertimeseed()
). Calls mtwist'smts_goodseed()
. Returns the seed.This method is called by
new(MT_GOODSEED)
. - bestseed()
-
Seeds the generator with 642 integers read from
/dev/random
if available. This might take a very long time and is probably not worth the waiting. If/dev/random
is unavailable or there was a reading error it falls back togoodseed()
. Calls mtwist'smts_bestseed()
.This method is called by
new(MT_BESTSEED)
. - timeseed()
-
Seeds the generator from the current system time obtained from
Time::HiRes::gettimeofday()
by calculatingseconds * 1e6 + microseconds
and coercing the result to an unsigned 32-bit integer. Returns the seed.This method is called by
new(MT_TIMESEED)
.timeseed
doesn't correspond to any of mtwist's functions. The rationale behind it is that mtwist uses the system time if neither/dev/urandom
nor/dev/random
is available. On Windows, the time source it uses has only millisecond resolution in contrast to microseconds fromgettimeofday()
, sofast/good/bestseed()
andsrand()
(w/o seed argument) calltimeseed()
directly in this case.
STATE HANDLING
- savestate($filename or $filehandle)
-
Saves the current state of the generator to a file given either by a filename (file will be truncated) or an open Perl file handle.
Returns 1 on success, 0 on error (you might want to check
$!
). - loadstate($filename or $filehandle)
-
Loads the state of the generator from a file given either by a filename or an open Perl file handle.
Returns 1 on success, 0 on error (you might want to check
$!
). - getstate()
-
Returns the current state of the generator as a binary string.
- setstate($string)
-
Sets the state of the generator from
$string
, which you should have obtained withgetstate()
.
savestate()
and loadstate()
are portable because they save the state as decimal numbers. getstate()
and setstate()
are not portable because they simply use a memory dump for laziness reasons.
However, depending on your system's architecture, you can convert getstate()
to savestate()
format using something like join ' ', (reverse unpack 'L*', getstate())[2..625,1];
.
UNIFORMLY DISTRIBUTED RANDOM NUMBERS
- irand()
-
Returns a random unsigned integer, 64-bit if your system supports it (see
irand64()
), 32-bit otherwise. - irand32()
-
Returns a random unsigned 32-bit integer. Calls mtwist's
mts_lrand()
. - irand64()
-
If your Perl is 64-bit, returns a 64-bit unsigned integer. If your Perl is 32-bit but your OS knows the
uint64_t
type, returns a 64-bit unsigned integer coerced to a double (so it's the full 64-bit range but with only 52-bit precision). Otherwise it returns undef. Calls mtwist'smts_llrand()
. - rand(), rand($bound)
-
Returns a random double with 52-bit precision in the range
[0, $bound)
. Calls mtwist'smts_ldrand()
.$bound
may be negative. If$bound
is omitted or zero it defaults to 1. - rand32(), rand32($bound)
-
Returns a random double with 32-bit precision in the range
[0, $bound)
. Slightly faster than rand(). Calls mtwist'smts_drand()
.$bound
may be negative. If$bound
is omitted or zero it defaults to 1.
NON-UNIFORMLY DISTRIBUTED RANDOM NUMBERS
With the exception of rd_double()
the following methods come in two variants: rd_xxx
and rd_lxxx
. They all return a double but the rd_xxx
versions provide 32-bit precision while the rd_lxxx
versions provide 52-bit precision at the expense of speed.
- rd_double(), rd_double($index)
-
This is kind of a FUNction (that's the "Fun with flags" sort of fun).
It generates a random double in the complete (signed) double range. It does that by drawing a random 64-bit integer (if available, otherwise two 32-bit integers) and interpreting the bit pattern as a double. That's the same as saying
unpack 'd', pack 'Q', irand64()
. The results follow a Benford distribution (each range [2^n, 2^(n+1)[ can hold 2^52 values). Be prepared to meet some NaNs and Infs.In scalar context it returns a double. In list context it returns the double, the corresponding integer (undef if your Perl doesn't have 64-bit integers) and the packed string representation.
For convenience, you can call rd_double() with and optional argument $index to get the same result as with (rd_double())[$index], just a bit more efficiently.
- rd_(l)exponential(double mean)
-
Generates an exponential distribution with the given mean.
- rd_(l)erlang(int k, double mean)
-
Generates an Erlang-k distribution with the given mean.
- rd_(l)weibull(double shape, double scale)
-
Generates a Weibull distribution with the given shape and scale.
- rd_(l)normal(double mean, double sigma)
-
Generates a normal (Gaussian) distribution with the given mean and standard deviation sigma.
- rd_(l)lognormal(double shape, double scale)
-
Generates a log-normal distribution with the given shape and scale.
- rd_(l)triangular(double lower, double upper, double mode)
-
Generates a triangular distribution in the range
[lower, upper)
with the given mode.
EXPORTS
By default the module exports the constants MT_TIMESEED, MT_FASTSEED, MT_GOODSEED and MT_BESTSEED that can be used as an argument to the constructor.
The following export tags are available:
- :dist
-
rd_double rd_erlang rd_lerlang rd_exponential rd_lexponential rd_lognormal rd_llognormal rd_normal rd_lnormal rd_triangular rd_ltriangular rd_weibull rd_lweibull
- :rand
-
rand rand rand32 rand64 irand irand32 irand64
- :seed
-
seed32 seedfull timeseed fastseed goodseed bestseed
- :state
-
savestate loadstate getstate setstate
- :all
-
All of the above.
- :DEFAULT
-
MT_TIMESEED MT_FASTSEED MT_GOODSEED MT_BESTSEED
NOTES
This module is not fork()/clone()
aware, i.e. you have to take care of re-seeding/re-instantiating in new processes/threads yourself.
Imported functions and OO methods have the same names. This works by symbol table "redirection", e.g. non-OO irand() is actually _irand() internally and so on (note the underscore). The minor drawback is that you can't use fully qualified names like Math::Random::MTwist::irand()
etc. Instead you have to say Math::Random::MTwist::_irand()
. I considered avoiding this by checking if the first argument is a blessed reference but I discarded that in favor of speed.
SEE ALSO
http://www.cs.hmc.edu/~geoff/mtwist.html
Math::Random::MT and Math::Random::MT::Auto are significantly slower than Math::Random::MTwist. MRMA has some additional sophisticated features but it depends on non-core modules.
AUTHOR
Carsten Gaebler (cgpan ʇɐ gmx ʇop de). I only accept encrypted e-mails, either via SMIME or GPG.
COPYRIGHT
Perl and XS portion: Copyright © 2014 by Carsten Gaebler.
mtwist C library: Copyright © 2001, 2002, 2010, 2012, 2013 by Geoff Kuenning.
LICENSE
Perl and XS portion: WTFPL.
mtwist C library: LGPL