The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

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 or MT_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's mts_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 or undefined values are taken as zero, excess values are ignored. Croaks unless you supply at least one non-zero value. Calls mtwist's mts_seedfull(). Returns nothing.

fastseed()

Seeds the generator with 4 bytes read from /dev/urandom (preferably via getrandom()) if available, otherwise from the system time (see details under timeseed()). Calls mtwist's mts_seed(). Returns the seed.

This method is called by new(MT_FASTSEED).

goodseed()

Seeds the generator with 4 bytes read from /dev/random (preferably via getrandom()) if available, otherwise from the system time (see details under timeseed()). Calls mtwist's mts_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 to goodseed(). Calls mtwist's mts_bestseed().

This method is called by new(MT_BESTSEED).

timeseed()

Seeds the generator from the current system time obtained from Time::HiRes::gettimeofday() by calculating seconds * 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 from gettimeofday(), so fast/good/bestseed() and srand() (w/o seed argument) call timeseed() 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 with getstate(). croak()s if $string is not a string of the correct size.

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 'L624i', getstate())[1..624,0];.

FLOATING POINT PRECISION

The rand() and rd_l* functions return whatever NVTYPE your Perl uses (i.e. quadmath, long double or double). A double gives you 53-bit precision. However, with larger double types you always get 64-bit precision since the mtwist library is limited to 64-bit. With quadmath or long double the corresponding math functions are used (sqrtq/sqrtl etc.).

The rand32() and non-l rd_* functions always return a double.

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 uses 64-bit integers, returns a 64-bit unsigned integer. If your Perl uses 32-bit integers but your OS knows the uint64_t type, returns a 64-bit unsigned integer as a decimal string. Otherwise it returns undef. Calls mtwist's mts_llrand().

rand(), rand($bound)

Returns a random double with 53-bit precision in the range [0, $bound). Calls mtwist's mts_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's mts_drand().

$bound may be negative. If $bound is omitted or zero it defaults to 1.

rd_iuniform(IV lower, IV upper)

Returns a signed integer in the range [lower, upper) of your Perl's IVTYPE (32-bit or 64-bit). Takes signed integer arguments.

rd_iuniform32(IV lower, IV upper)

Returns a signed 32-bit integer in the range [lower, upper). Takes signed 32-bit arguments.

rd_iuniform64(IV lower, IV upper)

Returns a signed 64-bit integer in the range [lower, upper) if your Perl uses 64-bit integers. Otherwise it returns undef. Note that unlike irand64() it doesn't return a decimal string in the 32-bit IV + uint64_t case because you could only pass it 32-bit arguments anyway.

randstr(), randstr($length)

Returns a random binary string. The default length is 8 bytes. Returns undef if there is not enough memory.

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 53-bit precision at the expense of speed.

TODO: If your Perl's NVs are long doubles, the rd_lxxx functions provide 64-bit precision.

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, Infs and subnormals (see POSIX::2008 for floating point check functions).

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 an optional argument $index to get the same result as with (rd_double())[$index], just a bit more efficiently.

rd_(l)uniform(NV lower, NV upper)

Generates floating point numbers from a uniform distribution in the range [lower, upper).

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