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 */ AbstractWell(final int k, final int m1, final int m2, final int m3)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 */ AbstractWell(final int k, final int m1, final int m2, final int m3, final int seed)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 */ AbstractWell(final int k, final int m1, final int m2, final int m3, final int[] seed)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 */ AbstractWell(final int k, final int m1, final int m2, final int m3, final long seed)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 setSeed(final int seed)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 setSeed(final int[] seed)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 setSeed(final long seed)178 public void setSeed(final long seed) { 179 setSeed(new int[] { (int) (seed >>> 32), (int) (seed & 0xffffffffl) }); 180 } 181 182 /** {@inheritDoc} */ 183 @Override next(final int bits)184 protected abstract int next(final int bits); 185 186 } 187