1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.math.random; 18 19 import java.io.Serializable; 20 21 22 /** This abstract class implements the WELL class of pseudo-random number generator 23 * from François Panneton, Pierre L'Ecuyer and Makoto Matsumoto. 24 25 * <p>This generator is described in a paper by François Panneton, 26 * Pierre L'Ecuyer and Makoto Matsumoto <a 27 * href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng.pdf">Improved 28 * Long-Period Generators Based on Linear Recurrences Modulo 2</a> ACM 29 * Transactions on Mathematical Software, 32, 1 (2006). The errata for the paper 30 * are in <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng-errata.txt">wellrng-errata.txt</a>.</p> 31 32 * @see <a href="http://www.iro.umontreal.ca/~panneton/WELLRNG.html">WELL Random number generator</a> 33 * @version $Revision: 1003892 $ $Date: 2010-10-02 23:28:56 +0200 (sam. 02 oct. 2010) $ 34 * @since 2.2 35 36 */ 37 public abstract class AbstractWell extends BitsStreamGenerator implements Serializable { 38 39 /** Serializable version identifier. */ 40 private static final long serialVersionUID = -817701723016583596L; 41 42 /** Current index in the bytes pool. */ 43 protected int index; 44 45 /** Bytes pool. */ 46 protected final int[] v; 47 48 /** Index indirection table giving for each index its predecessor taking table size into account. */ 49 protected final int[] iRm1; 50 51 /** Index indirection table giving for each index its second predecessor taking table size into account. */ 52 protected final int[] iRm2; 53 54 /** Index indirection table giving for each index the value index + m1 taking table size into account. */ 55 protected final int[] i1; 56 57 /** Index indirection table giving for each index the value index + m2 taking table size into account. */ 58 protected final int[] i2; 59 60 /** Index indirection table giving for each index the value index + m3 taking table size into account. */ 61 protected final int[] i3; 62 63 /** Creates a new random number generator. 64 * <p>The instance is initialized using the current time as the 65 * seed.</p> 66 * @param k number of bits in the pool (not necessarily a multiple of 32) 67 * @param m1 first parameter of the algorithm 68 * @param m2 second parameter of the algorithm 69 * @param m3 third parameter of the algorithm 70 */ 71 protected AbstractWell(final int k, final int m1, final int m2, final int m3) { 72 this(k, m1, m2, m3, System.currentTimeMillis()); 73 } 74 75 /** Creates a new random number generator using a single int seed. 76 * @param k number of bits in the pool (not necessarily a multiple of 32) 77 * @param m1 first parameter of the algorithm 78 * @param m2 second parameter of the algorithm 79 * @param m3 third parameter of the algorithm 80 * @param seed the initial seed (32 bits integer) 81 */ 82 protected AbstractWell(final int k, final int m1, final int m2, final int m3, final int seed) { 83 this(k, m1, m2, m3, new int[] { seed }); 84 } 85 86 /** Creates a new random number generator using an int array seed. 87 * @param k number of bits in the pool (not necessarily a multiple of 32) 88 * @param m1 first parameter of the algorithm 89 * @param m2 second parameter of the algorithm 90 * @param m3 third parameter of the algorithm 91 * @param seed the initial seed (32 bits integers array), if null 92 * the seed of the generator will be related to the current time 93 */ 94 protected AbstractWell(final int k, final int m1, final int m2, final int m3, final int[] seed) { 95 96 // the bits pool contains k bits, k = r w - p where r is the number 97 // of w bits blocks, w is the block size (always 32 in the original paper) 98 // and p is the number of unused bits in the last block 99 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 } 187