NAME

Math::Random::MT::Auto - Auto-seeded Mersenne Twister PRNG

SYNOPSIS

use Math::Random::MT::Auto qw/rand32 rand/,
                           '/dev/urandom' => 500,
                           'random_org';

my $die_roll = int(rand(6)) + 1;

my $coin_flip = (rand32() & 1) ? 'heads' : 'tails';

DESCRIPTION

The Mersenne Twister is a fast pseudo-random number generator (PRNG) that is capable of providing large volumes (> 2.5 * 10^6004) of "high quality" pseudo-random data to applications that may exhaust available "truly" random data source or system-provided PRNGs such as rand.

This module provides two random number functions ("rand" and "rand32") that are based on the Mersenne Twister. Additionally, the PRNG is self-seeding, automatically acquiring a 624-long-integer random seed when the module is loaded.

The design philosophy for this module emphasizes speed and simplicity. (Hence, no OO interface which compromises both, as well as defeating the auto-seeding feature of this module.)

Quickstart

To use this module as a drop-in replacement for Perl's rand function, just add the following to the top of your application code:

use Math::Random::MT::Auto qw/rand/;

and then just use rand as you would normally. You don't even need to bother seeding the PRNG (i.e., you don't need to use srand), as that gets done automatically when the module is loaded by Perl.

CAUTION: If you want to require this module, see the "Delayed Importation" section for important information.

Seeding Sources

Starting the PRNG with a 624-long-integer random seed takes advantage of the PRNG's full range of possible internal vectors states. This module attempts to acquire such a seed using several user-selectable sources.

Random Devices

Most OSs offer some sort of device for acquiring random numbers. The most common are /dev/urandom and /dev/random. You can specify the use of these devices for acquiring the seed for the PRNG when you declare this module:

use Math::Random::MT::Auto '/dev/urandom';

or they can be specified when using the "srand" function.

srand('/dev/random');

The devices are accessed in non-blocking mode so that if there is insufficient data when they are read, the application will not hang waiting for more.

File of Binary Data

Since the above devices are just files as far as Perl is concerned, you can also use random data previously stored in files (in binary format). (The module looks for slashes or back-slashes to determine if the specified source is a device or file, and not one of the Internet sources below.)

srand('C:\\temp\\random.dat');
Internet Sites

This module provides support for acquiring seed data from two Internet sites: random.org and HotBits. An Internet connection and LWP::UserAgent are required to utilize these sources.

use Math::Random::MT::Auto 'random_org';
  # or
use Math::Random::MT::Auto 'hotbits';

If you connect to the Internet through an HTTP proxy, then you must set the http_proxy variable in your environment when using this source. (See "Proxy attributes" in LWP::UserAgent.)

The HotBits site will only provide a maximum of 512 long-ints of data per request. If you want to get the full seed from HotBits, then specify the hotbits source twice in the module declaration.

use Math::Random::MT::Auto 'hotbits', 'hotbits' => 112;

The default list of seeding sources is determined in a BEGIN block when the module is loaded. First, /dev/urandom and then /dev/random are checked. The first one found is added to the list, and then random_org is added.

These defaults can be overriden by specifying the desired sources when the module is declared, or through the use of the "srand" function.

Optionally, the maximum number of long-ints to be used from a source may be specified.

# Get at most 500 long-ints from random.org
# Finish the seed using data from /dev/urandom
use Math::Random::MT::Auto 'random_org' => 500,
                           '/dev/urandom';

(I would be interested to hear about other random data sources if they could easily be included in future versions of this module.)

Functions

By default, this module does not automatically export any of its functions. If you want to use them without the full module-path, then you must specify them when you declare the module.

use Math::Random::MT::Auto qw/rand rand32 srand seed state/;
rand($num)

Behaves exactly like Perl's builtin rand, returning a number uniformly distributed in [0, $num). ($num defaults to 1.)

rand32()

Returns a 32-bit random integer between 0 and 2^32-1 (0xFFFFFFFF) inclusive.

srand

This (re)seeds the PRNG. It should definitely be called when the :!auto option is used. Additionally, it may be called anytime reseeding of the PRNG is desired (although this should normally not be needed).

When called without arguments, the previously determined/specified seeding source(s) will be used to seed the PRNG.

Optionally, seeding sources may be supplied as arguments. (These will be saved and used again if "srand" is subsequently called without arguments).

srand('hotbits', '/dev/random');

If called with a subroutine reference, then that subroutine will be called to acquire the seeding data. The subroutine will be passed two arguments: A array reference where seed data is to be added, and the number of long-integers needed.

sub MySeeder
{
    my $seed = $_[0];
    my $need = $_[1];

    while ($need--) {
        my $long_int = ...;      # Get seed data from your source
        push(@$seed, $long_int);
    }
}

# Call MySeeder for 256 long-ints, and
#  then get the rest from random.org.
srand(\&MySeeder => 256, 'random_org');

If called with long-integer data (single value or an array), or an array reference of long-integers, these data will be passed to "seed" for use in reseeding the PRNG.

seed

When called without arguments, this function will return an array reference containing the seed last sent to the PRNG.

When called with long-integer data (single value or an array), or an array reference of long-integers, these data will be used to reseed the PRNG.

