001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.math.random; 018 019 import java.io.Serializable; 020 021 022 /** This abstract class implements the WELL class of pseudo-random number generator 023 * from François Panneton, Pierre L'Ecuyer and Makoto Matsumoto. 024 025 * <p>This generator is described in a paper by François Panneton, 026 * Pierre L'Ecuyer and Makoto Matsumoto <a 027 * href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng.pdf">Improved 028 * Long-Period Generators Based on Linear Recurrences Modulo 2</a> ACM 029 * Transactions on Mathematical Software, 32, 1 (2006). The errata for the paper 030 * are in <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng-errata.txt">wellrng-errata.txt</a>.</p> 031 032 * @see <a href="http://www.iro.umontreal.ca/~panneton/WELLRNG.html">WELL Random number generator</a> 033 * @version $Revision: 1003892 $ $Date: 2010-10-02 23:28:56 +0200 (sam. 02 oct. 2010) $ 034 * @since 2.2 035 036 */ 037 public abstract class AbstractWell extends BitsStreamGenerator implements Serializable { 038 039 /** Serializable version identifier. */ 040 private static final long serialVersionUID = -817701723016583596L; 041 042 /** Current index in the bytes pool. */ 043 protected int index; 044 045 /** Bytes pool. */ 046 protected final int[] v; 047 048 /** Index indirection table giving for each index its predecessor taking table size into account. */ 049 protected final int[] iRm1; 050 051 /** Index indirection table giving for each index its second predecessor taking table size into account. */ 052 protected final int[] iRm2; 053 054 /** Index indirection table giving for each index the value index + m1 taking table size into account. */ 055 protected final int[] i1; 056 057 /** Index indirection table giving for each index the value index + m2 taking table size into account. */ 058 protected final int[] i2; 059 060 /** Index indirection table giving for each index the value index + m3 taking table size into account. */ 061 protected final int[] i3; 062 063 /** Creates a new random number generator. 064 * <p>The instance is initialized using the current time as the 065 * seed.</p> 066 * @param k number of bits in the pool (not necessarily a multiple of 32) 067 * @param m1 first parameter of the algorithm 068 * @param m2 second parameter of the algorithm 069 * @param m3 third parameter of the algorithm 070 */ 071 protected AbstractWell(final int k, final int m1, final int m2, final int m3) { 072 this(k, m1, m2, m3, System.currentTimeMillis()); 073 } 074 075 /** Creates a new random number generator using a single int seed. 076 * @param k number of bits in the pool (not necessarily a multiple of 32) 077 * @param m1 first parameter of the algorithm 078 * @param m2 second parameter of the algorithm 079 * @param m3 third parameter of the algorithm 080 * @param seed the initial seed (32 bits integer) 081 */ 082 protected AbstractWell(final int k, final int m1, final int m2, final int m3, final int seed) { 083 this(k, m1, m2, m3, new int[] { seed }); 084 } 085 086 /** Creates a new random number generator using an int array seed. 087 * @param k number of bits in the pool (not necessarily a multiple of 32) 088 * @param m1 first parameter of the algorithm 089 * @param m2 second parameter of the algorithm 090 * @param m3 third parameter of the algorithm 091 * @param seed the initial seed (32 bits integers array), if null 092 * the seed of the generator will be related to the current time 093 */ 094 protected AbstractWell(final int k, final int m1, final int m2, final int m3, final int[] seed) { 095 096 // the bits pool contains k bits, k = r w - p where r is the number 097 // of w bits blocks, w is the block size (always 32 in the original paper) 098 // and p is the number of unused bits in the last block 099 final int w = 32; 100 final int r = (k + w - 1) / w; 101 this.v = new int[r]; 102 this.index = 0; 103 104 // precompute indirection index tables. These tables are used for optimizing access 105 // they allow saving computations like "(j + r - 2) % r" with costly modulo operations 106 iRm1 = new int[r]; 107 iRm2 = new int[r]; 108 i1 = new int[r]; 109 i2 = new int[r]; 110 i3 = new int[r]; 111 for (int j = 0; j < r; ++j) { 112 iRm1[j] = (j + r - 1) % r; 113 iRm2[j] = (j + r - 2) % r; 114 i1[j] = (j + m1) % r; 115 i2[j] = (j + m2) % r; 116 i3[j] = (j + m3) % r; 117 } 118 119 // initialize the pool content 120 setSeed(seed); 121 122 } 123 124 /** Creates a new random number generator using a single long seed. 125 * @param k number of bits in the pool (not necessarily a multiple of 32) 126 * @param m1 first parameter of the algorithm 127 * @param m2 second parameter of the algorithm 128 * @param m3 third parameter of the algorithm 129 * @param seed the initial seed (64 bits integer) 130 */ 131 protected AbstractWell(final int k, final int m1, final int m2, final int m3, final long seed) { 132 this(k, m1, m2, m3, new int[] { (int) (seed >>> 32), (int) (seed & 0xffffffffl) }); 133 } 134 135 /** Reinitialize the generator as if just built with the given int seed. 136 * <p>The state of the generator is exactly the same as a new 137 * generator built with the same seed.</p> 138 * @param seed the initial seed (32 bits integer) 139 */ 140 @Override 141 public void setSeed(final int seed) { 142 setSeed(new int[] { seed }); 143 } 144 145 /** Reinitialize the generator as if just built with the given int array seed. 146 * <p>The state of the generator is exactly the same as a new 147 * generator built with the same seed.</p> 148 * @param seed the initial seed (32 bits integers array), if null 149 * the seed of the generator will be related to the current time 150 */ 151 @Override 152 public void setSeed(final int[] seed) { 153 154 if (seed == null) { 155 setSeed(System.currentTimeMillis()); 156 return; 157 } 158 159 System.arraycopy(seed, 0, v, 0, Math.min(seed.length, v.length)); 160 161 if (seed.length < v.length) { 162 for (int i = seed.length; i < v.length; ++i) { 163 final long l = v[i - seed.length]; 164 v[i] = (int) ((1812433253l * (l ^ (l >> 30)) + i) & 0xffffffffL); 165 } 166 } 167 168 index = 0; 169 170 } 171 172 /** Reinitialize the generator as if just built with the given long seed. 173 * <p>The state of the generator is exactly the same as a new 174 * generator built with the same seed.</p> 175 * @param seed the initial seed (64 bits integer) 176 */ 177 @Override 178 public void setSeed(final long seed) { 179 setSeed(new int[] { (int) (seed >>> 32), (int) (seed & 0xffffffffl) }); 180 } 181 182 /** {@inheritDoc} */ 183 @Override 184 protected abstract int next(final int bits); 185 186 }