The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Math::Random::MT;

use strict;
use Carp;
use DynaLoader;
use Time::HiRes qw(gettimeofday); # standard in Perl >= 5.8
use vars qw( @ISA $VERSION );

my $gen = undef;
@ISA = qw( DynaLoader );
$VERSION = '1.13';

bootstrap Math::Random::MT $VERSION;

sub new
{
    my ($class, @seeds) = @_;

    my $self = Math::Random::MT::init();
    $self->set_seed(@seeds);

    return $self;
}

sub set_seed
{
    my ($self, @seeds) = @_;
    @seeds > 1 ? $self->setup_array(@seeds) :
                 $self->init_seed($seeds[0] || _rand_seed());
    return $self->get_seed;
}

sub srand
{
    my (@seeds) = @_;
    $gen = Math::Random::MT->new(@seeds);
    return $gen->get_seed;
}

sub rand
{
    my ($self, $N) = @_;

    unless (ref $self) {
        $N = $self;
        Math::Random::MT::srand() unless defined $gen;
        $self = $gen;
    }

    return ($N || 1) * $self->genrand();
}

# Generate a random seed using the built-in PRNG.

sub _rand_seed {
    my ($self) = @_;

    # Seed rand with the same gettimeofday-based formula that is
    # used in Perl, and return an integer between 0 and 2**32-1.

    my ($s, $u) = gettimeofday;
    CORE::srand(1000003*$s+3*$u);
    return int(CORE::rand(2**32));
}

sub import
{
    no strict 'refs';
    my $pkg = caller;
    foreach my $sym (@_) {
        if ($sym eq "srand" || $sym eq "rand") {
            *{"${pkg}::$sym"} = \&$sym;
        }
    }
}

1;

__END__

=head1 NAME

Math::Random::MT - The Mersenne Twister PRNG

=head1 SYNOPSIS

  ## Object-oriented interface:
  use Math::Random::MT;
  $gen = Math::Random::MT->new()        # or...
  $gen = Math::Random::MT->new($seed);  # or...
  $gen = Math::Random::MT->new(@seeds);
  $seed = $gen->get_seed();             # seed used to generate the random numbers
  $rand = $gen->rand(42);               # random number in the interval [0, 42)
  $dice = int($gen->rand(6)+1);         # random integer between 1 and 6
  $coin = $gen->rand() < 0.5 ?          # flip a coin
    "heads" : "tails"

  ## Function-oriented interface:
  use Math::Random::MT qw(srand rand);
  # now use srand() and rand() as you usually do in Perl

=head1 DESCRIPTION

The Mersenne Twister is a pseudorandom number generator developed by
Makoto Matsumoto and Takuji Nishimura. It is described in their paper at
<URL:http://www.math.keio.ac.jp/~nisimura/random/doc/mt.ps>. This algorithm
has a very uniform distribution and is good for modelling purposes but do not
use it for cryptography.

This module implements two interfaces:

=head2 Object-oriented interface

=over

=item new()

Creates a new generator that is automatically seeded based on gettimeofday.

=item new($seed)

Creates a new generator seeded with an unsigned 32-bit integer.

=item new(@seeds)

Creates a new generator seeded with an array of (up to 624) unsigned
32-bit integers.

=item set_seed()

Seeds the generator. It takes the same arguments as I<new()>.

=item get_seed()

Retrieves the value of the seed used.

=item rand($num)

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

=back

=head2 Function-oriented interface

=over

=item rand($num)

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

=item srand($seed)

Behaves just like Perl's builtin srand(). As in Perl >= 5.14, the seed is
returned. If you use this interface, it is strongly recommended that you
call I<srand()> explicitly, rather than relying on I<rand()> to call it the
first time it is used.

=back

=head1 SEE ALSO

<URL:http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html>

Data::Entropy

=head1 ACKNOWLEDGEMENTS

=over 4

=item Sean M. Burke

For giving me the idea to write this module.

=item Philip Newton

For several useful patches.

=item Florent Angly

For implementing seed generation and retrieval.

=back

=head1 AUTHOR

Abhijit Menon-Sen <ams@toroid.org>

Copyright 2001 Abhijit Menon-Sen. All rights reserved.

Based on the C implementation of MT19937
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura

This software is distributed under a (three-clause) BSD-style license.
See the LICENSE file in the distribution for details.