/* Filename: Rand/MersenneTwister.xs
* Author: George Schlossnagle <george@omniti.com>
* Theo Schlossnagle <jesus@omniti.com>
* Created: 3rd October 2002
* Version: 1.0.1
*
* Copyright (c) 2002 OmniTI Computer Consulting, Inc. All rights reserved.
* This program is free software; you can redistribute it and/or
* modify it under the same terms as Perl itself.
*
*/
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#define GENERATOR generator *
#ifndef PERL_VERSION
#include "patchlevel.h"
#define PERL_REVISION 5
#define PERL_VERSION PATCHLEVEL
#define PERL_SUBVERSION SUBVERSION
#endif
#if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
# define PL_sv_undef sv_undef
# define PL_na na
# define PL_curcop curcop
# define PL_compiling compiling
#endif
SV *sv_NULL ;
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#define omniti_uint32 unsigned int
#define MT_N (624)
#define N MT_N /* length of state vector */
#define M (397) /* a period parameter */
#define K (0x9908B0DFU) /* a magic constant */
#define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */
#define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */
#define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */
#define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */
typedef struct _generator {
omniti_uint32 state[MT_N+1]; /* state vector + 1 extra to not violate ANSI C */
omniti_uint32 *next; /* next random value is computed from here */
int left; /* can *next++ this many times before reloading */
} generator;
static generator *mt_init()
{
generator *gen;
gen = (generator *)malloc(sizeof(generator));
gen->next = NULL;
gen->left = -1;
return gen;
}
static void mt_free(generator *gen) {
if(gen)
free(gen);
}
static void mt_seed(generator *gen, omniti_uint32 seed)
{
omniti_uint32 x = (seed | 1U) & 0xFFFFFFFFU;
omniti_uint32 *s = gen->state;
int j;
for(gen->left = 0, *s++ = x, j = N; --j;
*s++ = (x *= 69069U) & 0xFFFFFFFFU);
}
static omniti_uint32 mt_reload(generator *gen)
{
omniti_uint32 *p0 = gen->state;
omniti_uint32 *p2 = gen->state + 2;
omniti_uint32 *pM = gen->state + M;
omniti_uint32 s0, s1;
int j;
if(gen->left < -1) {
mt_seed(gen, 4357U);
}
gen->left = N -1, gen->next = gen->state + 1;
for (s0 = gen->state[0], s1 = gen->state[1], j = N - M +1; --j; s0 = s1, s1 = *p2++)
*p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
for (pM = gen->state, j = M; --j; s0 = s1, s1 = *p2++)
*p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
s1 = gen->state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
s1 ^= (s1 >> 11);
s1 ^= (s1 << 7) & 0x9D2C5680U;
s1 ^= (s1 << 15) & 0xEFC60000U;
return s1 ^ (s1 >> 18);
}
static omniti_uint32 mt_rand(generator *gen)
{
omniti_uint32 y;
if(--(gen->left) < 0) {
return mt_reload(gen);
}
y = *(gen->next)++;
y ^= (y >> 11);
y ^= (y << 7) & 0x9D2C5680U;
y ^= (y << 15) & 0xEFC60000U;
return y ^ (y >> 18);
}
#define GENERATE_SEED() ((long) (time(0) * getpid() * 1000000))
static int
not_here(s)
char *s;
{
croak("%s not implemented on this architecture", s);
return -1;
}
static SV *
constant(name, arg)
char *name;
int arg;
{
errno = ENOENT;
return 0;
}
MODULE = Rand::MersenneTwister PACKAGE = Rand::MersenneTwister PREFIX = MT_
REQUIRE: 1.9505
PROTOTYPES: DISABLE
BOOT:
sv_NULL = newSVpv("", 0) ;
SV *
constant(name,arg)
char * name
int arg
GENERATOR
MT_mt_init()
PREINIT:
GENERATOR gen;
CODE:
gen = mt_init();
RETVAL = gen;
OUTPUT:
RETVAL
SV *
MT_mt_free(gen)
GENERATOR gen
CODE:
mt_free(gen);
RETVAL = &PL_sv_yes;
OUTPUT:
RETVAL
void
MT_mt_seed(gen, seed)
GENERATOR gen
SV * seed
PREINIT:
int seedval;
CODE:
{
seedval = SvIV(seed);
mt_seed(gen, seedval);
}
OUTPUT:
SV *
MT_mt_rand(gen, max=&PL_sv_undef)
GENERATOR gen
SV * max
PREINIT:
omniti_uint32 v;
double d;
CODE:
if(max != &PL_sv_undef) {
d = SvNV(max);
} else {
d = 1.0;
}
v = mt_rand(gen);
d *= (double)v/(double)(UINT_MAX+1.0);
RETVAL = newSVnv(d);
OUTPUT:
RETVAL