/*
* $Id: lecuyer.c,v 1.1.1.1 2005/09/18 22:03:44 dhmunro Exp $
* small, fast, portable, certified good random number generator
* L'Ecuyer, Mathematics of Computation, 65, pp 203-213 (1996)
*/
/* Copyright (c) 2005, The Regents of the University of California.
* All rights reserved.
* This file is part of yorick (http://yorick.sourceforge.net).
* Read the accompanying LICENSE file for details.
*/
#include "lecuyer.h"
/* three non-zero uncertified but most likely random numbers */
unsigned long le_generator[3] = { 0x9ad5e0d7, 0xf08ff6d8, 0xe7ed3a47 };
unsigned long
le_next(unsigned long *g)
{
if (!g) g = le_generator;
{
unsigned long s1 = g[0];
unsigned long s2 = g[1];
unsigned long s3 = g[2];
unsigned long b = (((s1 & 0x0007ffff) << 13) ^ s1) >> 19;
s1 = ((s1 & 0x000ffffe) << 12) ^ b;
b = (((s2 & 0x3fffffff) << 2) ^ s2) >> 25;
s2 = ((s2 & 0x0ffffff8) << 4) ^ b;
b = (((s3 & 0x1fffffff) << 3) ^ s3) >> 11;
s3 = ((s3 & 0x00007ff0) << 17) ^ b;
g[0] = s1;
g[1] = s2;
g[2] = s3;
return s1 ^ s2 ^ s3;
}
}
double
le_random(unsigned long *g)
{
/* 1/(2^32-1) */
return 2.3283064370807974e-10*(le_next(g)-0.5001);
}
void
le_nrandom(unsigned long *g, long n, double *r)
{
if (!g) g = le_generator;
{
unsigned long s1 = g[0];
unsigned long s2 = g[1];
unsigned long s3 = g[2];
unsigned long b;
while ((n--)>0) {
b = (((s1 & 0x0007ffff) << 13) ^ s1) >> 19;
s1 = ((s1 & 0x000ffffe) << 12) ^ b;
b = (((s2 & 0x3fffffff) << 2) ^ s2) >> 25;
s2 = ((s2 & 0x0ffffff8) << 4) ^ b;
b = (((s3 & 0x1fffffff) << 3) ^ s3) >> 11;
s3 = ((s3 & 0x00007ff0) << 17) ^ b;
*(r++)= 2.3283064370807974e-10*((s1^s2^s3)-0.5001);
}
g[0] = s1;
g[1] = s2;
g[2] = s3;
}
}
void
le_iseed(unsigned long *g, unsigned long seed)
{
/* initialize the L'Ecuyer random sequence at an arbitrary place
* 0 starts at a "standard" place */
if (!g) g = le_generator;
g[0] = 0x9ad5e0d7;
g[1] = 0xf08ff6d8;
g[2] = 0xe7ed3a47;
seed &= 0xffffffff;
if (seed) {
g[seed&1] = seed; /* never get same sequence as seed=0 */
le_next(g);
le_next(g);
le_next(g);
}
}
void
le_rseed(unsigned long *g, double seed)
{
/* 2^32-1 */
unsigned long lseed = (seed<=0. || seed>=1.)? 0 :
((unsigned long)(4294967295.0*seed) + 1);
le_iseed(g, lseed);
}
syntax highlighted by Code2HTML, v. 0.9.1