You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2016/08/07 22:52:01 UTC
[36/39] commons-rng git commit: Initial commit.
http://git-wip-us.apache.org/repos/asf/commons-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/AbstractWell.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/AbstractWell.java b/src/main/java/org/apache/commons/rng/internal/source32/AbstractWell.java
new file mode 100644
index 0000000..d1ac45f
--- /dev/null
+++ b/src/main/java/org/apache/commons/rng/internal/source32/AbstractWell.java
@@ -0,0 +1,204 @@
+/*
+ * 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 4.0
+ */
+public abstract class AbstractWell extends IntProvider {
+ /** Current index in the bytes pool. */
+ protected int index;
+ /** Bytes pool. */
+ protected final int[] v;
+
+ /**
+ * Creates a new random number generator using an int array 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];
+ }
+
+ /**
+ * Reinitialize the generator as if just built with the given int array seed.
+ *
+ * <p>The state of the generator is exactly the same as a new generator built
+ * with the same seed.</p>
+ *
+ * @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/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/ISAACRandom.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/ISAACRandom.java b/src/main/java/org/apache/commons/rng/internal/source32/ISAACRandom.java
new file mode 100644
index 0000000..7145735
--- /dev/null
+++ b/src/main/java/org/apache/commons/rng/internal/source32/ISAACRandom.java
@@ -0,0 +1,266 @@
+/*
+ * 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>
+ *
+ * @since 4.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/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/IntProvider.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/IntProvider.java b/src/main/java/org/apache/commons/rng/internal/source32/IntProvider.java
new file mode 100644
index 0000000..ba30fd9
--- /dev/null
+++ b/src/main/java/org/apache/commons/rng/internal/source32/IntProvider.java
@@ -0,0 +1,130 @@
+/*
+ * 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/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/JDKRandom.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/JDKRandom.java b/src/main/java/org/apache/commons/rng/internal/source32/JDKRandom.java
new file mode 100644
index 0000000..1a44d34
--- /dev/null
+++ b/src/main/java/org/apache/commons/rng/internal/source32/JDKRandom.java
@@ -0,0 +1,95 @@
+/*
+ * 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
+ * {@code 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 4.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|IOException e) {
+ // Workaround checked exception.
+ throw new RuntimeException(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/commons-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/MersenneTwister.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/MersenneTwister.java b/src/main/java/org/apache/commons/rng/internal/source32/MersenneTwister.java
new file mode 100644
index 0000000..13c521d
--- /dev/null
+++ b/src/main/java/org/apache/commons/rng/internal/source32/MersenneTwister.java
@@ -0,0 +1,226 @@
+/*
+ * 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 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) {
+ checkStateSize(s, (N + 1) * 4);
+
+ 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-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/RandomIntSource.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/RandomIntSource.java b/src/main/java/org/apache/commons/rng/internal/source32/RandomIntSource.java
new file mode 100644
index 0000000..b4739db
--- /dev/null
+++ b/src/main/java/org/apache/commons/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.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-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/Well1024a.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/Well1024a.java b/src/main/java/org/apache/commons/rng/internal/source32/Well1024a.java
new file mode 100644
index 0000000..0912d63
--- /dev/null
+++ b/src/main/java/org/apache/commons/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.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-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/Well19937a.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/Well19937a.java b/src/main/java/org/apache/commons/rng/internal/source32/Well19937a.java
new file mode 100644
index 0000000..e4dc5ca
--- /dev/null
+++ b/src/main/java/org/apache/commons/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.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-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/Well19937c.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/Well19937c.java b/src/main/java/org/apache/commons/rng/internal/source32/Well19937c.java
new file mode 100644
index 0000000..8acbb81
--- /dev/null
+++ b/src/main/java/org/apache/commons/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.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-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/Well44497a.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/Well44497a.java b/src/main/java/org/apache/commons/rng/internal/source32/Well44497a.java
new file mode 100644
index 0000000..e72950a
--- /dev/null
+++ b/src/main/java/org/apache/commons/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.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-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/Well44497b.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/Well44497b.java b/src/main/java/org/apache/commons/rng/internal/source32/Well44497b.java
new file mode 100644
index 0000000..c1ef533
--- /dev/null
+++ b/src/main/java/org/apache/commons/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.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-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/Well512a.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/Well512a.java b/src/main/java/org/apache/commons/rng/internal/source32/Well512a.java
new file mode 100644
index 0000000..a059a2d
--- /dev/null
+++ b/src/main/java/org/apache/commons/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.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-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source32/package-info.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source32/package-info.java b/src/main/java/org/apache/commons/rng/internal/source32/package-info.java
new file mode 100644
index 0000000..e814765
--- /dev/null
+++ b/src/main/java/org/apache/commons/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.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.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.rng.RandomSource
+ * factory methods}.
+ * </li>
+ * </ul>
+ */
+
+package org.apache.commons.rng.internal.source32;
http://git-wip-us.apache.org/repos/asf/commons-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source64/LongProvider.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source64/LongProvider.java b/src/main/java/org/apache/commons/rng/internal/source64/LongProvider.java
new file mode 100644
index 0000000..1fb096d
--- /dev/null
+++ b/src/main/java/org/apache/commons/rng/internal/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.internal.source64;
+
+import org.apache.commons.rng.internal.util.NumberFactory;
+import org.apache.commons.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) {
+ 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/c0495bf2/src/main/java/org/apache/commons/rng/internal/source64/MersenneTwister64.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source64/MersenneTwister64.java b/src/main/java/org/apache/commons/rng/internal/source64/MersenneTwister64.java
new file mode 100644
index 0000000..badb92c
--- /dev/null
+++ b/src/main/java/org/apache/commons/rng/internal/source64/MersenneTwister64.java
@@ -0,0 +1,197 @@
+/*
+ * 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.source64;
+
+import java.util.Arrays;
+import org.apache.commons.rng.internal.util.NumberFactory;
+
+/**
+ * This class provides the 64-bits version of the originally 32-bits
+ * {@link org.apache.commons.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) {
+ checkStateSize(s, (NN + 1) * 8);
+
+ 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-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source64/RandomLongSource.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source64/RandomLongSource.java b/src/main/java/org/apache/commons/rng/internal/source64/RandomLongSource.java
new file mode 100644
index 0000000..eb96a02
--- /dev/null
+++ b/src/main/java/org/apache/commons/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.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-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source64/SplitMix64.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source64/SplitMix64.java b/src/main/java/org/apache/commons/rng/internal/source64/SplitMix64.java
new file mode 100644
index 0000000..904b2b1
--- /dev/null
+++ b/src/main/java/org/apache/commons/rng/internal/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.internal.source64;
+
+import org.apache.commons.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) {
+ checkStateSize(s, 8);
+
+ state = NumberFactory.makeLong(s);
+ }
+}
http://git-wip-us.apache.org/repos/asf/commons-rng/blob/c0495bf2/src/main/java/org/apache/commons/rng/internal/source64/TwoCmres.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/rng/internal/source64/TwoCmres.java b/src/main/java/org/apache/commons/rng/internal/source64/TwoCmres.java
new file mode 100644
index 0000000..87a4a3e
--- /dev/null
+++ b/src/main/java/org/apache/commons/rng/internal/source64/TwoCmres.java
@@ -0,0 +1,308 @@
+/*
+ * 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.source64;
+
+import java.util.List;
+import java.util.ArrayList;
+import org.apache.commons.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 {
+ /** 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));
+ }
+ }
+ }
+}