/* *
 * Title:
 * Description:
 * Copyright:
 * Notice:
 * @Version
 */



package umontreal.iro.lecuyer.rng; 

import umontreal.iro.lecuyer.util.BitVector;
import umontreal.iro.lecuyer.util.BitMatrix;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import java.io.FileNotFoundException;
import java.io.IOException;


/**
 * This class implements the {@link RandomStream} interface via inheritance from
 * {@link RandomStreamBase}. The backbone generator is a Well Equidistributed
 * Long period Linear Random Number Generator (WELL), proposed by F.
 *  Panneton, and which has a state size
 * of 512 bits and a period length of approximatively
 *  2512. The values of V, W and Z are 2150,
 * 2200 and 2350 respectively (see {@link RandomStream} for their
 * definition). The seed of the RNG, and the state of a stream at any given
 * step, is a 16-dimensional vector of 32-bit integers.
 * 
 * 

* This implementation requires about * 70K of memory to run. This memory is shared between all instances of the * class, and is only loaded when the first instance is created. * */ public class WELL512 extends RandomStreamBase { private static final long serialVersionUID = 70510L; //La date de modification a l'envers, lire 10/05/2007 private static final double NORM = (1.0 / 0x100000001L); private static final int W = 32; private static final int R = 16; private static final int P = 0; private static final int M1 = 13; private static final int M2 = 9; private static final int M3 = 5; private static final int MASK = 0xF; // = 15 //state variables private int state_i; private int[] state; //stream and substream variables : private int[] stream; private int[] substream; private static int[] curr_stream; //the state transition matrices private static BitMatrix Apw; private static BitMatrix Apz; // if the generator was initialised private static boolean initialised = false; // P(z) = {0xa7600001, 0xe0f4f3e2, 0xcb30e185, 0x7d6b79a9, // 0xf3d46237, 0x13a524cb, 0x38e3c2d2, 0xa1381bcb, // 0xf7ab5f06, 0x04a72cda, 0x4e302521, 0xaca072f1, // 0x4dd96181, 0x24aa25c9, 0x3c417e7, 0x0, 0x1} // Ce tableau represente les 512 coefficients du polynome suivant // (z^(2^200) mod P(z)) mod 2 // P(z) est le polynome caracteristique du generateur. private static final int [] pw = new int[] {0x280009a9, 0x31e221d0, 0xa00c0296, 0x763d492b, 0x63875b75, 0xef2acc3a, 0x1400839f, 0x5e0c8526, 0x514e11b, 0x56b398e4, 0x9436c8b9, 0xa6d8130b, 0xc0a48a78, 0x26ad57d0, 0xa3a0c62a, 0x3ff16c9b}; // Ce tableau represente les 512 coefficients du polynome suivant // (z^(2^350) mod P(z)) mod 2 // P(z) est le polynome caracteristique du generateur. private static final int [] pz = new int[] {0xcd68f2fe, 0x183e969a, 0x760449ae, 0xaa0ce54e, 0xfb5363af, 0x79deea9b, 0xef66c516, 0x103543cb, 0x244d1a97, 0x7570bc91, 0x31203fc7, 0x455ea2ca, 0xd77d327d, 0xd8c6a83c, 0xc51b05e7, 0x300c1501}; private static void initialisation() { // initialise all of the state variables curr_stream = new int[] {0xA341BF9A, 0xAFE4901B, 0x6B10DE18, 0x05FE1420, 0xE48B1A9C, 0x590AE15E, 0xC5EB82A7, 0x37EAB2F9, 0x90E1C6EA, 0x3AE63902, 0x735DC91C, 0x902E3A8C, 0x6CB28A5D, 0x8474E7D1, 0x843E01A3, 0x5A7370EF}; //reading the state transition matrices /* try { InputStream is = WELL512.class.getClassLoader(). getResourceAsStream("umontreal/iro/lecuyer/rng/WELL512.dat"); ObjectInputStream ois = new ObjectInputStream(is); Apw = (BitMatrix)ois.readObject(); Apz = (BitMatrix)ois.readObject(); ois.close(); } catch(FileNotFoundException e) { System.err.println("Couldn't find WELL512.dat"); e.printStackTrace(); System.exit(1); } catch(IOException e) { e.printStackTrace(); System.exit(1); } catch(ClassNotFoundException e) { e.printStackTrace(); System.exit(1); } */ initialised = true; } /* private void advanceSeed(int[] seed, BitMatrix bm) { BitVector bv = new BitVector(seed, 512); bv = bm.multiply(bv); for(int i = 0; i < R; i++) seed[i] = bv.getInt(i); } */ private void advanceSeed(int[] seed, int [] p) { int b; int [] x = new int[R]; for (int i = 0; i < R; i++) { state[i] = seed[i]; } state_i = 0; for (int j = 0; j < R; ++j) { b = p[j]; for (int k = 0; k < W; ++k) { if ((b & 1) == 1) { for (int i = 0; i < R; i++) { x[i] ^= state[(state_i + i) & MASK]; } } b >>= 1; nextValue(); } } for (int i = 0; i < R; i++) { seed[i] = x[i]; } } private static void verifySeed(int[] seed) { if (seed.length < R) throw new IllegalArgumentException("Seed must contain " + R + "values"); for (int i = 0; i < R; i++) if (seed[i] != 0) return; throw new IllegalArgumentException ("At least one of the element of the seed must not be 0."); } private WELL512(int i) { //unit vector (to build the state transition matrice) state = new int[R]; for(int j = 0; j < R; j++) state[j] = 0; state[i / W] = 1 << (i % W); state_i = 0; } /** * Constructs a new stream. * */ public WELL512() { if (!initialised) initialisation(); state = new int[R]; stream = new int[R]; substream = new int[R]; for(int i = 0; i < R; i++) stream[i] = curr_stream[i]; // advanceSeed(curr_stream, Apz); advanceSeed(curr_stream, pz); resetStartStream(); } /** * Constructs a new stream with the identifier name * (used in the toString method). * * @param name name of the stream * */ public WELL512 (String name) { this(); this.name = name; } /** * Sets the initial seed of the class WELL512 to the 16 * integers of the vector seed[0..15]. * This will be the initial seed of the class of the next created stream. * At least one of the integers must be non-zero. * * @param seed array of 16 elements representing the seed * * */ public static void setPackageSeed (int seed[]) { verifySeed(seed); if (!initialised) initialisation(); for(int i = 0; i < R; i++) curr_stream[i] = seed[i]; } /** * This method is discouraged for normal use. * Initializes the stream at the beginning of a stream with the initial * seed seed[0..15]. The seed must satisfy the same * conditions as in setPackageSeed. * This method only affects the specified stream; the others are not * modified. Hence after calling this method, the beginning of the streams * will no longer be spaced Z values apart. * For this reason, this method should only be used in very exceptional cases; * proper use of the reset... methods and of the stream constructor is * preferable. * * @param seed array of 16 elements representing the seed * * */ public void setSeed (int seed[]) { verifySeed(seed); for(int i = 0; i < R; i++) stream[i] = seed[i]; resetStartStream(); } /** * Returns the current state of the stream, represented as an * array of 16 integers. * * @return the current state of the stream * */ public int[] getState() { int[] result = new int[R]; for(int i = 0; i < R; i++) result[i] = state[(state_i + i) & MASK]; return result; } /** * Clones the current generator and return its copy. * * @return A deep copy of the current generator * */ public WELL512 clone() { WELL512 retour = null; retour = (WELL512)super.clone(); retour.state = new int[R]; retour.substream = new int[R]; retour.stream = new int[R]; for (int i = 0; i>> 11)); state[state_i] = z1 ^ z2; state[(state_i + 15) & MASK] = (z0 ^ (z0 << 2)) ^ (z1 ^ (z1 << 18)) ^ (z2 << 28) ^ (state[state_i] ^ ((state[state_i] << 5) & 0xDA442D24)); state_i = (state_i + 15) & MASK; long result = state[state_i]; return (double)(result > 0 ? result : (result + 0x100000000L)) * NORM; } /** * This method is only meant to be used during the compilation process. * It is used to create the resource file the class need in order to * run. * */ public static void main(String[] args) { if(args.length < 1) { System.err.println("Must provide the output file."); System.exit(1); } //computes the state transition matrices System.out.println("Creating the WELL512 state transition matrices."); //the state transition matrices BitMatrix STp0, STpw, STpz; BitVector[] bv = new BitVector[512]; WELL512 well; int[] vect = new int[R]; for(int i = 0; i < 512; i++) { well = new WELL512(i); well.nextValue(); for(int j = 0; j < R; j++) vect[j] = well.state[(well.state_i + j) & MASK]; bv[i] = new BitVector(vect, 512); } STp0 = (new BitMatrix(bv)).transpose(); STpw = STp0.power2e(200); STpz = STpw.power2e(150); try { FileOutputStream fos = new FileOutputStream(args[0]); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(STpw); oos.writeObject(STpz); oos.close(); } catch(FileNotFoundException e) { System.err.println("Couldn't create " + args[0]); e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } } }

Ads help maintain this website.