http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/MersenneTwister.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/MersenneTwister.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/MersenneTwister.java new file mode 100644 index 0000000..7ae5fd8 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/MersenneTwister.java @@ -0,0 +1,230 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.source32; + +import java.util.Arrays; +import org.apache.commons.math4.exception.InsufficientDataException; +import org.apache.commons.math4.rng.internal.util.NumberFactory; + +/** + * This class implements a powerful pseudo-random number generator + * developed by Makoto Matsumoto and Takuji Nishimura during + * 1996-1997. + * + * <p> + * This generator features an extremely long period + * (2<sup>19937</sup>-1) and 623-dimensional equidistribution up to + * 32 bits accuracy. The home page for this generator is located at + * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html"> + * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html</a>. + * </p> + * + * <p> + * This generator is described in a paper by Makoto Matsumoto and + * Takuji Nishimura in 1998: + * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf"> + * Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random + * Number Generator</a>, + * ACM Transactions on Modeling and Computer Simulation, Vol. 8, No. 1, + * January 1998, pp 3--30 + * </p> + * + * <p> + * This class is mainly a Java port of the + * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html"> + * 2002-01-26 version of the generator</a> written in C by Makoto Matsumoto + * and Takuji Nishimura. Here is their original copyright: + * </p> + * + * <table border="0" width="80%" cellpadding="10" align="center" bgcolor="#E0E0E0"> + * <tr><td>Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + * All rights reserved.</td></tr> + * + * <tr><td>Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * <ol> + * <li>Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer.</li> + * <li>Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution.</li> + * <li>The names of its contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission.</li> + * </ol></td></tr> + * + * <tr><td><strong>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE.</strong></td></tr> + * </table> + * + * @since 4.0 + */ +public class MersenneTwister extends IntProvider { + /** Mask 32 most significant bits. */ + private static final long INT_MASK_LONG = 0xffffffffL; + /** Most significant w-r bits. */ + private static final long UPPER_MASK_LONG = 0x80000000L; + /** Least significant r bits */ + private static final long LOWER_MASK_LONG = 0x7fffffffL; + /** Most significant w-r bits. */ + private static final int UPPER_MASK = 0x80000000; + /** Least significant r bits */ + private static final int LOWER_MASK = 0x7fffffff; + /** Size of the bytes pool. */ + private static final int N = 624; + /** Period second parameter. */ + private static final int M = 397; + /** X * MATRIX_A for X = {0, 1}. */ + private static final int[] MAG01 = { 0x0, 0x9908b0df }; + /** Bytes pool. */ + private int[] mt = new int[N]; + /** Current index in the bytes pool. */ + private int mti; + + /** + * Creates a new random number generator. + * + * @param seed Initial seed. + */ + public MersenneTwister(int[] seed) { + setSeedInternal(seed); + } + + /** {@inheritDoc} */ + @Override + protected byte[] getStateInternal() { + final int[] s = Arrays.copyOf(mt, N + 1); + s[N] = mti; + + return NumberFactory.makeByteArray(s); + } + + /** {@inheritDoc} */ + @Override + protected void setStateInternal(byte[] s) { + if (s.length != (N + 1) * 4) { + throw new InsufficientDataException(); + } + + final int[] tmp = NumberFactory.makeIntArray(s); + + System.arraycopy(tmp, 0, mt, 0, N); + mti = tmp[N]; + } + + /** + * Reinitializes the generator as if just built with the given seed. + * + * @param seed Initial seed. + */ + private void setSeedInternal(int[] seed) { + initState(19650218); + int i = 1; + int j = 0; + + for (int k = Math.max(N, seed.length); k != 0; k--) { + final long l0 = (mt[i] & LOWER_MASK_LONG) | ((mt[i] < 0) ? UPPER_MASK_LONG : 0); + final long l1 = (mt[i-1] & LOWER_MASK_LONG) | ((mt[i-1] < 0) ? UPPER_MASK_LONG : 0); + final long l = (l0 ^ ((l1 ^ (l1 >> 30)) * 1664525l)) + seed[j] + j; // non linear + mt[i] = (int) (l & INT_MASK_LONG); + i++; j++; + if (i >= N) { + mt[0] = mt[N - 1]; + i = 1; + } + if (j >= seed.length) { + j = 0; + } + } + + for (int k = N - 1; k != 0; k--) { + final long l0 = (mt[i] & LOWER_MASK_LONG) | ((mt[i] < 0) ? UPPER_MASK_LONG : 0); + final long l1 = (mt[i-1] & LOWER_MASK_LONG) | ((mt[i-1] < 0) ? UPPER_MASK_LONG : 0); + final long l = (l0 ^ ((l1 ^ (l1 >> 30)) * 1566083941l)) - i; // non linear + mt[i] = (int) (l & INT_MASK_LONG); + i++; + if (i >= N) { + mt[0] = mt[N - 1]; + i = 1; + } + } + + mt[0] = UPPER_MASK; // MSB is 1; assuring non-zero initial array + } + + /** + * Initialize the internal state of this instance. + * + * @param seed Seed. + */ + private void initState(int seed) { + long longMT = seed & INT_MASK_LONG; + mt[0]= (int) longMT; + for (mti = 1; mti < N; ++mti) { + longMT = (1812433253L * (longMT ^ (longMT >> 30)) + mti) & INT_MASK_LONG; + mt[mti]= (int) longMT; + } + } + + /** {@inheritDoc} */ + @Override + public int next() { + int y; + + if (mti >= N) { // Generate N words at one time. + int mtNext = mt[0]; + for (int k = 0; k < N - M; ++k) { + int mtCurr = mtNext; + mtNext = mt[k + 1]; + y = (mtCurr & UPPER_MASK) | (mtNext & LOWER_MASK); + mt[k] = mt[k + M] ^ (y >>> 1) ^ MAG01[y & 1]; + } + for (int k = N - M; k < N - 1; ++k) { + int mtCurr = mtNext; + mtNext = mt[k + 1]; + y = (mtCurr & UPPER_MASK) | (mtNext & LOWER_MASK); + mt[k] = mt[k + (M - N)] ^ (y >>> 1) ^ MAG01[y & 1]; + } + y = (mtNext & UPPER_MASK) | (mt[0] & LOWER_MASK); + mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ MAG01[y & 1]; + + mti = 0; + } + + y = mt[mti++]; + + // Tempering. + y ^= y >>> 11; + y ^= (y << 7) & 0x9d2c5680; + y ^= (y << 15) & 0xefc60000; + y ^= y >>> 18; + + return y; + } +}
http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/RandomIntSource.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/RandomIntSource.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/RandomIntSource.java new file mode 100644 index 0000000..88f420c --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/RandomIntSource.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math4.rng.internal.source32; + +/** + * Source of randomness that generate values of type {@code int}. + * + * @since 4.0 + */ +public interface RandomIntSource { + /** + * @return the next random value. + */ + int next(); +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/Well1024a.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/Well1024a.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well1024a.java new file mode 100644 index 0000000..86c84c3 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well1024a.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.source32; + +/** + * This class implements the WELL1024a pseudo-random number generator + * from François Panneton, Pierre L'Ecuyer and Makoto Matsumoto. + * <p> + * This generator is described in a paper by François Panneton, + * Pierre L'Ecuyer and Makoto Matsumoto + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng.pdf"> + * Improved Long-Period Generators Based on Linear Recurrences Modulo 2</a> + * ACM Transactions on Mathematical Software, 32, 1 (2006). + * The errata for the paper are in + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng-errata.txt">wellrng-errata.txt</a>. + * </p> + * + * @see <a href="http://www.iro.umontreal.ca/~panneton/WELLRNG.html">WELL Random number generator</a> + * @since 4.0 + */ +public class Well1024a extends AbstractWell { + /** Number of bits in the pool. */ + private static final int K = 1024; + /** First parameter of the algorithm. */ + private static final int M1 = 3; + /** Second parameter of the algorithm. */ + private static final int M2 = 24; + /** Third parameter of the algorithm. */ + private static final int M3 = 10; + /** The indirection index table. */ + private static final IndexTable TABLE = new IndexTable(K, M1, M2, M3); + + /** + * Creates a new random number generator. + * + * @param seed Initial seed. + */ + public Well1024a(int[] seed) { + super(K, seed); + } + + /** {@inheritDoc} */ + @Override + public int next() { + final int indexRm1 = TABLE.getIndexPred(index); + + final int v0 = v[index]; + final int vM1 = v[TABLE.getIndexM1(index)]; + final int vM2 = v[TABLE.getIndexM2(index)]; + final int vM3 = v[TABLE.getIndexM3(index)]; + + final int z0 = v[indexRm1]; + final int z1 = v0 ^ (vM1 ^ (vM1 >>> 8)); + final int z2 = (vM2 ^ (vM2 << 19)) ^ (vM3 ^ (vM3 << 14)); + final int z3 = z1 ^ z2; + final int z4 = (z0 ^ (z0 << 11)) ^ (z1 ^ (z1 << 7)) ^ (z2 ^ (z2 << 13)); + + v[index] = z3; + v[indexRm1] = z4; + index = indexRm1; + + return z4; + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/Well19937a.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/Well19937a.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well19937a.java new file mode 100644 index 0000000..7f83ddf --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well19937a.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.source32; + +/** + * This class implements the WELL19937a pseudo-random number generator + * from François Panneton, Pierre L'Ecuyer and Makoto Matsumoto. + * <p> + * This generator is described in a paper by François Panneton, + * Pierre L'Ecuyer and Makoto Matsumoto + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng.pdf"> + * Improved Long-Period Generators Based on Linear Recurrences Modulo 2</a> + * ACM Transactions on Mathematical Software, 32, 1 (2006). + * The errata for the paper are in + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng-errata.txt">wellrng-errata.txt</a>. + * </p> + * + * @see <a href="http://www.iro.umontreal.ca/~panneton/WELLRNG.html">WELL Random number generator</a> + * @since 4.0 + */ +public class Well19937a extends AbstractWell { + /** Number of bits in the pool. */ + private static final int K = 19937; + /** First parameter of the algorithm. */ + private static final int M1 = 70; + /** Second parameter of the algorithm. */ + private static final int M2 = 179; + /** Third parameter of the algorithm. */ + private static final int M3 = 449; + /** The indirection index table. */ + private static final IndexTable TABLE = new IndexTable(K, M1, M2, M3); + + /** + * Creates a new random number generator. + * + * @param seed Initial seed. + */ + public Well19937a(int[] seed) { + super(K, seed); + } + + /** {@inheritDoc} */ + @Override + public int next() { + final int indexRm1 = TABLE.getIndexPred(index); + final int indexRm2 = TABLE.getIndexPred2(index); + + final int v0 = v[index]; + final int vM1 = v[TABLE.getIndexM1(index)]; + final int vM2 = v[TABLE.getIndexM2(index)]; + final int vM3 = v[TABLE.getIndexM3(index)]; + + final int z0 = (0x80000000 & v[indexRm1]) ^ (0x7FFFFFFF & v[indexRm2]); + final int z1 = (v0 ^ (v0 << 25)) ^ (vM1 ^ (vM1 >>> 27)); + final int z2 = (vM2 >>> 9) ^ (vM3 ^ (vM3 >>> 1)); + final int z3 = z1 ^ z2; + final int z4 = z0 ^ (z1 ^ (z1 << 9)) ^ (z2 ^ (z2 << 21)) ^ (z3 ^ (z3 >>> 21)); + + v[index] = z3; + v[indexRm1] = z4; + v[indexRm2] &= 0x80000000; + index = indexRm1; + + return z4; + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/Well19937c.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/Well19937c.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well19937c.java new file mode 100644 index 0000000..25b9d03 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well19937c.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.source32; + +/** + * This class implements the WELL19937c pseudo-random number generator + * from François Panneton, Pierre L'Ecuyer and Makoto Matsumoto. + * <p> + * This generator is described in a paper by François Panneton, + * Pierre L'Ecuyer and Makoto Matsumoto + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng.pdf"> + * Improved Long-Period Generators Based on Linear Recurrences Modulo 2</a> + * ACM Transactions on Mathematical Software, 32, 1 (2006). + * The errata for the paper are in + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng-errata.txt">wellrng-errata.txt</a>. + * </p> + * + * @see <a href="http://www.iro.umontreal.ca/~panneton/WELLRNG.html">WELL Random number generator</a> + * @since 2.2 + */ +public class Well19937c extends AbstractWell { + /** Number of bits in the pool. */ + private static final int K = 19937; + /** First parameter of the algorithm. */ + private static final int M1 = 70; + /** Second parameter of the algorithm. */ + private static final int M2 = 179; + /** Third parameter of the algorithm. */ + private static final int M3 = 449; + /** The indirection index table. */ + private static final IndexTable TABLE = new IndexTable(K, M1, M2, M3); + + /** + * Creates a new random number generator. + * + * @param seed Initial seed. + */ + public Well19937c(int[] seed) { + super(K, seed); + } + + /** {@inheritDoc} */ + @Override + public int next() { + final int indexRm1 = TABLE.getIndexPred(index); + final int indexRm2 = TABLE.getIndexPred2(index); + + final int v0 = v[index]; + final int vM1 = v[TABLE.getIndexM1(index)]; + final int vM2 = v[TABLE.getIndexM2(index)]; + final int vM3 = v[TABLE.getIndexM3(index)]; + + final int z0 = (0x80000000 & v[indexRm1]) ^ (0x7FFFFFFF & v[indexRm2]); + final int z1 = (v0 ^ (v0 << 25)) ^ (vM1 ^ (vM1 >>> 27)); + final int z2 = (vM2 >>> 9) ^ (vM3 ^ (vM3 >>> 1)); + final int z3 = z1 ^ z2; + int z4 = z0 ^ (z1 ^ (z1 << 9)) ^ (z2 ^ (z2 << 21)) ^ (z3 ^ (z3 >>> 21)); + + v[index] = z3; + v[indexRm1] = z4; + v[indexRm2] &= 0x80000000; + index = indexRm1; + + // add Matsumoto-Kurita tempering + // to get a maximally-equidistributed generator + z4 ^= (z4 << 7) & 0xe46e1700; + z4 ^= (z4 << 15) & 0x9b868000; + + return z4; + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/Well44497a.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/Well44497a.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well44497a.java new file mode 100644 index 0000000..8b72b83 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well44497a.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.source32; + +/** + * This class implements the WELL44497a pseudo-random number generator + * from François Panneton, Pierre L'Ecuyer and Makoto Matsumoto. + * <p> + * This generator is described in a paper by François Panneton, + * Pierre L'Ecuyer and Makoto Matsumoto + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng.pdf"> + * Improved Long-Period Generators Based on Linear Recurrences Modulo 2</a> + * ACM Transactions on Mathematical Software, 32, 1 (2006). + * The errata for the paper are in + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng-errata.txt">wellrng-errata.txt</a>. + * </p> + * + * @see <a href="http://www.iro.umontreal.ca/~panneton/WELLRNG.html">WELL Random number generator</a> + * @since 4.0 + */ +public class Well44497a extends AbstractWell { + /** Number of bits in the pool. */ + private static final int K = 44497; + /** First parameter of the algorithm. */ + private static final int M1 = 23; + /** Second parameter of the algorithm. */ + private static final int M2 = 481; + /** Third parameter of the algorithm. */ + private static final int M3 = 229; + /** The indirection index table. */ + private static final IndexTable TABLE = new IndexTable(K, M1, M2, M3); + + /** + * Creates a new random number generator. + * + * @param seed Initial seed. + */ + public Well44497a(int[] seed) { + super(K, seed); + } + + /** {@inheritDoc} */ + @Override + public int next() { + final int indexRm1 = TABLE.getIndexPred(index); + final int indexRm2 = TABLE.getIndexPred2(index); + + final int v0 = v[index]; + final int vM1 = v[TABLE.getIndexM1(index)]; + final int vM2 = v[TABLE.getIndexM2(index)]; + final int vM3 = v[TABLE.getIndexM3(index)]; + + // the values below include the errata of the original article + final int z0 = (0xFFFF8000 & v[indexRm1]) ^ (0x00007FFF & v[indexRm2]); + final int z1 = (v0 ^ (v0 << 24)) ^ (vM1 ^ (vM1 >>> 30)); + final int z2 = (vM2 ^ (vM2 << 10)) ^ (vM3 << 26); + final int z3 = z1 ^ z2; + final int z2Prime = ((z2 << 9) ^ (z2 >>> 23)) & 0xfbffffff; + final int z2Second = ((z2 & 0x00020000) != 0) ? (z2Prime ^ 0xb729fcec) : z2Prime; + final int z4 = z0 ^ (z1 ^ (z1 >>> 20)) ^ z2Second ^ z3; + + v[index] = z3; + v[indexRm1] = z4; + v[indexRm2] &= 0xFFFF8000; + index = indexRm1; + + return z4; + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/Well44497b.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/Well44497b.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well44497b.java new file mode 100644 index 0000000..5300aba --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well44497b.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.source32; + +/** + * This class implements the WELL44497b pseudo-random number generator + * from François Panneton, Pierre L'Ecuyer and Makoto Matsumoto. + * <p> + * This generator is described in a paper by François Panneton, + * Pierre L'Ecuyer and Makoto Matsumoto + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng.pdf"> + * Improved Long-Period Generators Based on Linear Recurrences Modulo 2</a> + * ACM Transactions on Mathematical Software, 32, 1 (2006). + * The errata for the paper are in + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng-errata.txt">wellrng-errata.txt</a>. + * </p> + * + * @see <a href="http://www.iro.umontreal.ca/~panneton/WELLRNG.html">WELL Random number generator</a> + * @since 4.0 + */ +public class Well44497b extends AbstractWell { + /** Number of bits in the pool. */ + private static final int K = 44497; + /** First parameter of the algorithm. */ + private static final int M1 = 23; + /** Second parameter of the algorithm. */ + private static final int M2 = 481; + /** Third parameter of the algorithm. */ + private static final int M3 = 229; + /** The indirection index table. */ + private static final IndexTable TABLE = new IndexTable(K, M1, M2, M3); + + /** + * Creates a new random number generator. + * + * @param seed Initial seed. + */ + public Well44497b(int[] seed) { + super(K, seed); + } + + /** {@inheritDoc} */ + @Override + public int next() { + // compute raw value given by WELL44497a generator + // which is NOT maximally-equidistributed + final int indexRm1 = TABLE.getIndexPred(index); + final int indexRm2 = TABLE.getIndexPred2(index); + + final int v0 = v[index]; + final int vM1 = v[TABLE.getIndexM1(index)]; + final int vM2 = v[TABLE.getIndexM2(index)]; + final int vM3 = v[TABLE.getIndexM3(index)]; + + // the values below include the errata of the original article + final int z0 = (0xFFFF8000 & v[indexRm1]) ^ (0x00007FFF & v[indexRm2]); + final int z1 = (v0 ^ (v0 << 24)) ^ (vM1 ^ (vM1 >>> 30)); + final int z2 = (vM2 ^ (vM2 << 10)) ^ (vM3 << 26); + final int z3 = z1 ^ z2; + final int z2Prime = ((z2 << 9) ^ (z2 >>> 23)) & 0xfbffffff; + final int z2Second = ((z2 & 0x00020000) != 0) ? (z2Prime ^ 0xb729fcec) : z2Prime; + int z4 = z0 ^ (z1 ^ (z1 >>> 20)) ^ z2Second ^ z3; + + v[index] = z3; + v[indexRm1] = z4; + v[indexRm2] &= 0xFFFF8000; + index = indexRm1; + + // add Matsumoto-Kurita tempering + // to get a maximally-equidistributed generator + z4 ^= (z4 << 7) & 0x93dd1400; + z4 ^= (z4 << 15) & 0xfa118000; + + return z4; + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/Well512a.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/Well512a.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well512a.java new file mode 100644 index 0000000..1faf571 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/Well512a.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.source32; + +/** + * This class implements the WELL512a pseudo-random number generator + * from François Panneton, Pierre L'Ecuyer and Makoto Matsumoto. + * <p> + * This generator is described in a paper by François Panneton, + * Pierre L'Ecuyer and Makoto Matsumoto + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng.pdf"> + * Improved Long-Period Generators Based on Linear Recurrences Modulo 2</a> + * ACM Transactions on Mathematical Software, 32, 1 (2006). + * The errata for the paper are in + * <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng-errata.txt">wellrng-errata.txt</a>. + * </p> + * + * @see <a href="http://www.iro.umontreal.ca/~panneton/WELLRNG.html">WELL Random number generator</a> + * @since 4.0 + */ +public class Well512a extends AbstractWell { + /** Number of bits in the pool. */ + private static final int K = 512; + /** First parameter of the algorithm. */ + private static final int M1 = 13; + /** Second parameter of the algorithm. */ + private static final int M2 = 9; + /** Third parameter of the algorithm. */ + private static final int M3 = 5; + /** The indirection index table. */ + private static final IndexTable TABLE = new IndexTable(K, M1, M2, M3); + + /** + * Creates a new random number generator. + * + * @param seed Initial seed. + */ + public Well512a(int[] seed) { + super(K, seed); + } + + /** {@inheritDoc} */ + @Override + public int next() { + final int indexRm1 = TABLE.getIndexPred(index); + + final int vi = v[index]; + final int vi1 = v[TABLE.getIndexM1(index)]; + final int vi2 = v[TABLE.getIndexM2(index)]; + final int z0 = v[indexRm1]; + + // the values below include the errata of the original article + final int z1 = (vi ^ (vi << 16)) ^ (vi1 ^ (vi1 << 15)); + final int z2 = vi2 ^ (vi2 >>> 11); + final int z3 = z1 ^ z2; + final int z4 = (z0 ^ (z0 << 2)) ^ (z1 ^ (z1 << 18)) ^ (z2 << 28) ^ (z3 ^ ((z3 << 5) & 0xda442d24)); + + v[index] = z3; + v[indexRm1] = z4; + index = indexRm1; + + return z4; + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/package-info.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/package-info.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/package-info.java new file mode 100644 index 0000000..bb7d2e2 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/package-info.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * <h3> + * Concrete algorithms for {@code int}-based sources of randomness + * </h3> + * + * <p> + * <b>For internal use only:</b> Direct access to classes in this package + * is discouraged, as they could be modified without notice. + * </p> + * + * <p><b>Notes for developers</b></p> + * + * <ul> + * <li> + * A source of randomness must inherit from + * {@link org.apache.commons.math4.rng.internal.source32.IntProvider} + * </li> + * <li> + * The "provider" must specify <em>one</em> way for setting the seed. + * For a given seed, the generated sequence must always be the same. + * </li> + * <li> + * The "provider" must implement methods {@code getStateInternal} and + * {@code setStateInternal} in order to save and restore the state of an + * instance (cf. {@link org.apache.commons.math4.rng.internal.BaseProvider}). + * </li> + * <li> + * When a new class is implemented here, user-access to it must be provided + * through associated {@link org.apache.commons.math4.rng.RandomSource + * factory methods}. + * </li> + * </ul> + */ + +package org.apache.commons.math4.rng.internal.source32; http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source64/LongProvider.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source64/LongProvider.java b/src/main/java/org/apache/commons/math4/rng/internal/source64/LongProvider.java new file mode 100644 index 0000000..3e73f05 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source64/LongProvider.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math4.rng.internal.source64; + +import org.apache.commons.math4.exception.OutOfRangeException; +import org.apache.commons.math4.rng.internal.util.NumberFactory; +import org.apache.commons.math4.rng.internal.BaseProvider; + +/** + * Base class for all implementations that provide a {@code long}-based + * source randomness. + */ +public abstract class LongProvider + extends BaseProvider + implements RandomLongSource { + + /** {@inheritDoc} */ + @Override + public abstract long next(); + + /** {@inheritDoc} */ + @Override + public long nextLong() { + return next(); + } + + /** {@inheritDoc} */ + @Override + public int nextInt() { + return NumberFactory.makeInt(nextLong()); + } + + /** {@inheritDoc} */ + @Override + public double nextDouble() { + return NumberFactory.makeDouble(nextLong()); + } + + /** {@inheritDoc} */ + @Override + public boolean nextBoolean() { + return NumberFactory.makeBoolean(nextLong()); + } + + /** {@inheritDoc} */ + @Override + public float nextFloat() { + return NumberFactory.makeFloat(nextInt()); + } + + /** {@inheritDoc} */ + @Override + public void nextBytes(byte[] bytes) { + nextBytesFill(this, bytes, 0, bytes.length); + } + + /** {@inheritDoc} */ + @Override + public void nextBytes(byte[] bytes, + int start, + int len) { + if (start < 0 || + start >= bytes.length) { + throw new OutOfRangeException(start, 0, bytes.length); + } + if (len < 0 || + len > bytes.length - start) { + throw new OutOfRangeException(len, 0, bytes.length - start); + } + + nextBytesFill(this, bytes, start, len); + } + + /** + * Generates random bytes and places them into a user-supplied array. + * + * <p> + * The array is filled with bytes extracted from random {@code long} values. + * This implies that the number of random bytes generated may be larger than + * the length of the byte array. + * </p> + * + * @param source Source of randomness. + * @param bytes Array in which to put the generated bytes. Cannot be null. + * @param start Index at which to start inserting the generated bytes. + * @param len Number of bytes to insert. + */ + static void nextBytesFill(RandomLongSource source, + byte[] bytes, + int start, + int len) { + int index = start; // Index of first insertion. + + // Index of first insertion plus multiple of 8 part of length + // (i.e. length with 3 least significant bits unset). + final int indexLoopLimit = index + (len & 0x7ffffff8); + + // Start filling in the byte array, 8 bytes at a time. + while (index < indexLoopLimit) { + final long random = source.next(); + bytes[index++] = (byte) random; + bytes[index++] = (byte) (random >>> 8); + bytes[index++] = (byte) (random >>> 16); + bytes[index++] = (byte) (random >>> 24); + bytes[index++] = (byte) (random >>> 32); + bytes[index++] = (byte) (random >>> 40); + bytes[index++] = (byte) (random >>> 48); + bytes[index++] = (byte) (random >>> 56); + } + + final int indexLimit = start + len; // Index of last insertion + 1. + + // Fill in the remaining bytes. + if (index < indexLimit) { + long random = source.next(); + while (true) { + bytes[index++] = (byte) random; + if (index < indexLimit) { + random >>>= 8; + } else { + break; + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source64/MersenneTwister64.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source64/MersenneTwister64.java b/src/main/java/org/apache/commons/math4/rng/internal/source64/MersenneTwister64.java new file mode 100644 index 0000000..0280842 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source64/MersenneTwister64.java @@ -0,0 +1,201 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.source64; + +import java.util.Arrays; +import org.apache.commons.math4.exception.InsufficientDataException; +import org.apache.commons.math4.rng.internal.util.NumberFactory; + +/** + * This class provides the 64-bits version of the originally 32-bits + * {@link org.apache.commons.math4.rng.internal.source32.MersenneTwister + * Mersenne Twister}. + * + * <p> + * This class is mainly a Java port of + * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html"> + * the 2014/2/23 version of the generator + * </a> written in C by Takuji Nishimura and Makoto Matsumoto. + * </p> + * + * <p> + * Here is their original copyright: + * </p> + * + * <table border="0" width="80%" cellpadding="10" align="center" bgcolor="#E0E0E0"> + * <tr><td>Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura, + * All rights reserved.</td></tr> + * + * <tr><td>Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * <ol> + * <li>Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer.</li> + * <li>Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution.</li> + * <li>The names of its contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission.</li> + * </ol></td></tr> + * + * <tr><td><strong>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE.</strong></td></tr> + * </table> + * + * @since 4.0 + */ +public class MersenneTwister64 extends LongProvider { + /** Size of the bytes pool. */ + private static final int NN = 312; + /** Period second parameter. */ + private static final int MM = 156; + /** X * MATRIX_A for X = {0, 1}. */ + private static final long[] MAG01 = { 0x0, 0xb5026f5aa96619e9L }; + /** Most significant 33 bits. */ + private static final long UM = 0xffffffff80000000L; + /** Least significant 31 bits. */ + private static final long LM = 0x7fffffffL; + /** Bytes pool. */ + private long[] mt = new long[NN]; + /** Current index in the bytes pool. */ + private int mti; + + /** + * Creates a new random number generator. + * + * @param seed Initial seed. + */ + public MersenneTwister64(long[] seed) { + setSeedInternal(seed); + } + + /** {@inheritDoc} */ + @Override + protected byte[] getStateInternal() { + final long[] s = Arrays.copyOf(mt, NN + 1); + s[NN] = mti; + + return NumberFactory.makeByteArray(s); + } + + /** {@inheritDoc} */ + @Override + protected void setStateInternal(byte[] s) { + if (s.length != (NN + 1) * 8) { + throw new InsufficientDataException(); + } + + final long[] tmp = NumberFactory.makeLongArray(s); + + System.arraycopy(tmp, 0, mt, 0, NN); + mti = (int) tmp[NN]; + } + + /** + * Reinitializes the generator as if just built with the given seed. + * + * @param seed Initial seed. + */ + private void setSeedInternal(long[] seed) { + initState(19650218L); + + int i = 1; + int j = 0; + + for (int k = Math.max(NN, seed.length); k != 0; k--) { + final long mm1 = mt[i - 1]; + mt[i] = (mt[i] ^ ((mm1 ^ (mm1 >>> 62)) * 0x369dea0f31a53f85L)) + seed[j] + j; // non linear + i++; + j++; + if (i >= NN) { + mt[0] = mt[NN - 1]; + i = 1; + } + if (j >= seed.length) { + j = 0; + } + } + for (int k = NN - 1; k != 0; k--) { + final long mm1 = mt[i - 1]; + mt[i] = (mt[i] ^ ((mm1 ^ (mm1 >>> 62)) * 0x27bb2ee687b0b0fdL)) - i; // non linear + i++; + if (i >= NN) { + mt[0] = mt[NN - 1]; + i = 1; + } + } + + mt[0] = 0x8000000000000000L; // MSB is 1; assuring non-zero initial array + } + + /** + * Initialize the internal state of this instance. + * + * @param seed Seed. + */ + private void initState(long seed) { + mt[0] = seed; + for (mti = 1; mti < NN; mti++) { + final long mm1 = mt[mti - 1]; + mt[mti] = 0x5851f42d4c957f2dL * (mm1 ^ (mm1 >>> 62)) + mti; + } + } + + /** {@inheritDoc} */ + @Override + public long next() { + long x; + + if (mti >= NN) { // generate NN words at one time + for (int i = 0; i < NN - MM; i++) { + x = (mt[i] & UM) | (mt[i + 1] & LM); + mt[i] = mt[i + MM] ^ (x >>> 1) ^ MAG01[(int)(x & 0x1L)]; + } + for (int i = NN - MM; i < NN - 1; i++) { + x = (mt[i] & UM) | (mt[i + 1] & LM); + mt[i] = mt[ i + (MM - NN)] ^ (x >>> 1) ^ MAG01[(int)(x & 0x1L)]; + } + + x = (mt[NN - 1] & UM) | (mt[0] & LM); + mt[NN - 1] = mt[MM - 1] ^ (x >>> 1) ^ MAG01[(int)(x & 0x1L)]; + + mti = 0; + } + + x = mt[mti++]; + + x ^= (x >>> 29) & 0x5555555555555555L; + x ^= (x << 17) & 0x71d67fffeda60000L; + x ^= (x << 37) & 0xfff7eee000000000L; + x ^= x >>> 43; + + return x; + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source64/RandomLongSource.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source64/RandomLongSource.java b/src/main/java/org/apache/commons/math4/rng/internal/source64/RandomLongSource.java new file mode 100644 index 0000000..0daa068 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source64/RandomLongSource.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math4.rng.internal.source64; + +/** + * Source of randomness that generate values of type {@code long}. + * + * @since 4.0 + */ +public interface RandomLongSource { + /** + * @return the next random value. + */ + long next(); +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source64/SplitMix64.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source64/SplitMix64.java b/src/main/java/org/apache/commons/math4/rng/internal/source64/SplitMix64.java new file mode 100644 index 0000000..086bd03 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source64/SplitMix64.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math4.rng.internal.source64; + +import org.apache.commons.math4.exception.InsufficientDataException; +import org.apache.commons.math4.rng.internal.util.NumberFactory; + +/** + * A fast RNG, with 64 bits of state, that can be used to initialize the + * state of other generators. + * + * @see <a href="http://xorshift.di.unimi.it/splitmix64.c"> + * Original source code</a> + * + * @since 4.0 + */ +public class SplitMix64 extends LongProvider { + /** State. */ + private long state; + + /** + * Creates a new instance. + * + * @param seed Initial seed. + */ + public SplitMix64(Long seed) { + setSeedInternal(seed); + } + + /** + * Seeds the RNG. + * + * @param seed Seed. + */ + private void setSeedInternal(Long seed) { + state = seed; + } + + /** {@inheritDoc} */ + @Override + public long next() { + long z = state += 0x9e3779b97f4a7c15L; + z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L; + z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL; + return z ^ (z >>> 31); + } + + /** {@inheritDoc} */ + @Override + protected byte[] getStateInternal() { + return NumberFactory.makeByteArray(state); + } + + /** {@inheritDoc} */ + @Override + protected void setStateInternal(byte[] s) { + if (s.length != 8) { + throw new InsufficientDataException(); + } + + state = NumberFactory.makeLong(s); + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source64/TwoCmres.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source64/TwoCmres.java b/src/main/java/org/apache/commons/math4/rng/internal/source64/TwoCmres.java new file mode 100644 index 0000000..d6fdcd6 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source64/TwoCmres.java @@ -0,0 +1,310 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math4.rng.internal.source64; + +import java.util.List; +import java.util.ArrayList; +import org.apache.commons.math4.exception.MathInternalError; +import org.apache.commons.math4.exception.OutOfRangeException; +import org.apache.commons.math4.exception.InsufficientDataException; +import org.apache.commons.math4.rng.internal.util.NumberFactory; + +/** + * Random number generator designed by Mark D. Overton. + * <p> + * It is one of the many generators described by the author in the following article series: + * <ul> + * <li><a href="http://www.drdobbs.com/tools/fast-high-quality-parallel-random-number/229625477">Part one</a></li> + * <li><a href="http://www.drdobbs.com/tools/fast-high-quality-parallel-random-number/231000484">Part two</a></li> + * </ul> + * </p> + * + * @since 4.0 + */ +public class TwoCmres extends LongProvider { + /** A small positive integer. */ + private static final byte SEED_GUARD = 9; + /** Factory of instances of this class. Singleton. */ + private static final Cmres.Factory FACTORY = new Cmres.Factory(); + /** First subcycle generator. */ + private final Cmres x; + /** Second subcycle generator. */ + private final Cmres y; + /** State of first subcycle generator. */ + private long xx; + /** State of second subcycle generator. */ + private long yy; + + /** + * Creates a new instance. + * + * @param seed Initial seed. + * @param x First subcycle generator. + * @param y Second subcycle generator. + * @throws InsufficientDataException if {@code x == y}. + */ + private TwoCmres(int seed, + Cmres x, + Cmres y) { + if (x == y) { + throw new InsufficientDataException(); + } + this.x = x; + this.y = y; + setSeedInternal(seed); + } + + /** + * Creates a new instance. + * + * @param seed Seed. + */ + public TwoCmres(Integer seed) { + this(seed, 0, 1); + } + + /** + * Creates a new instance. + * + * @param seed Seed. + * @param i Table entry for first subcycle generator. + * @param j Table entry for second subcycle generator. + * @throws InsufficientDataException if {@code i == j}. + * @throws OutOfRangeException if {@code i < 0} or + * {@code i >= numberOfSubcycleGenerators()}. + * @throws OutOfRangeException if {@code j < 0} or + * {@code j >= numberOfSubcycleGenerators()}. + */ + public TwoCmres(Integer seed, + int i, + int j) { + this(seed, FACTORY.get(i), FACTORY.get(j)); + } + + /** {@inheritDoc} */ + @Override + public long next() { + xx = x.transform(xx); + yy = y.transform(yy); + + return xx + yy; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return super.toString() + " (" + x + " + " + y + ")"; + } + + /** + * @return the number of subcycle generators. + */ + public static int numberOfSubcycleGenerators() { + return FACTORY.numberOfSubcycleGenerators(); + } + + /** {@inheritDoc} */ + @Override + protected byte[] getStateInternal() { + return NumberFactory.makeByteArray(new long[] { xx, yy }); + } + + /** {@inheritDoc} */ + @Override + protected void setStateInternal(byte[] s) { + if (s.length != 16) { + throw new InsufficientDataException(); + } + + final long[] state = NumberFactory.makeLongArray(s); + xx = state[0]; + yy = state[1]; + } + + /** + * @param seed Seed. + */ + private void setSeedInternal(int seed) { + // The seeding procedure consists in going away from some + // point known to be in the cycle. + // The total number of calls to the "transform" method will + // not exceed about 130,000 (which is negligible as seeding + // will not occur more than once in normal usage). + + // Make two positive 16-bits integers. + final long s = NumberFactory.makeLong(0, seed); // s >= 0 + final int xMax = (int) (s & 0xffff + SEED_GUARD); + final int yMax = (int) ((s >> 16) + SEED_GUARD); + + if (xMax < 0 || + yMax < 0) { + throw new MathInternalError(); + } + + xx = x.getStart(); + for (int i = xMax; i > 0; i--) { + xx = x.transform(xx); + } + + yy = y.getStart(); + for (int i = yMax; i > 0; i--) { + yy = y.transform(yy); + } + } + + /** + * Subcycle generator. + * Class is immutable. + */ + static class Cmres { + /** Cycle start. */ + private final int start; + /** Multiplier. */ + private final long multiply; + /** Rotation. */ + private final int rotate; + + /** + * @param multiply Multiplier. + * @param rotate Positive number. Must be in {@code [0, 64]}. + * @param start Cycle start. + */ + Cmres(long multiply, + int rotate, + int start) { + this.multiply = multiply; + this.rotate = rotate; + this.start = start; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + final String sep = ", "; + // Use hexadecimal for "multiplier" field. + final String m = String.format((java.util.Locale) null, "0x%016xL", multiply); + return "Cmres: [" + m + sep + rotate + sep + start + "]"; + } + + /** + * @return the multiplier. + */ + public long getMultiply() { + return multiply; + } + + /** + * @return the cycle start. + */ + public int getStart() { + return start; + } + + /** + * @param state Current state. + * @return the new state. + */ + long transform(long state) { + long s = state; + s *= multiply; + s = rotl(s); + s -= state; + return s; + } + + /** + * @param state State. + * @return the rotated state. + */ + private long rotl(long state) { + return (state << rotate) | (state >>> (64 - rotate)); + } + + /** Factory. */ + static class Factory { + /** List of good "Cmres" subcycle generators. */ + private static final List<Cmres> TABLE = new ArrayList<Cmres>(); + + /** + * Populates the table. + * It lists parameters known to be good (provided in + * the article referred to above). + * To maintain compatibility, new entries must be added + * only at the end of the table. + */ + static { + add(0xedce446814d3b3d9L, 33, 0x13b572e7); + add(0xc5b3cf786c806df7L, 33, 0x13c8e18a); + add(0xdd91bbb8ab9e0e65L, 31, 0x06dd03a6); + add(0x7b69342c0790221dL, 31, 0x1646bb8b); + add(0x0c72c0d18614c32bL, 33, 0x06014a3d); + add(0xd8d98c13bebe26c9L, 33, 0x014e8475); + add(0xcb039dc328bbc40fL, 31, 0x008684bd); + add(0x858c5ef3c021ed2fL, 32, 0x0dc8d622); + add(0x4c8be96bfc23b127L, 33, 0x0b6b20cc); + add(0x11eab77f808cf641L, 32, 0x06534421); + add(0xbc9bd78810fd28fdL, 31, 0x1d9ba40d); + add(0x0f1505c780688cb5L, 33, 0x0b7b7b67); + add(0xadc174babc2053afL, 31, 0x267f4197); + add(0x900b6b82b31686d9L, 31, 0x023c6985); + // Add new entries here. + } + + /** + * @return the number of subcycle generators. + */ + int numberOfSubcycleGenerators() { + return TABLE.size(); + } + + /** + * @param index Index into the list of available generators. + * @return the subcycle generator entry at index {@code index}. + */ + Cmres get(int index) { + if (index < 0 || + index >= TABLE.size()) { + throw new OutOfRangeException(index, 0, TABLE.size()); + } + + return TABLE.get(index); + } + + /** + * Adds an entry to the {@link Factory#TABLE}. + * + * @param multiply Multiplier. + * @param rotate Rotate. + * @param start Cycle start. + */ + private static void add(long multiply, + int rotate, + int start) { + // Sanity check: if there are duplicates, the class initialization + // will fail (and the JVM will report "NoClassDefFoundError"). + for (Cmres sg : TABLE) { + if (multiply == sg.getMultiply()) { + throw new MathInternalError(); + } + } + + TABLE.add(new Cmres(multiply, rotate, start)); + } + } + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source64/XorShift1024Star.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source64/XorShift1024Star.java b/src/main/java/org/apache/commons/math4/rng/internal/source64/XorShift1024Star.java new file mode 100644 index 0000000..c6bcfaa --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source64/XorShift1024Star.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math4.rng.internal.source64; + +import java.util.Arrays; +import org.apache.commons.math4.exception.InsufficientDataException; +import org.apache.commons.math4.rng.internal.util.NumberFactory; + +/** + * A fast RNG. + * + * @see <a href="http://xorshift.di.unimi.it/xorshift1024star.c"> + * Original source code</a> + * + * @since 4.0 + */ +public class XorShift1024Star extends LongProvider { + /** Size of the state vector. */ + private static final int SEED_SIZE = 16; + /** State. */ + private final long[] state = new long[SEED_SIZE]; + /** Index in "state" array. */ + private int index; + + /** + * Creates a new instance. + * + * @param seed Initial seed. + * If the length is larger than 16, only the first 16 elements will + * be used; if smaller, the remaining elements will be automatically + * set. + */ + public XorShift1024Star(long[] seed) { + setSeedInternal(seed); + } + + /** {@inheritDoc} */ + @Override + protected byte[] getStateInternal() { + final long[] s = Arrays.copyOf(state, SEED_SIZE + 1); + s[SEED_SIZE] = index; + + return NumberFactory.makeByteArray(s); + } + + /** {@inheritDoc} */ + @Override + protected void setStateInternal(byte[] s) { + if (s.length != (SEED_SIZE + 1) * 8) { + throw new InsufficientDataException(); + } + + final long[] tmp = NumberFactory.makeLongArray(s); + + System.arraycopy(tmp, 0, state, 0, SEED_SIZE); + index = (int) tmp[SEED_SIZE]; + } + + /** + * Seeds the RNG. + * + * @param seed Seed. + */ + private void setSeedInternal(long[] seed) { + // Reset the whole state of this RNG (i.e. "state" and "index"). + // Seeding procedure is not part of the reference code. + + System.arraycopy(seed, 0, state, 0, Math.min(seed.length, state.length)); + + if (seed.length < SEED_SIZE) { + for (int i = seed.length; i < SEED_SIZE; i++) { + state[i] = 26021969L * i; + } + for (int i = SEED_SIZE - 1; i > seed.length; i--) { + state[i] ^= state[SEED_SIZE - i - 1]; + } + + state[seed.length] = 0x8000000000000000L; // Ensuring non-zero initial array. + } + + index = 0; + } + + /** {@inheritDoc} */ + @Override + public long next() { + final long s0 = state[index]; + long s1 = state[index = (index + 1) & 15]; + s1 ^= s1 << 31; // a + state[index] = s1 ^ s0 ^ (s1 >>> 11) ^ (s0 >>> 30); // b,c + return state[index] * 1181783497276652981L; + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source64/package-info.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source64/package-info.java b/src/main/java/org/apache/commons/math4/rng/internal/source64/package-info.java new file mode 100644 index 0000000..8afab2c --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/source64/package-info.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * <h3> + * Concrete algorithms for {@code long}-based sources of randomness + * </h3> + * + * <p> + * <b>For internal use only:</b> Direct access to classes in this package + * is discouraged, as they could be modified without notice. + * </p> + * + * <p><b>Notes for developers</b></p> + * + * <ul> + * <li> + * A source of randomness must inherit from + * {@link org.apache.commons.math4.rng.internal.source64.LongProvider} + * </li> + * <li> + * The "provider" must specify <em>one</em> way for setting the seed. + * For a given seed, the generated sequence must always be the same. + * </li> + * <li> + * The "provider" must implement methods {@code getStateInternal} and + * {@code setStateInternal} in order to save and restore the state of an + * instance (cf. {@link org.apache.commons.math4.rng.internal.BaseProvider}). + * </li> + * <li> + * When a new class is implemented here, user-access to it must be provided + * through associated {@link org.apache.commons.math4.rng.RandomSource + * factory methods}. + * </li> + * </ul> + */ + +package org.apache.commons.math4.rng.internal.source64; http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/util/Int2Long.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/util/Int2Long.java b/src/main/java/org/apache/commons/math4/rng/internal/util/Int2Long.java new file mode 100644 index 0000000..d423c08 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/util/Int2Long.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.util; + +/** + * Converts a {@code Integer} to an {@code Long}. + * + * @since 4.0 + */ +public class Int2Long implements SeedConverter<Integer, Long> { + /** {@inheritDoc} */ + @Override + public Long convert(Integer seed) { + final int s = seed; + return NumberFactory.makeLong(s, ~s); + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return getClass().getSimpleName(); + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/util/IntArray2Int.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/util/IntArray2Int.java b/src/main/java/org/apache/commons/math4/rng/internal/util/IntArray2Int.java new file mode 100644 index 0000000..030895d --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/util/IntArray2Int.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.util; + +/** + * Creates a single value by "xor" of all the values in the input array. + * + * @since 4.0 + */ +public class IntArray2Int implements SeedConverter<int[], Integer> { + /** {@inheritDoc} */ + @Override + public Integer convert(int[] seed) { + int out = 0; + for (int i = 0; i < seed.length; i++) { + out ^= seed[i]; + } + + return out; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return getClass().getSimpleName(); + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/util/IntArray2LongArray.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/util/IntArray2LongArray.java b/src/main/java/org/apache/commons/math4/rng/internal/util/IntArray2LongArray.java new file mode 100644 index 0000000..399de7f --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/util/IntArray2LongArray.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.util; + +/** + * Creates a {@code long[]} from an {@code int[]}. + * + * @since 4.0 + */ +public class IntArray2LongArray implements SeedConverter<int[], long[]> { + /** {@inheritDoc} */ + @Override + public long[] convert(int[] seed) { + final int outSize = (seed.length + 1) / 2; + final long[] out = new long[outSize]; + for (int i = 0; i < outSize; i++) { + final int lo = seed[i]; + final int hi = outSize + i < seed.length ? seed[outSize + i] : 0; + out[i] = NumberFactory.makeLong(hi, lo) ; + } + + return out; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return getClass().getSimpleName(); + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/util/Long2Int.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/util/Long2Int.java b/src/main/java/org/apache/commons/math4/rng/internal/util/Long2Int.java new file mode 100644 index 0000000..638b173 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/util/Long2Int.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.util; + +/** + * Converts a {@code Long} to an {@code Integer}. + * + * @since 4.0 + */ +public class Long2Int implements SeedConverter<Long, Integer> { + /** {@inheritDoc} */ + @Override + public Integer convert(Long seed) { + return NumberFactory.makeInt(seed); + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return getClass().getSimpleName(); + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/util/Long2IntArray.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/util/Long2IntArray.java b/src/main/java/org/apache/commons/math4/rng/internal/util/Long2IntArray.java new file mode 100644 index 0000000..84e5016 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/util/Long2IntArray.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.util; + +import org.apache.commons.math4.rng.internal.source64.SplitMix64; + +/** + * Uses a {@code long} value to seed a {@link SplitMix64} RNG and + * create a {@code int[]} with the requested number of random + * values. + * + * @since 4.0 + */ +public class Long2IntArray implements SeedConverter<Long, int[]> { + /** Size of the output array. */ + private final int size; + + /** + * @param size Size of the output array. + */ + public Long2IntArray(int size) { + this.size = size; + } + + /** {@inheritDoc} */ + @Override + public int[] convert(Long seed) { + return SeedFactory.createIntArray(size, new SplitMix64(seed)); + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return getClass().getSimpleName() + "(size=" + size + ")"; + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/util/Long2LongArray.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/util/Long2LongArray.java b/src/main/java/org/apache/commons/math4/rng/internal/util/Long2LongArray.java new file mode 100644 index 0000000..9d8b700 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/util/Long2LongArray.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.util; + +import org.apache.commons.math4.rng.internal.source64.SplitMix64; + +/** + * Uses a {@code Long} value to seed a {@link SplitMix64} RNG and + * create a {@code long[]} with the requested number of random + * values. + * + * @since 4.0 + */ +public class Long2LongArray implements SeedConverter<Long, long[]> { + /** Size of the output array. */ + private final int size; + + /** + * @param size Size of the output array. + */ + public Long2LongArray(int size) { + this.size = size; + } + + /** {@inheritDoc} */ + @Override + public long[] convert(Long seed) { + final long[] out = new long[size]; + final SplitMix64 rng = new SplitMix64(seed); + for (int i = 0; i < size; i++) { + out[i] = rng.nextLong(); + } + + return out; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return getClass().getSimpleName() + "(size: " + size + ")"; + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/util/LongArray2IntArray.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/util/LongArray2IntArray.java b/src/main/java/org/apache/commons/math4/rng/internal/util/LongArray2IntArray.java new file mode 100644 index 0000000..67b2ba8 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/util/LongArray2IntArray.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.util; + +/** + * Creates an {@code int[]} from a {@code long[]}. + * + * @since 4.0 + */ +public class LongArray2IntArray implements SeedConverter<long[], int[]> { + /** {@inheritDoc} */ + @Override + public int[] convert(long[] seed) { + final int[] out = new int[seed.length * 2]; + for (int i = 0; i < seed.length; i++) { + final long current = seed[i]; + out[i] = NumberFactory.extractLo(current); + out[seed.length + i] = NumberFactory.extractHi(current); + } + + return out; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return getClass().getSimpleName(); + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/util/LongArray2Long.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/util/LongArray2Long.java b/src/main/java/org/apache/commons/math4/rng/internal/util/LongArray2Long.java new file mode 100644 index 0000000..4556aaf --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/util/LongArray2Long.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.util; + +/** + * Creates a single value by "xor" of all the values in the input array. + * + * @since 4.0 + */ +public class LongArray2Long implements SeedConverter<long[], Long> { + /** {@inheritDoc} */ + @Override + public Long convert(long[] seed) { + long out = 0; + for (int i = 0; i < seed.length; i++) { + out ^= seed[i]; + } + + return out; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return getClass().getSimpleName(); + } +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/util/LongMixInt.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/rng/internal/util/LongMixInt.java b/src/main/java/org/apache/commons/math4/rng/internal/util/LongMixInt.java new file mode 100644 index 0000000..e30a072 --- /dev/null +++ b/src/main/java/org/apache/commons/math4/rng/internal/util/LongMixInt.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.rng.internal.util; + +import org.apache.commons.math4.rng.internal.source64.SplitMix64; + +/** + * Uses a {@code long} value to seed a {@link SplitMix64} RNG and + * create an {@code int[]} with the requested number of random + * values. + * + * @since 4.0 + */ +public class LongMixInt implements SeedConverter<Long, int[]> { + /** Size of the output array. */ + private final int size; + + /** + * @param size Size of the output array. + */ + public LongMixInt(int size) { + this.size = size; + } + + /** {@inheritDoc} */ + @Override + public int[] convert(Long seed) { + return SeedFactory.createIntArray(size, new SplitMix64(seed)); + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return getClass().getSimpleName() + "(size=" + size + ")"; + } +}