edu.cornell.lassp.houle.RngPack.Ranmar Maven / Gradle / Ivy
package edu.cornell.lassp.houle.RngPack;
import java.util.*;
import java.io.Serializable;
//
// RngPack 1.1a by Paul Houle
// http://www.honeylocust.com/RngPack/
//
/**
*
* RANMAR is a lagged Fibonacci generator proposed by Marsaglia and
* Zaman and is a good research grade generator. This version of
* RANMAR is based on the paper by James, which is a good
* reference for the properties of RANMAR and several other
* generators.
*
*
* REFERENCES:
*
* F. James, Comp. Phys. Comm. 60 (1990) p 329-344
*
* and was originally described in
*
* G. Marsaglia, A. Zaman and W.-W Tsang, Stat. Prob. Lett 9 (1990) p 35.
*
*
*
*
* Source code is available.
*
* @author Paul Houle (E-mail: [email protected])
* @version 1.1a
*/
public class Ranmar extends RandomSeedable implements Serializable {
double c,cd,cm,u[],uvec[] ;
int i97,j97 ;
/**
* Default seed. DEFSEED=54217137
*/
public static int DEFSEED=54217137;
/**
* The 46,009,220nd prime number,
* he largest prime less than 9*108. Used as a modulus
* because this version of RANMAR needs a seed between 0
* and 9*108 and BIG_PRIME
isn't commensurate
* with any regular period.
* BIG_PRIME= 899999963
*/
public static int BIG_PRIME=899999963;
/**
*
* Initialize Ranmar with a specified integer seed
*
* @param ijkl seed integer; Ranmar(int ijkl) takes uses
* ijkl modulus BIG_PRIME as a seed for RANMAR.
*
*/
public Ranmar(int ijkl)
{
ranmarin(Math.abs(ijkl % BIG_PRIME));
};
/**
*
* Initialize Ranmar with a specified long seed
*
* @param ijkl seed long; Ranmar(long ijkl) takes uses
* ijkl modulus BIG_PRIME as a seed for RANMAR.
*
*/
public Ranmar(long ijkl)
{
ranmarin((int) Math.abs(ijkl % BIG_PRIME));
};
/**
*
* Initialize Ranmar with a default seed taken from Marsaglia and
* Zaman's paper. Equivalent to Ranmar(54217137).
*
*/
public Ranmar()
{
ranmarin(DEFSEED);
};
/**
*
* Seed RANMAR from the clock.
*
*
* RandomElement e=new Ranmar(new Date());
*
*
* @param d a Date object to seed Ranmar with, typically new Date()
*
*/
public Ranmar(Date d) {
ranmarin((int) ClockSeed(d) % BIG_PRIME);
};
/**
*
* Internal methods: ranmarin is the initialization code for the
* generator.
*
*/
void ranmarin(int ijkl)
{
int ij,kl;
int i,ii,j,jj,k,l,m ;
double s,t ;
u = new double[97];
uvec = new double[97];
ij=ijkl/30082;
kl=ijkl-30082*ij;
i = ((ij/177) % 177) + 2 ;
j = (ij % 177) + 2 ;
k = ((kl/169) % 178) + 1 ;
l = kl % 169 ;
for (ii=0; ii<97; ii++)
{
s = 0.0 ;
t = 0.5 ;
for (jj=0; jj<24; jj++)
{
m = (((i*j) % 179) * k) % 179 ;
i = j ;
j = k ;
k = m ;
l = (53*l + 1) % 169 ;
if ( ((l*m) % 64) >= 32) s += t ;
t *= 0.5 ;
}
u[ii] = s ;
}
c = 362436.0 / 16777216.0 ;
cd = 7654321.0 / 16777216.0 ;
cm =16777213.0 / 16777216.0 ;
i97 = 96 ;
j97 = 32 ;
};
/**
* The generator
* @return a pseudo random number
*/
final public double raw() {
double uni;
uni=u[i97]-u[j97];
if (uni<0.0) uni+=1.0;
u[i97]=uni;
if (--i97<0) i97=96;
if (--j97<0) j97=96;
c-=cd;
if (c<0.0) c+=cm;
uni-=c;
if (uni<0.0) uni+=1.0;
return(uni);
};
/**
*
* A version of the generator for filling arrays, inlined for speed
*
* @param d an array of doubles to be filled
* @param n size of the array
*
*/
final public void raw(double d[],int n) {
double uni;
for(int i=0;i