http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/LongProvider.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/LongProvider.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/LongProvider.java new file mode 100644 index 0000000..0c7bed7 --- /dev/null +++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/LongProvider.java @@ -0,0 +1,134 @@ +/* + * 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.rng.core.source64; + +import org.apache.commons.rng.core.util.NumberFactory; +import org.apache.commons.rng.core.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) { + checkIndex(0, bytes.length - 1, start); + checkIndex(0, bytes.length - start, len); + + 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-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/MersenneTwister64.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/MersenneTwister64.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/MersenneTwister64.java new file mode 100644 index 0000000..bd0683f --- /dev/null +++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/MersenneTwister64.java @@ -0,0 +1,202 @@ +/* + * 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.rng.core.source64; + +import java.util.Arrays; +import org.apache.commons.rng.core.util.NumberFactory; + +/** + * This class provides the 64-bits version of the originally 32-bits + * {@link org.apache.commons.rng.core.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" style="background-color: #E0E0E0" summary="Mersenne Twister licence"> + * <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> + * + * @see <a href="https://en.wikipedia.org/wiki/Mersenne_Twister">Mersenne Twister (Wikipedia)</a> + * @since 1.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) { + checkStateSize(s, (NN + 1) * 8); + + final long[] tmp = NumberFactory.makeLongArray(s); + System.arraycopy(tmp, 0, mt, 0, NN); + mti = (int) tmp[NN]; + } + + /** + * Initializes the generator with the given seed. + * + * @param seed Initial seed. + */ + private void setSeedInternal(long[] seed) { + if (seed.length == 0) { + // Accept empty seed. + seed = new long[1]; + } + + 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-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/RandomLongSource.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/RandomLongSource.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/RandomLongSource.java new file mode 100644 index 0000000..0b3a19d --- /dev/null +++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/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.rng.core.source64; + +/** + * Source of randomness that generates values of type {@code long}. + * + * @since 1.0 + */ +public interface RandomLongSource { + /** + * @return the next random value. + */ + long next(); +} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/SplitMix64.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/SplitMix64.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/SplitMix64.java new file mode 100644 index 0000000..79af46f --- /dev/null +++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/SplitMix64.java @@ -0,0 +1,75 @@ +/* + * 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.rng.core.source64; + +import org.apache.commons.rng.core.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 1.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) { + checkStateSize(s, 8); + + state = NumberFactory.makeLong(s); + } +} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/TwoCmres.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/TwoCmres.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/TwoCmres.java new file mode 100644 index 0000000..af08c2f --- /dev/null +++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/TwoCmres.java @@ -0,0 +1,307 @@ +/* + * 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.rng.core.source64; + +import java.util.List; +import java.util.ArrayList; +import org.apache.commons.rng.core.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:</p> + * <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> + * + * @since 1.0 + */ +public class TwoCmres extends LongProvider { + /** Error message. */ + private static final String INTERNAL_ERROR_MSG = "Internal error: Please file a bug report"; + /** 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 IllegalArgumentException if {@code x == y}. + */ + private TwoCmres(int seed, + Cmres x, + Cmres y) { + if (x == y) { + throw new IllegalArgumentException("Subcycle generators must be different"); + } + 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 IllegalArgumentException if {@code i == j}. + * @throws IndexOutOfBoundsException if {@code i < 0} or + * {@code i >= numberOfSubcycleGenerators()}. + * @throws IndexOutOfBoundsException 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) { + checkStateSize(s, 16); + + 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 IllegalStateException(INTERNAL_ERROR_MSG); + } + + 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 IndexOutOfBoundsException("Out of interval [0, " + + (TABLE.size() - 1) + "]"); + } + + 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 IllegalStateException(INTERNAL_ERROR_MSG); + } + } + + TABLE.add(new Cmres(multiply, rotate, start)); + } + } + } +} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024Star.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024Star.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024Star.java new file mode 100644 index 0000000..1877453 --- /dev/null +++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/XorShift1024Star.java @@ -0,0 +1,93 @@ +/* + * 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.rng.core.source64; + +import java.util.Arrays; +import org.apache.commons.rng.core.util.NumberFactory; + +/** + * A fast RNG. + * + * @see <a href="http://xorshift.di.unimi.it/xorshift1024star.c"> + * Original source code</a> + * + * @see <a href="https://en.wikipedia.org/wiki/Xorshift">Xorshift (Wikipedia)</a> + * @since 1.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) { + checkStateSize(s, (SEED_SIZE + 1) * 8); + + 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"). + // Filling procedure is not part of the reference code. + fillState(state, seed); + 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-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/package-info.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/package-info.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source64/package-info.java new file mode 100644 index 0000000..224317b --- /dev/null +++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/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.rng.core.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.rng.core.BaseProvider}). + * </li> + * <li> + * When a new class is implemented here, user-access to it must be provided + * through associated {@link org.apache.commons.rng.RandomSource + * factory methods}. + * </li> + * </ul> + */ + +package org.apache.commons.rng.core.source64; http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/core/util/NumberFactory.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/util/NumberFactory.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/util/NumberFactory.java new file mode 100644 index 0000000..41d830b --- /dev/null +++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/util/NumberFactory.java @@ -0,0 +1,332 @@ +/* + * 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.rng.core.util; + +import java.util.Arrays; + +/** + * Utility for creating number types from one or two {@code int} values + * or one {@code long} value, or a sequence of bytes. + */ +public final class NumberFactory { + /** See {@link #makeDouble(long)}. */ + private static final long DOUBLE_HIGH_BITS = 0x3ffL << 52; + /** See {@link #makeFloat(int)}. */ + private static final float FLOAT_MULTIPLIER = 0x1.0p-23f; + /** See {@link #makeDouble(int, int)}. */ + private static final double DOUBLE_MULTIPLIER = 0x1.0p-52d; + /** Lowest byte mask. */ + private static final long LONG_LOWEST_BYTE_MASK = 0xffL; + /** Number of bytes in a {@code long}. */ + private static final int LONG_SIZE = 8; + /** Lowest byte mask. */ + private static final int INT_LOWEST_BYTE_MASK = 0xff; + /** Number of bytes in a {@code int}. */ + private static final int INT_SIZE = 4; + + /** + * Class contains only static methods. + */ + private NumberFactory() {} + + /** + * @param v Number. + * @return a boolean. + */ + public static boolean makeBoolean(int v) { + return (v >>> 31) != 0; + } + + /** + * @param v Number. + * @return a boolean. + */ + public static boolean makeBoolean(long v) { + return (v >>> 63) != 0; + } + + /** + * @param v Number. + * @return a {@code double} value in the interval {@code [0, 1]}. + */ + public static double makeDouble(long v) { + // http://xorshift.di.unimi.it + return Double.longBitsToDouble(DOUBLE_HIGH_BITS | v >>> 12) - 1d; + } + + /** + * @param v Number (high order bits). + * @param w Number (low order bits). + * @return a {@code double} value in the interval {@code [0, 1]}. + */ + public static double makeDouble(int v, + int w) { + final long high = ((long) (v >>> 6)) << 26; + final int low = w >>> 6; + return (high | low) * DOUBLE_MULTIPLIER; + } + + /** + * @param v Number. + * @return a {@code float} value in the interval {@code [0, 1]}. + */ + public static float makeFloat(int v) { + return (v >>> 9) * FLOAT_MULTIPLIER; + } + + /** + * @param v Number (high order bits). + * @param w Number (low order bits). + * @return a {@code long} value. + */ + public static long makeLong(int v, + int w) { + return (((long) v) << 32) | (w & 0xffffffffL); + } + + /** + * Creates an {@code int} from a {@code long}. + * + * @param v Number. + * @return an {@code int} value made from the "xor" of the + * {@link #extractHi(long) high order bits} and + * {@link #extractLo(long) low order bits} of {@code v}. + */ + public static int makeInt(long v) { + return extractHi(v) ^ extractLo(v); + } + + /** + * Creates an {@code int} from a {@code long}, using the high order bits. + * + * <p>The returned value is such that if</p> + * <pre><code> + * vL = extractLo(v); + * vH = extractHi(v); + * </code></pre> + * + * <p>then {@code v} is equal to {@link #makeLong(int,int) makeLong(vH, vL)}.</p> + * + * @param v Number. + * @return an {@code int} value made from the most significant bits + * of {@code v}. + */ + public static int extractHi(long v) { + return (int) (v >>> 32); + } + + /** + * Creates an {@code int} from a {@code long}, using the low order bits. + * + * <p>The returned value is such that if</p> + * + * <pre><code> + * vL = extractLo(v); + * vH = extractHi(v); + * </code></pre> + * + * <p>then {@code v} is equal to {@link #makeLong(int,int) makeLong(vH, vL)}.</p> + * + * @param v Number. + * @return an {@code int} value made from the least significant bits + * of {@code v}. + */ + public static int extractLo(long v) { + return (int) v; + } + + /** + * Splits a {@code long} into 8 bytes. + * + * @param v Value. + * @return the bytes that compose the given value (least-significant + * byte first). + */ + public static byte[] makeByteArray(long v) { + final byte[] b = new byte[LONG_SIZE]; + + for (int i = 0; i < LONG_SIZE; i++) { + final int shift = i * 8; + b[i] = (byte) ((v >>> shift) & LONG_LOWEST_BYTE_MASK); + } + + return b; + } + + /** + * Creates a {@code long} from 8 bytes. + * + * @param input Input. + * @return the value that correspond to the given bytes assuming + * that the is ordered in increasing byte significance (i.e. the + * first byte in the array is the least-siginficant). + * @throws IllegalArgumentException if {@code input.length != 8}. + */ + public static long makeLong(byte[] input) { + checkSize(LONG_SIZE, input.length); + + long v = 0; + for (int i = 0; i < LONG_SIZE; i++) { + final int shift = i * 8; + v |= (((long) input[i]) & LONG_LOWEST_BYTE_MASK) << shift; + } + + return v; + } + + /** + * Splits an array of {@code long} values into a sequence of bytes. + * This method calls {@link #makeByteArray(long)} for each element of + * the {@code input}. + * + * @param input Input. + * @return an array of bytes. + */ + public static byte[] makeByteArray(long[] input) { + final int size = input.length * LONG_SIZE; + final byte[] b = new byte[size]; + + for (int i = 0; i < input.length; i++) { + final byte[] current = makeByteArray(input[i]); + System.arraycopy(current, 0, b, i * LONG_SIZE, LONG_SIZE); + } + + return b; + } + + /** + * Creates an array of {@code long} values from a sequence of bytes. + * This method calls {@link #makeLong(byte[])} for each subsequence + * of 8 bytes. + * + * @param input Input. + * @return an array of {@code long}. + * @throws IllegalArgumentException if {@code input.length} is not + * a multiple of 8. + */ + public static long[] makeLongArray(byte[] input) { + final int size = input.length; + final int num = size / LONG_SIZE; + checkSize(num * LONG_SIZE, size); + + final long[] output = new long[num]; + for (int i = 0; i < num; i++) { + final int from = i * LONG_SIZE; + final byte[] current = Arrays.copyOfRange(input, from, from + LONG_SIZE); + output[i] = makeLong(current); + } + + return output; + } + + /** + * Splits an {@code int} into 4 bytes. + * + * @param v Value. + * @return the bytes that compose the given value (least-significant + * byte first). + */ + public static byte[] makeByteArray(int v) { + final byte[] b = new byte[INT_SIZE]; + + for (int i = 0; i < INT_SIZE; i++) { + final int shift = i * 8; + b[i] = (byte) ((v >>> shift) & INT_LOWEST_BYTE_MASK); + } + + return b; + } + + /** + * Creates an {@code int} from 4 bytes. + * + * @param input Input. + * @return the value that correspond to the given bytes assuming + * that the is ordered in increasing byte significance (i.e. the + * first byte in the array is the least-siginficant). + * @throws IllegalArgumentException if {@code input.length != 4}. + */ + public static int makeInt(byte[] input) { + checkSize(INT_SIZE, input.length); + + int v = 0; + for (int i = 0; i < INT_SIZE; i++) { + final int shift = i * 8; + v |= (((int) input[i]) & INT_LOWEST_BYTE_MASK) << shift; + } + + return v; + } + + /** + * Splits an array of {@code int} values into a sequence of bytes. + * This method calls {@link #makeByteArray(int)} for each element of + * the {@code input}. + * + * @param input Input. + * @return an array of bytes. + */ + public static byte[] makeByteArray(int[] input) { + final int size = input.length * INT_SIZE; + final byte[] b = new byte[size]; + + for (int i = 0; i < input.length; i++) { + final byte[] current = makeByteArray(input[i]); + System.arraycopy(current, 0, b, i * INT_SIZE, INT_SIZE); + } + + return b; + } + + /** + * Creates an array of {@code int} values from a sequence of bytes. + * This method calls {@link #makeInt(byte[])} for each subsequence + * of 4 bytes. + * + * @param input Input. Length must be a multiple of 4. + * @return an array of {@code int}. + * @throws IllegalArgumentException if {@code input.length} is not + * a multiple of 4. + */ + public static int[] makeIntArray(byte[] input) { + final int size = input.length; + final int num = size / INT_SIZE; + checkSize(num * INT_SIZE, size); + + final int[] output = new int[num]; + for (int i = 0; i < num; i++) { + final int from = i * INT_SIZE; + final byte[] current = Arrays.copyOfRange(input, from, from + INT_SIZE); + output[i] = makeInt(current); + } + + return output; + } + + /** + * @param expected Expected value. + * @param actual Actual value. + * @throw IllegalArgumentException if {@code expected != actual}. + */ + private static void checkSize(int expected, + int actual) { + if (expected != actual) { + throw new IllegalArgumentException("Array size: Expected " + expected + + " but was " + actual); + } + } +} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/internal/BaseProvider.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/BaseProvider.java b/commons-rng-core/src/main/java/org/apache/commons/rng/internal/BaseProvider.java deleted file mode 100644 index be8b225..0000000 --- a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/BaseProvider.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * 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.rng.internal; - -import org.apache.commons.rng.RestorableUniformRandomProvider; -import org.apache.commons.rng.RandomProviderState; - -/** - * Base class with default implementation for common methods. - */ -public abstract class BaseProvider - implements RestorableUniformRandomProvider { - /** {@inheritDoc} */ - @Override - public int nextInt(int n) { - checkStrictlyPositive(n); - - if ((n & -n) == n) { - return (int) ((n * (long) (nextInt() >>> 1)) >> 31); - } - int bits; - int val; - do { - bits = nextInt() >>> 1; - val = bits % n; - } while (bits - val + (n - 1) < 0); - - return val; - } - - /** {@inheritDoc} */ - @Override - public long nextLong(long n) { - checkStrictlyPositive(n); - - long bits; - long val; - do { - bits = nextLong() >>> 1; - val = bits % n; - } while (bits - val + (n - 1) < 0); - - return val; - } - - /** {@inheritDoc} */ - @Override - public RandomProviderState saveState() { - return new RandomProviderDefaultState(getStateInternal()); - } - - /** {@inheritDoc} */ - @Override - public void restoreState(RandomProviderState state) { - if (state instanceof RandomProviderDefaultState) { - setStateInternal(((RandomProviderDefaultState) state).getState()); - } else { - throw new IllegalArgumentException("Foreign instance"); - } - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return getClass().getName(); - } - - /** - * Creates a snapshot of the RNG state. - * - * @return the internal state. - * @throws UnsupportedOperationException if not implemented. - */ - protected byte[] getStateInternal() { - throw new UnsupportedOperationException(); - } - - /** - * Resets the RNG to the given {@code state}. - * - * @param state State (previously obtained by a call to - * {@link #getStateInternal()}). - * @throws UnsupportedOperationException if not implemented. - * - * @see #checkStateSize(byte[],int) - */ - protected void setStateInternal(byte[] state) { - throw new UnsupportedOperationException(); - } - - /** - * Simple filling procedure. - * It will - * <ol> - * <li> - * fill the beginning of {@code state} by copying - * {@code min(seed.length, state.length)} elements from - * {@code seed}, - * </li> - * <li> - * set all remaining elements of {@code state} with non-zero - * values (even if {@code seed.length < state.length}). - * </li> - * </ol> - * - * @param state State. Must be allocated. - * @param seed Seed. Cannot be null. - */ - protected void fillState(int[] state, - int[] seed) { - final int stateSize = state.length; - final int seedSize = seed.length; - System.arraycopy(seed, 0, state, 0, Math.min(seedSize, stateSize)); - - if (seedSize < stateSize) { - for (int i = seedSize; i < stateSize; i++) { - state[i] = (int) (scrambleWell(state[i - seed.length], i) & 0xffffffffL); - } - } - } - - /** - * Simple filling procedure. - * It will - * <ol> - * <li> - * fill the beginning of {@code state} by copying - * {@code min(seed.length, state.length)} elements from - * {@code seed}, - * </li> - * <li> - * set all remaining elements of {@code state} with non-zero - * values (even if {@code seed.length < state.length}). - * </li> - * </ol> - * - * @param state State. Must be allocated. - * @param seed Seed. Cannot be null. - */ - protected void fillState(long[] state, - long[] seed) { - final int stateSize = state.length; - final int seedSize = seed.length; - System.arraycopy(seed, 0, state, 0, Math.min(seedSize, stateSize)); - - if (seedSize < stateSize) { - for (int i = seedSize; i < stateSize; i++) { - state[i] = scrambleWell(state[i - seed.length], i); - } - } - } - - /** - * Checks that the {@code state} has the {@code expected} size. - * - * @param state State. - * @param expected Expected length of {@code state} array. - * @throws IllegalArgumentException if {@code state.length != expected}. - */ - protected void checkStateSize(byte[] state, - int expected) { - if (state.length != expected) { - throw new IllegalArgumentException("State size must be " + expected + - " but was " + state.length); - } - } - - /** - * Checks whether {@code index} is in the range {@code [min, max]}. - * - * @param min Lower bound. - * @param max Upper bound. - * @param index Value that must lie within the {@code [min, max]} interval. - * @throws IndexOutOfBoundsException if {@code index} is not within the - * {@code [min, max]} interval. - */ - protected void checkIndex(int min, - int max, - int index) { - if (index < min || - index > max) { - throw new IndexOutOfBoundsException(index + " is out of interval [" + - min + ", " + - max + "]"); - } - } - - /** - * Checks that the argument is strictly positive. - * - * @param n Number to check. - * @throws IllegalArgumentException if {@code n <= 0}. - */ - private void checkStrictlyPositive(long n) { - if (n <= 0) { - throw new IllegalArgumentException("Must be strictly positive: " + n); - } - } - - /** - * Transformation used to scramble the initial state of - * a generator. - * - * @param n Seed element. - * @param mult Multiplier. - * @param shift Shift. - * @param add Offset. - * @return the transformed seed element. - */ - private static long scramble(long n, - long mult, - int shift, - int add) { - // Code inspired from "AbstractWell" class. - return mult * (n ^ (n >> shift)) + add; - } - - /** - * Transformation used to scramble the initial state of - * a generator. - * - * @param n Seed element. - * @param add Offset. - * @return the transformed seed element. - * @see #scramble(long,long,int,int) - */ - private static long scrambleWell(long n, - int add) { - // Code inspired from "AbstractWell" class. - return scramble(n, 1812433253L, 30, add); - } -} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/internal/RandomProviderDefaultState.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/RandomProviderDefaultState.java b/commons-rng-core/src/main/java/org/apache/commons/rng/internal/RandomProviderDefaultState.java deleted file mode 100644 index 2b882b3..0000000 --- a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/RandomProviderDefaultState.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.rng.internal; - -import java.util.Arrays; - -import org.apache.commons.rng.RandomProviderState; - -/** - * Wraps the internal state of the {@link RestorableUniformRandomProvider} - * instances created by this factory. - * Its purpose is to store all the data needed to recover the same - * state in order to restart a sequence where it left off. - * External code should not try to modify the data contained in instances - * of this class. - * - * @since 1.0 - */ -public class RandomProviderDefaultState implements RandomProviderState { - /** Internal state. */ - private final byte[] state; - - /** - * Initializes an instance. - * The contents of the {@code state} argument is unspecified, and is - * guaranteed to be valid only if it was generated by implementations - * provided by this library. - * - * @param state Mapping of all the data which an implementation of - * {@link org.apache.commons.rng.UniformRandomProvider} needs in order - * to reset its internal state. - */ - public RandomProviderDefaultState(byte[] state) { - this.state = Arrays.copyOf(state, state.length); - } - - /** - * @return the internal state. - */ - public byte[] getState() { - return Arrays.copyOf(state, state.length); - } -} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/internal/package-info.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/package-info.java b/commons-rng-core/src/main/java/org/apache/commons/rng/internal/package-info.java deleted file mode 100644 index f3c5970..0000000 --- a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/package-info.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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>Base classes for the {@link org.apache.commons.rng.UniformRandomProvider - * generation of uniformly distributed random numbers}. - * </h3> - * - * <p> - * <b>For internal use only:</b> Direct access to classes in this package - * and below, is discouraged, as they could be modified without notice. - * </p> - * - * <p><b>Notes for developers</b></p> - * - * <p> - * This package contains the common functionality. - * <br> - * Implementations that produce - * {@link org.apache.commons.rng.internal.source32.RandomIntSource int} - * values are defined in the - * {@link org.apache.commons.rng.internal.source32 source32} package. - * <br> - * Implementations that produce - * {@link org.apache.commons.rng.internal.source64.RandomLongSource long} - * values are defined in the - * {@link org.apache.commons.rng.internal.source64 source64} package. - * </p> - * - * <p> - * Each implementation must have an identifier in - * {@link org.apache.commons.rng.internal.ProviderBuilder.RandomSourceInternal - * ProviderBuilder.RandomSourceInternal} which must be referred to from the - * {@link org.apache.commons.rng.RandomSource public API}. - * </p> - */ - -package org.apache.commons.rng.internal; http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/AbstractWell.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/AbstractWell.java b/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/AbstractWell.java deleted file mode 100644 index 2043ec6..0000000 --- a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/AbstractWell.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * 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.rng.internal.source32; - -import java.util.Arrays; -import org.apache.commons.rng.internal.util.NumberFactory; - -/** - * This abstract class implements the WELL class of 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 1.0 - */ -public abstract class AbstractWell extends IntProvider { - /** Current index in the bytes pool. */ - protected int index; - /** Bytes pool. */ - protected final int[] v; - - /** - * Creates an instance with the given {@code seed}. - * - * @param k Number of bits in the pool (not necessarily a multiple of 32). - * @param seed Initial seed. - */ - protected AbstractWell(final int k, - final int[] seed) { - final int r = calculateBlockCount(k); - v = new int[r]; - index = 0; - - // Initialize the pool content. - setSeedInternal(seed); - } - - /** {@inheritDoc} */ - @Override - protected byte[] getStateInternal() { - final int[] s = Arrays.copyOf(v, v.length + 1); - s[v.length] = index; - - return NumberFactory.makeByteArray(s); - } - - /** {@inheritDoc} */ - @Override - protected void setStateInternal(byte[] s) { - checkStateSize(s, (v.length + 1) * 4); - - final int[] tmp = NumberFactory.makeIntArray(s); - System.arraycopy(tmp, 0, v, 0, v.length); - index = tmp[v.length]; - } - - /** - * Initializes the generator with the given {@code seed}. - * - * @param seed Seed. Cannot be null. - */ - private void setSeedInternal(final int[] seed) { - System.arraycopy(seed, 0, v, 0, Math.min(seed.length, v.length)); - - if (seed.length < v.length) { - for (int i = seed.length; i < v.length; ++i) { - final long current = v[i - seed.length]; - v[i] = (int) ((1812433253L * (current ^ (current >> 30)) + i) & 0xffffffffL); - } - } - - index = 0; - } - - /** - * Calculate the number of 32-bits blocks. - * - * @param k Number of bits in the pool (not necessarily a multiple of 32). - * @return the number of 32-bits blocks. - */ - private static int calculateBlockCount(final int k) { - // the bits pool contains k bits, k = r w - p where r is the number - // of w bits blocks, w is the block size (always 32 in the original paper) - // and p is the number of unused bits in the last block - final int w = 32; - final int r = (k + w - 1) / w; - return r; - } - - /** - * Inner class used to store the indirection index table which is fixed for a given - * type of WELL class of pseudo-random number generator. - */ - protected static final class IndexTable { - /** Index indirection table giving for each index its predecessor taking table size into account. */ - private final int[] iRm1; - /** Index indirection table giving for each index its second predecessor taking table size into account. */ - private final int[] iRm2; - /** Index indirection table giving for each index the value index + m1 taking table size into account. */ - private final int[] i1; - /** Index indirection table giving for each index the value index + m2 taking table size into account. */ - private final int[] i2; - /** Index indirection table giving for each index the value index + m3 taking table size into account. */ - private final int[] i3; - - /** Creates a new pre-calculated indirection index table. - * @param k number of bits in the pool (not necessarily a multiple of 32) - * @param m1 first parameter of the algorithm - * @param m2 second parameter of the algorithm - * @param m3 third parameter of the algorithm - */ - public IndexTable(final int k, final int m1, final int m2, final int m3) { - - final int r = calculateBlockCount(k); - - // precompute indirection index tables. These tables are used for optimizing access - // they allow saving computations like "(j + r - 2) % r" with costly modulo operations - iRm1 = new int[r]; - iRm2 = new int[r]; - i1 = new int[r]; - i2 = new int[r]; - i3 = new int[r]; - for (int j = 0; j < r; ++j) { - iRm1[j] = (j + r - 1) % r; - iRm2[j] = (j + r - 2) % r; - i1[j] = (j + m1) % r; - i2[j] = (j + m2) % r; - i3[j] = (j + m3) % r; - } - } - - /** - * Returns the predecessor of the given index modulo the table size. - * @param index the index to look at - * @return (index - 1) % table size - */ - public int getIndexPred(final int index) { - return iRm1[index]; - } - - /** - * Returns the second predecessor of the given index modulo the table size. - * @param index the index to look at - * @return (index - 2) % table size - */ - public int getIndexPred2(final int index) { - return iRm2[index]; - } - - /** - * Returns index + M1 modulo the table size. - * @param index the index to look at - * @return (index + M1) % table size - */ - public int getIndexM1(final int index) { - return i1[index]; - } - - /** - * Returns index + M2 modulo the table size. - * @param index the index to look at - * @return (index + M2) % table size - */ - public int getIndexM2(final int index) { - return i2[index]; - } - - /** - * Returns index + M3 modulo the table size. - * @param index the index to look at - * @return (index + M3) % table size - */ - public int getIndexM3(final int index) { - return i3[index]; - } - } -} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/ISAACRandom.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/ISAACRandom.java b/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/ISAACRandom.java deleted file mode 100644 index 79433c9..0000000 --- a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/ISAACRandom.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * 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.rng.internal.source32; - -import java.util.Arrays; -import org.apache.commons.rng.internal.util.NumberFactory; - -/** - * A fast cryptographic pseudo-random number generator. - * <p> - * ISAAC (Indirection, Shift, Accumulate, Add, and Count) generates 32-bit - * random numbers. - * ISAAC has been designed to be cryptographically secure and is inspired - * by RC4. - * Cycles are guaranteed to be at least 2<sup>40</sup> values long, and they - * are 2<sup>8295</sup> values long on average. - * The results are uniformly distributed, unbiased, and unpredictable unless - * you know the seed. - * <p> - * This code is based (with minor changes and improvements) on the original - * implementation of the algorithm by Bob Jenkins. - * - * @see <a href="http://burtleburtle.net/bob/rand/isaacafa.html"> - * ISAAC: a fast cryptographic pseudo-random number generator</a> - * - * @see <a href="https://en.wikipedia.org/wiki/ISAAC_(cipher)">ISAAC (Wikipedia)</a> - * @since 1.0 - */ -public class ISAACRandom extends IntProvider { - /** Log of size of rsl[] and mem[]. */ - private static final int SIZE_L = 8; - /** Size of rsl[] and mem[]. */ - private static final int SIZE = 1 << SIZE_L; - /** Half-size of rsl[] and mem[]. */ - private static final int H_SIZE = SIZE >> 1; - /** For pseudo-random lookup. */ - private static final int MASK = SIZE - 1 << 2; - /** The golden ratio. */ - private static final int GLD_RATIO = 0x9e3779b9; - /** The results given to the user. */ - private final int[] rsl = new int[SIZE]; - /** The internal state. */ - private final int[] mem = new int[SIZE]; - /** Count through the results in rsl[]. */ - private int count; - /** Accumulator. */ - private int isaacA; - /** The last result. */ - private int isaacB; - /** Counter, guarantees cycle is at least 2^40. */ - private int isaacC; - /** Service variable. */ - private final int[] arr = new int[8]; - /** Service variable. */ - private int isaacX; - /** Service variable. */ - private int isaacI; - /** Service variable. */ - private int isaacJ; - - /** - * Creates a new ISAAC random number generator. - * - * @param seed Initial seed - */ - public ISAACRandom(int[] seed) { - setSeedInternal(seed); - } - - /** {@inheritDoc} */ - @Override - protected byte[] getStateInternal() { - final int[] sRsl = Arrays.copyOf(rsl, SIZE); - final int[] sMem = Arrays.copyOf(mem, SIZE); - final int[] sRem = Arrays.copyOf(new int[] { count, isaacA, isaacB, isaacC }, 4); - - final int[] s = new int[2 * SIZE + sRem.length]; - System.arraycopy(sRsl, 0, s, 0, SIZE); - System.arraycopy(sMem, 0, s, SIZE, SIZE); - System.arraycopy(sRem, 0, s, 2 * SIZE, sRem.length); - - return NumberFactory.makeByteArray(s); - } - - /** {@inheritDoc} */ - @Override - protected void setStateInternal(byte[] s) { - checkStateSize(s, (2 * SIZE + 4) * 4); - - final int[] tmp = NumberFactory.makeIntArray(s); - System.arraycopy(tmp, 0, rsl, 0, SIZE); - System.arraycopy(tmp, SIZE, mem, 0, SIZE); - final int offset = 2 * SIZE; - count = tmp[offset]; - isaacA = tmp[offset + 1]; - isaacB = tmp[offset + 2]; - isaacC = tmp[offset + 3]; - } - - /** - * Reseeds the RNG. - * - * @param seed Seed. Cannot be null. - */ - private void setSeedInternal(int[] seed) { - final int seedLen = seed.length; - final int rslLen = rsl.length; - System.arraycopy(seed, 0, rsl, 0, Math.min(seedLen, rslLen)); - if (seedLen < rslLen) { - for (int j = seedLen; j < rslLen; j++) { - long k = rsl[j - seedLen]; - rsl[j] = (int) (0x6c078965L * (k ^ k >> 30) + j & 0xffffffffL); - } - } - initState(); - } - - /** {@inheritDoc} */ - @Override - public int next() { - if (count < 0) { - isaac(); - count = SIZE - 1; - } - return rsl[count--]; - } - - /** Generate 256 results */ - private void isaac() { - isaacI = 0; - isaacJ = H_SIZE; - isaacB += ++isaacC; - while (isaacI < H_SIZE) { - isaac2(); - } - isaacJ = 0; - while (isaacJ < H_SIZE) { - isaac2(); - } - } - - /** Intermediate internal loop. */ - private void isaac2() { - isaacX = mem[isaacI]; - isaacA ^= isaacA << 13; - isaacA += mem[isaacJ++]; - isaac3(); - isaacX = mem[isaacI]; - isaacA ^= isaacA >>> 6; - isaacA += mem[isaacJ++]; - isaac3(); - isaacX = mem[isaacI]; - isaacA ^= isaacA << 2; - isaacA += mem[isaacJ++]; - isaac3(); - isaacX = mem[isaacI]; - isaacA ^= isaacA >>> 16; - isaacA += mem[isaacJ++]; - isaac3(); - } - - /** Lowest level internal loop. */ - private void isaac3() { - mem[isaacI] = mem[(isaacX & MASK) >> 2] + isaacA + isaacB; - isaacB = mem[(mem[isaacI] >> SIZE_L & MASK) >> 2] + isaacX; - rsl[isaacI++] = isaacB; - } - - /** Initialize, or reinitialize, this instance of rand. */ - private void initState() { - isaacA = 0; - isaacB = 0; - isaacC = 0; - for (int j = 0; j < arr.length; j++) { - arr[j] = GLD_RATIO; - } - for (int j = 0; j < 4; j++) { - shuffle(); - } - // fill in mem[] with messy stuff - for (int j = 0; j < SIZE; j += 8) { - arr[0] += rsl[j]; - arr[1] += rsl[j + 1]; - arr[2] += rsl[j + 2]; - arr[3] += rsl[j + 3]; - arr[4] += rsl[j + 4]; - arr[5] += rsl[j + 5]; - arr[6] += rsl[j + 6]; - arr[7] += rsl[j + 7]; - shuffle(); - setState(j); - } - // second pass makes all of seed affect all of mem - for (int j = 0; j < SIZE; j += 8) { - arr[0] += mem[j]; - arr[1] += mem[j + 1]; - arr[2] += mem[j + 2]; - arr[3] += mem[j + 3]; - arr[4] += mem[j + 4]; - arr[5] += mem[j + 5]; - arr[6] += mem[j + 6]; - arr[7] += mem[j + 7]; - shuffle(); - setState(j); - } - isaac(); - count = SIZE - 1; - } - - /** Shuffle array. */ - private void shuffle() { - arr[0] ^= arr[1] << 11; - arr[3] += arr[0]; - arr[1] += arr[2]; - arr[1] ^= arr[2] >>> 2; - arr[4] += arr[1]; - arr[2] += arr[3]; - arr[2] ^= arr[3] << 8; - arr[5] += arr[2]; - arr[3] += arr[4]; - arr[3] ^= arr[4] >>> 16; - arr[6] += arr[3]; - arr[4] += arr[5]; - arr[4] ^= arr[5] << 10; - arr[7] += arr[4]; - arr[5] += arr[6]; - arr[5] ^= arr[6] >>> 4; - arr[0] += arr[5]; - arr[6] += arr[7]; - arr[6] ^= arr[7] << 8; - arr[1] += arr[6]; - arr[7] += arr[0]; - arr[7] ^= arr[0] >>> 9; - arr[2] += arr[7]; - arr[0] += arr[1]; - } - - /** Set the state by copying the internal arrays. - * - * @param start First index into {@link #mem} array. - */ - private void setState(int start) { - mem[start] = arr[0]; - mem[start + 1] = arr[1]; - mem[start + 2] = arr[2]; - mem[start + 3] = arr[3]; - mem[start + 4] = arr[4]; - mem[start + 5] = arr[5]; - mem[start + 6] = arr[6]; - mem[start + 7] = arr[7]; - } -} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/IntProvider.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/IntProvider.java b/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/IntProvider.java deleted file mode 100644 index ba30fd9..0000000 --- a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/IntProvider.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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.rng.internal.source32; - -import org.apache.commons.rng.internal.util.NumberFactory; -import org.apache.commons.rng.internal.BaseProvider; - -/** - * Base class for all implementations that provide an {@code int}-based - * source randomness. - */ -public abstract class IntProvider - extends BaseProvider - implements RandomIntSource { - - /** {@inheritDoc} */ - @Override - public abstract int next(); - - /** {@inheritDoc} */ - @Override - public int nextInt() { - return next(); - } - - /** {@inheritDoc} */ - @Override - public boolean nextBoolean() { - return NumberFactory.makeBoolean(nextInt()); - } - - /** {@inheritDoc} */ - @Override - public double nextDouble() { - return NumberFactory.makeDouble(nextInt(), nextInt()); - } - - /** {@inheritDoc} */ - @Override - public float nextFloat() { - return NumberFactory.makeFloat(nextInt()); - } - - /** {@inheritDoc} */ - @Override - public long nextLong() { - return NumberFactory.makeLong(nextInt(), 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) { - checkIndex(0, bytes.length - 1, start); - checkIndex(0, bytes.length - start, len); - - 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 int} 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(RandomIntSource source, - byte[] bytes, - int start, - int len) { - int index = start; // Index of first insertion. - - // Index of first insertion plus multiple of 4 part of length - // (i.e. length with 2 least significant bits unset). - final int indexLoopLimit = index + (len & 0x7ffffffc); - - // Start filling in the byte array, 4 bytes at a time. - while (index < indexLoopLimit) { - final int random = source.next(); - bytes[index++] = (byte) random; - bytes[index++] = (byte) (random >>> 8); - bytes[index++] = (byte) (random >>> 16); - bytes[index++] = (byte) (random >>> 24); - } - - final int indexLimit = start + len; // Index of last insertion + 1. - - // Fill in the remaining bytes. - if (index < indexLimit) { - int 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-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/JDKRandom.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/JDKRandom.java b/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/JDKRandom.java deleted file mode 100644 index 028469b..0000000 --- a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/JDKRandom.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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.rng.internal.source32; - -import java.util.Random; -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ByteArrayInputStream; - -/** - * A provider that uses the {@link Random#nextInt()} method of the JDK's - * {@link Random} class as the source of randomness. - * - * <p> - * <b>Caveat:</b> All the other calls will be redirected to the methods - * implemented within this library. - * </p> - * - * <p> - * The state of this source of randomness is saved and restored through - * the serialization of the {@link Random} instance. - * </p> - * - * @since 1.0 - */ -public class JDKRandom extends IntProvider { - /** Delegate. Cannot be "final" (to allow serialization). */ - private Random delegate; - - /** - * Creates an instance with the given seed. - * - * @param seed Initial seed. - */ - public JDKRandom(Long seed) { - delegate = new Random(seed); - } - - /** - * {@inheritDoc} - * - * @see Random#nextInt() - */ - @Override - public int next() { - return delegate.nextInt(); - } - - /** {@inheritDoc} */ - @Override - protected byte[] getStateInternal() { - try { - final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - final ObjectOutputStream oos = new ObjectOutputStream(bos); - - // Serialize the "delegate". - oos.writeObject(delegate); - - return bos.toByteArray(); - } catch (IOException e) { - // Workaround checked exception. - throw new RuntimeException(e); - } - } - - /** {@inheritDoc} */ - @Override - protected void setStateInternal(byte[] s) { - try { - final ByteArrayInputStream bis = new ByteArrayInputStream(s); - final ObjectInputStream ois = new ObjectInputStream(bis); - - delegate = (Random) ois.readObject(); - } catch (ClassNotFoundException e) { - // Workaround checked exception. - throw new RuntimeException(e); - } catch (IOException e) { - // Workaround checked exception. - throw new RuntimeException(e); - } - } -} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/ec3720f2/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/KISSRandom.java ---------------------------------------------------------------------- diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/KISSRandom.java b/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/KISSRandom.java deleted file mode 100644 index 7f5e68b..0000000 --- a/commons-rng-core/src/main/java/org/apache/commons/rng/internal/source32/KISSRandom.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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.rng.internal.source32; - -import org.apache.commons.rng.internal.util.NumberFactory; - -/** - * Port from Marsaglia's <a href="http://www.cse.yorku.ca/~oz/marsaglia-rng.html"> - * "KISS" algorithm</a>. - * This version contains the correction referred to - * <a href="https://programmingpraxis.com/2010/10/05/george-marsaglias-random-number-generators/">here</a> - * in a reply to the original post. - * - * @see <a href="https://en.wikipedia.org/wiki/KISS_(algorithm)">KISS (Wikipedia)</a> - * @since 1.0 - */ -public class KISSRandom extends IntProvider { - /** Size of the seed. */ - private static final int SEED_SIZE = 4; - /** State variable. */ - private int z; - /** State variable. */ - private int w; - /** State variable. */ - private int jsr; - /** State variable. */ - private int jcong; - - /** - * Creates a new instance. - * - * @param seed Seed. - * If the length is larger than 4, only the first 4 elements will - * be used; if smaller, the remaining elements will be automatically - * set. - */ - public KISSRandom(int[] seed) { - setSeedInternal(seed); - } - - /** {@inheritDoc} */ - @Override - protected byte[] getStateInternal() { - return NumberFactory.makeByteArray(new int[] { z, w, jsr, jcong }); - } - - /** {@inheritDoc} */ - @Override - protected void setStateInternal(byte[] s) { - checkStateSize(s, SEED_SIZE * 4); - - final int[] tmp = NumberFactory.makeIntArray(s); - - z = tmp[0]; - w = tmp[1]; - jsr = tmp[2]; - jcong = tmp[3]; - } - - /** - * Seeds the RNG. - * - * @param seed Seed. - */ - private void setSeedInternal(int[] seed) { - // Reset the whole state of this RNG (i.e. the 4 state variables). - // Filling procedure is not part of the reference code. - final int[] tmp = new int[SEED_SIZE]; - fillState(tmp, seed); - - z = tmp[0]; - w = tmp[1]; - jsr = tmp[2]; - jcong = tmp[3]; - } - - /** {@inheritDoc} */ - @Override - public int next() { - z = computeNew(36969, z); - w = computeNew(18000, w); - final int mwc = (z << 16) + w; - - // Cf. correction mentioned in the reply to the original post: - // https://programmingpraxis.com/2010/10/05/george-marsaglias-random-number-generators/ - jsr ^= jsr << 13; - jsr ^= jsr >>> 17; - jsr ^= jsr << 5; - - jcong = 69069 * jcong + 1234567; - - return (mwc ^ jcong) + jsr; - } - - /** - * Compute new value. - * - * @param mult Multiplier. - * @param previous Previous value. - * @return new value. - */ - private int computeNew(int mult, - int previous) { - return mult * (previous & 65535) + (previous >>> 16); - } -}