Together, these functions may be useful for setting up identical sequences of random numbers based on the same seed.

state

When called without arguments, this function returns an array reference containing the current state vector of the PRNG.

To reset the PRNG to a previous state, call this function with a previously obtained state-vector array reference.

# Get the current state of the PRNG
my $state_vector = state();

# Run the PRNG some more
my $rand1 = rand32();

# Restore the previous state of the PRNG
state($state_vector);

# Get another random number
my $rand2 = rand32();

# $rand1 and $rand2 will be equal.

CAUTION: It should go without saying that you should not modify the values in the state vector, but I'll say it anyway: "You should not modify the values in the state vector." 'Nough said.

In conjunction with Data::Dumper and do(file), this function can be used to save and then reload the state vector between application runs. See t/state1.t and t/state2.t in this module's distribution for an example of this.

Delayed Seeding

Normally, the PRNG is automatically seeded when the module is loaded. This behavior can be modified by supplying the :!auto (or :noauto) flag when the module is declared. (The PRNG will still be seeded using time and PID just in case.) When the :!auto option is used, the "srand" function should be imported, and then run before calling "rand" or "rand32".

use Math::Random::MT::Auto qw/rand srand :!auto/;
  ...
srand();
  ...
my $rn = rand(10);

Delayed Importation

When this module is imported via use, the PRNG is initialized via an INIT block that is executed right after the module is loaded. However, if you want to delay the importation of this module using require, then you must import "srand" and execute it so that the PRNG gets initialized:

eval {
    require Math::Random::MT::Auto;
    # Add other symbols to the import call, as desired.
    import Math::Random::MT::Auto qw/srand/;
    # Add optional arguments to the srand() call, as desired.
    srand();
};

(Otherwise, core dump! <Flame protection ON> For speed considerations, I purposely removed the code that checked if the PRNG was initialized because the check would get executed with every call to get a random number. <Flame protection off>)

DIAGNOSTICS

@Math::Random::MT::Auto::errors

This array contains information related to any problem encountered while trying to acquire seed data. It can be examined after the module is loaded, or after "srand" is called. After examining the messages, you can empty the array if desired.

@Math::Random::MT::Auto::errors = ();

This module sets a 10 second timeout for Internet connections so that if something goes awry when trying to get seed data from an Internet source, your application will not hang for an inordinate amount of time.

If you connect to the Internet through an HTTP proxy, then you must set the http_proxy variable in your environment when using the Internet seed sources. (See "Proxy attributes" in LWP::UserAgent.)

The HotBits site has a quota on the amount of data you can request in a 24-hour period. (I don't know how big the quota is.) Therefore, this source may fail to provide any data if used too often.

If the module cannot acquire any seed data from the specified sources, then the time() and PID will be used to seed the PRNG.

It is possible to seed the PRNG with more than 624 long-integers of data (through the use of a seeding subroutine supplied to "srand", or by supplying a large array ref of data to "seed"). However, doing so does not make the PRNG "more random" as 624 long-integers more than covers all the possible PRNG state vectors.

PERFORMANCE

This module is 50% faster than Math::Random::MT. (Most of this is due to the elimination of the OO interface.) The file samples/random, included in this module's distribution, can be used to compare timing results.

Depending on your connnection speed, acquiring seed data from the Internet may take a couple of seconds. This delay might be apparent when your application is first started. This is especially true if you specify the hotbits source twice (so as to get the full seed from the HotBits site) as this results in two accesses to the Internet. (If /dev/urandom is available on your machine, then you should definitely consider using the Internet sources only as a secondary source.)

SEE ALSO

The Mersenne Twister is the (current) quintessential pseudo-random number generator. It is fast, and has a period of 2^19937 - 1. The Mersenne Twister algorithm was developed by Makoto Matsumoto and Takuji Nishimura. http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html

random.org generates random numbers from radio frequency noise. http://random.org/

HotBits generates random number from a radioactive decay source. http://www.fourmilab.ch/hotbits/

OpenBSD random devices. http://www.openbsd.org/cgi-bin/man.cgi?query=arandom&sektion=4&apropos=0&manpath=OpenBSD+Current&arch=

FreeBSD random devices. http://www.freebsd.org/cgi/man.cgi?query=random&sektion=4&apropos=0&manpath=FreeBSD+5.3-RELEASE+and+Ports

Man pages for /dev/random and /dev/urandom on Unix/Linux/Cygwin/Solaris. http://www.die.net/doc/linux/man/man4/random.4.html

LWP::UserAgent

Math::Random::MT

Net::Random

AUTHOR

Jerry D. Hedden, <jdhedden AT 1979 DOT usna DOT com>

COPYRIGHT AND LICENSE

A C-program for MT19937, with initialization improved 2002/1/26. Coded by Takuji Nishimura and Makoto Matsumoto, and including Shawn Cokus's optimizations.

Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, All rights reserved. Copyright (C) 2005, Mutsuo Saito, All rights reserved. Copyright 2005 Jerry D. Hedden <jdhedden AT 1979 DOT usna DOT com>

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Any feedback is very welcome. <m-mat AT math DOT sci DOT hiroshima-u DOT ac DOT jp> http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html

1 POD Error

The following errors were encountered while parsing the POD:

Around line 475:

=back without =over