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/04/22 01:15:22 UTC
[36/53] [abbrv] [math] MATH-1335.
MATH-1335.
New package "o.a.c.m.rng" contains RNG core functionality (uniform distribution).
Utilities to interface with stress test suites.
Userguide: benchmarks and stress test suites reports (MATH-1327).
Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/6ddf4769
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/6ddf4769
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/6ddf4769
Branch: refs/heads/develop
Commit: 6ddf4769919bb32cc43c5bf43e2f4e7526d3cda0
Parents: 7a8dc00
Author: Gilles <er...@apache.org>
Authored: Fri Mar 11 01:51:58 2016 +0100
Committer: Gilles <er...@apache.org>
Committed: Sun Mar 20 23:29:55 2016 +0100
----------------------------------------------------------------------
.../apache/commons/math4/rng/RandomSource.java | 417 ++
.../math4/rng/UniformRandomProvider.java | 118 +
.../math4/rng/internal/BaseProvider.java | 141 +
.../math4/rng/internal/ProviderBuilder.java | 346 ++
.../math4/rng/internal/StateSettable.java | 49 +
.../math4/rng/internal/package-info.java | 51 +
.../rng/internal/source32/AbstractWell.java | 208 +
.../rng/internal/source32/ISAACRandom.java | 270 ++
.../rng/internal/source32/IntProvider.java | 137 +
.../math4/rng/internal/source32/JDKRandom.java | 95 +
.../rng/internal/source32/MersenneTwister.java | 230 ++
.../rng/internal/source32/RandomIntSource.java | 30 +
.../math4/rng/internal/source32/Well1024a.java | 78 +
.../math4/rng/internal/source32/Well19937a.java | 80 +
.../math4/rng/internal/source32/Well19937c.java | 85 +
.../math4/rng/internal/source32/Well44497a.java | 83 +
.../math4/rng/internal/source32/Well44497b.java | 90 +
.../math4/rng/internal/source32/Well512a.java | 78 +
.../rng/internal/source32/package-info.java | 52 +
.../rng/internal/source64/LongProvider.java | 141 +
.../internal/source64/MersenneTwister64.java | 201 +
.../rng/internal/source64/RandomLongSource.java | 30 +
.../math4/rng/internal/source64/SplitMix64.java | 78 +
.../math4/rng/internal/source64/TwoCmres.java | 310 ++
.../rng/internal/source64/XorShift1024Star.java | 108 +
.../rng/internal/source64/package-info.java | 52 +
.../math4/rng/internal/util/Int2Long.java | 37 +
.../math4/rng/internal/util/IntArray2Int.java | 41 +
.../rng/internal/util/IntArray2LongArray.java | 44 +
.../math4/rng/internal/util/Long2Int.java | 36 +
.../math4/rng/internal/util/Long2IntArray.java | 50 +
.../math4/rng/internal/util/Long2LongArray.java | 56 +
.../rng/internal/util/LongArray2IntArray.java | 43 +
.../math4/rng/internal/util/LongArray2Long.java | 41 +
.../math4/rng/internal/util/LongMixInt.java | 50 +
.../math4/rng/internal/util/LongMixLong.java | 56 +
.../math4/rng/internal/util/NoOpConverter.java | 40 +
.../math4/rng/internal/util/NumberFactory.java | 327 ++
.../math4/rng/internal/util/SeedConverter.java | 35 +
.../internal/util/SeedConverterComposer.java | 56 +
.../math4/rng/internal/util/SeedFactory.java | 262 ++
.../math4/rng/internal/util/package-info.java | 22 +
.../apache/commons/math4/rng/package-info.java | 95 +
src/site/apt/userguide/rng.apt | 228 +
.../txt/userguide/rng/stress/dh/run_1/dh_1 | 146 +
.../txt/userguide/rng/stress/dh/run_1/dh_10 | 139 +
.../txt/userguide/rng/stress/dh/run_1/dh_11 | 148 +
.../txt/userguide/rng/stress/dh/run_1/dh_12 | 172 +
.../txt/userguide/rng/stress/dh/run_1/dh_13 | 168 +
.../txt/userguide/rng/stress/dh/run_1/dh_2 | 139 +
.../txt/userguide/rng/stress/dh/run_1/dh_3 | 173 +
.../txt/userguide/rng/stress/dh/run_1/dh_4 | 140 +
.../txt/userguide/rng/stress/dh/run_1/dh_5 | 140 +
.../txt/userguide/rng/stress/dh/run_1/dh_6 | 146 +
.../txt/userguide/rng/stress/dh/run_1/dh_7 | 204 +
.../txt/userguide/rng/stress/dh/run_1/dh_8 | 201 +
.../txt/userguide/rng/stress/dh/run_1/dh_9 | 143 +
.../txt/userguide/rng/stress/dh/run_2/dh_1 | 146 +
.../txt/userguide/rng/stress/dh/run_2/dh_10 | 172 +
.../txt/userguide/rng/stress/dh/run_2/dh_11 | 259 ++
.../txt/userguide/rng/stress/dh/run_2/dh_12 | 168 +
.../txt/userguide/rng/stress/dh/run_2/dh_13 | 261 ++
.../txt/userguide/rng/stress/dh/run_2/dh_2 | 140 +
.../txt/userguide/rng/stress/dh/run_2/dh_3 | 139 +
.../txt/userguide/rng/stress/dh/run_2/dh_4 | 171 +
.../txt/userguide/rng/stress/dh/run_2/dh_5 | 143 +
.../txt/userguide/rng/stress/dh/run_2/dh_6 | 260 ++
.../txt/userguide/rng/stress/dh/run_2/dh_7 | 143 +
.../txt/userguide/rng/stress/dh/run_2/dh_8 | 800 ++++
.../txt/userguide/rng/stress/dh/run_2/dh_9 | 175 +
.../txt/userguide/rng/stress/tu/run_1/tu_1 | 3882 ++++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_10 | 3803 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_11 | 3795 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_12 | 3803 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_13 | 3802 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_2 | 3803 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_3 | 3807 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_4 | 3806 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_5 | 3804 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_6 | 3804 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_7 | 3803 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_8 | 3804 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_1/tu_9 | 3802 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_1 | 3879 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_10 | 3803 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_11 | 3795 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_12 | 3795 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_13 | 3795 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_2 | 3803 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_3 | 3808 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_4 | 3805 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_5 | 3804 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_6 | 3803 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_7 | 3803 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_8 | 3803 +++++++++++++++++
.../txt/userguide/rng/stress/tu/run_2/tu_9 | 3795 +++++++++++++++++
src/site/site.xml | 1 +
src/site/xdoc/userguide/index.xml | 7 +
.../math4/rng/Providers32ParametricTest.java | 64 +
.../math4/rng/Providers64ParametricTest.java | 64 +
.../rng/ProvidersCommonParametricTest.java | 667 +++
.../apache/commons/math4/rng/ProvidersList.java | 157 +
.../rng/internal/source32/ISAACRandomTest.java | 389 ++
.../rng/internal/source32/JDKRandomTest.java | 38 +
.../internal/source32/MersenneTwisterTest.java | 240 ++
.../rng/internal/source32/Well1024aTest.java | 71 +
.../rng/internal/source32/Well19937aTest.java | 109 +
.../rng/internal/source32/Well19937cTest.java | 109 +
.../rng/internal/source32/Well44497aTest.java | 109 +
.../rng/internal/source32/Well44497bTest.java | 109 +
.../rng/internal/source32/Well512aTest.java | 69 +
.../source64/MersenneTwister64Test.java | 239 ++
.../rng/internal/source64/SplitMix64Test.java | 45 +
.../rng/internal/source64/TwoCmresTest.java | 55 +
.../internal/source64/XorShift1024StarTest.java | 55 +
.../rng/internal/util/NumberFactoryTest.java | 164 +
.../rng/internal/util/SeedFactoryTest.java | 111 +
src/userguide/README | 15 +-
src/userguide/c/rng/stdin2testu01.c | 127 +
.../math4/userguide/rng/GeneratorsList.java | 57 +
.../math4/userguide/rng/RandomStressTester.java | 280 ++
src/userguide/pom.xml | 30 +
122 files changed, 112502 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/RandomSource.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/rng/RandomSource.java b/src/main/java/org/apache/commons/math4/rng/RandomSource.java
new file mode 100644
index 0000000..087960c
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/rng/RandomSource.java
@@ -0,0 +1,417 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.rng;
+
+import org.apache.commons.math4.exception.MathUnsupportedOperationException;
+import org.apache.commons.math4.rng.internal.ProviderBuilder;
+import org.apache.commons.math4.rng.internal.BaseProvider;
+import org.apache.commons.math4.rng.internal.util.SeedFactory;
+import org.apache.commons.math4.rng.internal.source64.TwoCmres;
+
+/**
+ * This class provides the API for creating generators of random numbers.
+ * <p>
+ * Usage examples:
+ * <pre><code>
+ * UniformRandomProvider rng = RandomSource.create(RandomSource.MT);
+ * </code></pre>
+ * or
+ * <pre><code>
+ * final int[] seed = new int[] { 196, 9, 0, 226 };
+ * UniformRandomProvider rng = RandomSource.create(RandomSource.MT, seed);
+ * </code></pre>
+ * or
+ * <pre><code>
+ * final int[] seed = RandomSource.createIntArray(256);
+ * UniformRandomProvider rng = RandomSource.create(RandomSource.MT, seed);
+ * </code></pre>
+ * where the first argument to method {@code create} is the identifier
+ * of the generator's concrete implementation, and the second the is the
+ * (optional) seed.
+ * <br>
+ * In the first form, a random seed will be {@link SeedFactory generated
+ * automatically}; the random seed generation step is explicit in the
+ * third form.
+ * </p>
+ *
+ * <p>
+ * Seeding is the procedure by which a value (or set of values) is
+ * used to <i>initialize</i> a generator instance.
+ * The requirement that a given seed will always result in the same
+ * internal state allows to create different instances of a generator
+ * that will produce the same sequence of pseudo-random numbers.
+ * </p>
+ *
+ * <p>
+ * The type of data used as a seed depends on the concrete implementation
+ * as some types may not provide enough information to fully initialize
+ * the generator's internal state.
+ * <br>
+ * The reference algorithm's seeding procedure (if provided) operates
+ * on a value of a (single) <i>native</i> type:
+ * Each concrete implementation's constructor creates an instance using
+ * the native type whose information contents is used to set the
+ * internal state.
+ * <br>
+ * When the seed value passed by the caller is of the native type, it is
+ * expected that the sequences produced will be the same as those
+ * produced by other implementations of the algorithm.
+ * <br>
+ * However, when the seed value passed by the caller is not of the native
+ * type, a transformation is performed by this library and the resulting
+ * native type value will <i>not</i> contain more information than the
+ * original seed value.
+ * If the algorithm's native type is "simpler" than the type passed by
+ * the caller, then some (unuse) information will even be lost.
+ * <br>
+ * The transformation from non-native to native seed type is arbitrary,
+ * as long as it does not reduce the amount of information required by
+ * the algorithm to initialize its state.
+ * The consequence of the transformation is that the sequences produced
+ * by this library may not be the same as the sequences produced by other
+ * implementations of the same algorithm!
+ * </p>
+ *
+ * <p>
+ * This class provides methods to generate random seeds (single values
+ * or arrays of values, of {@code int} or {@code long} types) that can
+ * be passed to the {@link RandomSource#create(RandomSource,Object,Object[])
+ * generators factory method}.
+ * <br>
+ * Although the seed-generating methods defined in this class will likely
+ * return different values for all calls, there is no guarantee that the
+ * produced seed will result always in a "good" sequence of numbers, even
+ * if the generator is good.
+ * The only way to ensure that the selected seed will make the generator
+ * produce a "good" sequence is to submit that sequence to a series of
+ * stringent tests, as provided by tools such as
+ * <a href="http://www.phy.duke.edu/~rgb/General/dieharder.php">dieharder</a>
+ * or <a href="http://simul.iro.umontreal.ca/testu01/tu01.html">TestU01</a>.
+ * </p>
+ *
+ * <p>
+ * The current implementations have no provision for producing non-overlapping
+ * sequences.
+ * For parallel applications, a possible workaround is that each thread uses
+ * a generator of a different type (see {@link #TWO_CMRES_SELECT}).
+ * </p>
+ *
+ * <p>
+ * <b>Note:</b>
+ * Seeding is not equivalent to restoring the internal state of an
+ * <i>already initialized</i> generator.
+ * Indeed, generators can have a state that is more complex than the
+ * seed, and seeding is thus a transformation (from seed to state).
+ * Implementations do not provide the inverse transformation (from
+ * state to seed), hence it is not generally possible to know the seed
+ * that would initialize a new generator instance to the current state
+ * of another instance.
+ * Reseeding is also inefficient if the purpose is to continue the
+ * same sequence where another instance left off, as it would require
+ * to "replay" all the calls performed by that other instance (and it
+ * would require to know the number of calls to the primary source of
+ * randomness, which is also not usually accessible).
+ * <br>
+ * This factory thus provides a method for
+ * {@link #saveState(UniformRandomProvider) saving} the internal
+ * state of a generator.
+ * The state is encapsulated in an {@link State "opaque object"} to be
+ * used for {@link #restoreState(UniformRandomProvider,State) restoring}
+ * a generator (of the same type) to an identical state (e.g. to allow
+ * persistent storage, or to continue a sequence from where the original
+ * instance left off.).
+ * </p>
+ *
+ * @since 4.0
+ */
+public enum RandomSource {
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source32.JDKRandom}.
+ * Native seed type: {@code Long}.
+ */
+ JDK(ProviderBuilder.RandomSourceInternal.JDK),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source32.Well512a}.
+ * Native seed type: {@code int[]}.
+ */
+ WELL_512_A(ProviderBuilder.RandomSourceInternal.WELL_512_A),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source32.Well1024a}.
+ * Native seed type: {@code int[]}.
+ */
+ WELL_1024_A(ProviderBuilder.RandomSourceInternal.WELL_1024_A),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source32.Well19937a}.
+ * Native seed type: {@code int[]}.
+ */
+ WELL_19937_A(ProviderBuilder.RandomSourceInternal.WELL_19937_A),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source32.Well19937c}.
+ * Native seed type: {@code int[]}.
+ */
+ WELL_19937_C(ProviderBuilder.RandomSourceInternal.WELL_19937_C),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source32.Well44497a}.
+ * Native seed type: {@code int[]}.
+ */
+ WELL_44497_A(ProviderBuilder.RandomSourceInternal.WELL_44497_A),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source32.Well44497b}.
+ * Native seed type: {@code int[]}.
+ */
+ WELL_44497_B(ProviderBuilder.RandomSourceInternal.WELL_44497_B),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source32.MersenneTwister}.
+ * Native seed type: {@code int[]}.
+ */
+ MT(ProviderBuilder.RandomSourceInternal.MT),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source32.ISAACRandom}.
+ * Native seed type: {@code int[]}.
+ */
+ ISAAC(ProviderBuilder.RandomSourceInternal.ISAAC),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source64.SplitMix64}.
+ * Native seed type: {@code Long}.
+ */
+ SPLIT_MIX_64(ProviderBuilder.RandomSourceInternal.SPLIT_MIX_64),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source64.XorShift1024Star}.
+ * Native seed type: {@code long[]}.
+ */
+ XOR_SHIFT_1024_S(ProviderBuilder.RandomSourceInternal.XOR_SHIFT_1024_S),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source64.TwoCmres}.
+ * Native seed type: {@code Integer}.
+ */
+ TWO_CMRES(ProviderBuilder.RandomSourceInternal.TWO_CMRES),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source64.TwoCmres},
+ * with explicit selection of the two subcycle generators.
+ * Native seed type: {@code Integer}.
+ */
+ TWO_CMRES_SELECT(ProviderBuilder.RandomSourceInternal.TWO_CMRES_SELECT),
+ /**
+ * Source of randomness is {@link org.apache.commons.math4.rng.internal.source64.MersenneTwister64}.
+ * Native seed type: {@code long[]}.
+ */
+ MT_64(ProviderBuilder.RandomSourceInternal.MT_64);
+
+ /** Internal identifier. */
+ private final ProviderBuilder.RandomSourceInternal internalIdentifier;
+
+ /**
+ * @param id Internal identifier.
+ */
+ RandomSource(ProviderBuilder.RandomSourceInternal id) {
+ internalIdentifier = id;
+ }
+
+ /**
+ * @return the internal identifier.
+ */
+ ProviderBuilder.RandomSourceInternal getInternalIdentifier() {
+ return internalIdentifier;
+ }
+
+ /**
+ * Checks whether the type of given {@code seed} is the native type
+ * of the implementation.
+ *
+ * @param seed Seed value.
+ * @return {@code true} if the seed can be passed to the builder
+ * for this RNG type.
+ */
+ public boolean isNativeSeed(Object seed) {
+ return internalIdentifier.isNativeSeed(seed);
+ }
+
+ /**
+ * Marker interface used to define the "save" and "restore"
+ * functionality of the generators.
+ */
+ public interface State {}
+
+ /**
+ * Creates a random number generator with a random seed.
+ *
+ * <p>
+ * Example of usage:
+ * <pre><code>
+ * UniformRandomProvider rng = RandomSource.create(Source.MT);
+ * </code></pre>
+ * </p>
+ *
+ * @param source {@link RandomSource RNG type}.
+ * @return the RNG.
+ */
+ public static UniformRandomProvider create(RandomSource source) {
+ return create(source, null);
+ }
+
+ /**
+ * Creates a random number generator with the given {@code seed}.
+ *
+ * <p>
+ * Example of usage:
+ * <pre><code>
+ * UniformRandomProvider rng = RandomSource.create(Source.TWO_CMRES_SELECT, 26219, 6, 9);
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * Valid types for the {@code seed} are:
+ * <ul>
+ * <li>{@code Integer} (or {@code int})</li>
+ * <li>{@code Long} (or {@code long})</li>
+ * <li>{@code int[]}</li>
+ * <li>{@code long[]}</li>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * Notes:
+ * <ul>
+ * <li>
+ * When the seed type passed as argument is more complex (i.e. more
+ * bits can be independently chosen) than the generator's
+ * {@link #isNativeSeed(Object) native type}, the conversion of a
+ * set of different seeds will necessarily result in the same value
+ * of the native seed type.
+ * </li>
+ * <li>
+ * When the native seed type is an array, the same remark applies
+ * when the array contains more bits than the state of the generator.
+ * </li>
+ * <li>
+ * When the native seed type is an array and the {@code seed} is
+ * {@code null}, the size of the generated array will be 128.
+ * </li>
+ * </p>
+ *
+ * @param source {@link RandomSource RNG type}.
+ * @param seed Seed value. It can be {@code null} (in which case a
+ * random value will be used).
+ * @param data Additional arguments to the implementation's constructor.
+ * Please refer to the documentation of each specific implementation.
+ * @return the RNG.
+ * @throws MathUnsupportedOperationException if the type of the
+ * {@code seed} is invalid.
+ * @throws org.apache.commons.math4.exception.InsufficientDataException
+ * if data is missing to initialize the generator implemented by the
+ * given {@code source}.
+ */
+ public static UniformRandomProvider create(RandomSource source,
+ Object seed,
+ Object ... data) {
+ return ProviderBuilder.create(source.getInternalIdentifier(), seed, data);
+ }
+
+ /**
+ * Gets the number of elements of the set of "subcycle" generators from
+ * which two can be selected in order to create a {@link TwoCmres} RNG.
+ *
+ * @return the number of implemented subcycle generators.
+ */
+ public static int numberOfCmresGenerators() {
+ return TwoCmres.numberOfSubcycleGenerators();
+ }
+
+ /**
+ * Saves the state of a RNG.
+ *
+ * @param provider Provider.
+ * @return the current state of the given {@code provider}.
+ * @throws MathUnsupportedOperationException if the {@code provider} is
+ * not an object created by this factory or the underlying source of
+ * randomness does not support this functionality.
+ *
+ * @see #restoreState(UniformRandomProvider,RandomSource.State)
+ */
+ public static State saveState(UniformRandomProvider provider) {
+ if (!(provider instanceof BaseProvider)) {
+ throw new MathUnsupportedOperationException();
+ } else {
+ return ((BaseProvider) provider).getState();
+ }
+ }
+
+ /**
+ * Restores the state of a RNG.
+ *
+ * @param provider Provider.
+ * @param state State which the {@code provider} will be set to.
+ * This parameter must have been obtained by a call to
+ * {@link #saveState(UniformRandomProvider) saveState(rng)}
+ * where {@code rng} is either the same object as {@code provider},
+ * or an object of the same concrete type.
+ * @throws MathUnsupportedOperationException if the {@code provider} is
+ * not an object created by this factory or the underlying source of
+ * randomness does not support this functionality.
+ * @throws org.apache.commons.math4.exception.InsufficientDataException
+ * if it was detected that the {@code state} is incompatible with the
+ * given {@code provider}.
+ *
+ * @see #saveState(UniformRandomProvider)
+ */
+ public static void restoreState(UniformRandomProvider provider,
+ State state) {
+ if (!(provider instanceof BaseProvider)) {
+ throw new MathUnsupportedOperationException();
+ } else {
+ ((BaseProvider) provider).setState(state);
+ }
+ }
+
+ /**
+ * Creates a number for use as a seed.
+ *
+ * @return a random number.
+ */
+ public static int createInt() {
+ return SeedFactory.createInt();
+ }
+
+ /**
+ * Creates a number for use as a seed.
+ *
+ * @return a random number.
+ */
+ public static long createLong() {
+ return SeedFactory.createLong();
+ }
+
+ /**
+ * Creates an array of numbers for use as a seed.
+ *
+ * @param n Size of the array to create.
+ * @return an array of {@code n} random numbers.
+ */
+ public static int[] createIntArray(int n) {
+ return SeedFactory.createIntArray(n);
+ }
+
+ /**
+ * Creates an array of numbers for use as a seed.
+ *
+ * @param n Size of the array to create.
+ * @return an array of {@code n} random numbers.
+ */
+ public static long[] createLongArray(int n) {
+ return SeedFactory.createLongArray(n);
+ }
+}
http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/UniformRandomProvider.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/rng/UniformRandomProvider.java b/src/main/java/org/apache/commons/math4/rng/UniformRandomProvider.java
new file mode 100644
index 0000000..ef17f06
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/rng/UniformRandomProvider.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.rng;
+
+/**
+ * Applies to generators of random number sequences that follow a uniform
+ * distribution.
+ *
+ * @since 4.0
+ */
+public interface UniformRandomProvider {
+ /**
+ * Generates {@code byte} values and places them into a user-supplied array.
+ * <p>
+ * The number of random bytes produced is equal to the length of the
+ * the byte array.
+ * </p>
+ *
+ * @param bytes Byte array in which to put the random bytes.
+ * Cannot be {@code null}.
+ */
+ void nextBytes(byte[] bytes);
+
+ /**
+ * Generates {@code byte} values and places them into a user-supplied array.
+ *
+ * <p>
+ * The array is filled with bytes extracted from random integers.
+ * This implies that the number of random bytes generated may be larger than
+ * the length of the byte array.
+ * </p>
+ *
+ * @param bytes Array in which to put the generated bytes.
+ * Cannot be {@code null}.
+ * @param start Index at which to start inserting the generated bytes.
+ * @param len Number of bytes to insert.
+ * @throws org.apache.commons.math4.exception.OutOfRangeException
+ * if {@code start < 0} or {@code start >= bytes.length}.
+ * @throws org.apache.commons.math4.exception.OutOfRangeException
+ * if {@code len < 0} or {@code len > bytes.length - start}.
+ */
+ void nextBytes(byte[] bytes,
+ int start,
+ int len);
+
+ /**
+ * Generates an {@code int} value.
+ *
+ * @return the next random value.
+ */
+ int nextInt();
+
+ /**
+ * Generates an {@code int} value between 0 (inclusive) and the
+ * specified value (exclusive).
+ *
+ * @param n Bound on the random number to be returned. Must be positive.
+ * @return a random {@code int} value between 0 (inclusive) and n
+ * (exclusive).
+ * @throws org.apache.commons.math4.exception.NotStrictlyPositiveException
+ * if {@code n} is not positive.
+ */
+ int nextInt(int n);
+
+ /**
+ * Generates a {@code long} value.
+ *
+ * @return the next random value.
+ */
+ long nextLong();
+
+ /**
+ * Generates a {@code long} value between 0 (inclusive) and the specified
+ * value (exclusive).
+ *
+ * @param n Bound on the random number to be returned. Must be positive.
+ * @return a random {@code long} value between 0 (inclusive) and n
+ * (exclusive).
+ * @throws org.apache.commons.math4.exception.NotStrictlyPositiveException
+ * if {@code n} is not positive.
+ */
+ long nextLong(long n);
+
+ /**
+ * Generates a {@code boolean} value.
+ *
+ * @return the next random value.
+ */
+ boolean nextBoolean();
+
+ /**
+ * Generates a {@code float} value between 0 and 1.
+ *
+ * @return the next random value between 0 and 1.
+ */
+ float nextFloat();
+
+ /**
+ * Generates a {@code double} value between 0 and 1.
+ *
+ * @return the next random value between 0 and 1.
+ */
+ double nextDouble();
+}
http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/BaseProvider.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/rng/internal/BaseProvider.java b/src/main/java/org/apache/commons/math4/rng/internal/BaseProvider.java
new file mode 100644
index 0000000..e29d854
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/rng/internal/BaseProvider.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.rng.internal;
+
+import java.util.Arrays;
+import java.io.Serializable;
+import org.apache.commons.math4.exception.MathUnsupportedOperationException;
+import org.apache.commons.math4.exception.NotStrictlyPositiveException;
+import org.apache.commons.math4.rng.UniformRandomProvider;
+import org.apache.commons.math4.rng.RandomSource;
+
+/**
+ * Base class with default implementation for common methods.
+ */
+public abstract class BaseProvider
+ implements UniformRandomProvider,
+ StateSettable {
+ /** {@inheritDoc} */
+ @Override
+ public int nextInt(int n) throws IllegalArgumentException {
+ if (n > 0) {
+ 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;
+ }
+
+ throw new NotStrictlyPositiveException(n);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public long nextLong(long n) {
+ if (n > 0) {
+ long bits;
+ long val;
+ do {
+ bits = nextLong() >>> 1;
+ val = bits % n;
+ } while (bits - val + (n - 1) < 0);
+ return val;
+ }
+
+ throw new NotStrictlyPositiveException(n);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return getClass().getName();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public RandomSource.State getState() {
+ return new State(getStateInternal());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setState(RandomSource.State state) {
+ // Cast will intentionally fail if the argument is not one we created.
+ final State s = (State) state;
+ setStateInternal(s.getState());
+ }
+
+ /**
+ * Creates a snapshot of the RNG state.
+ *
+ * @return the internal state.
+ * @throws MathUnsupportedOperationException if not implemented.
+ */
+ protected byte[] getStateInternal() {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /**
+ * Resets the RNG to the given {@code state}.
+ *
+ * @param state State (previously obtained by a call to
+ * {@link #getStateInternal()}).
+ * @throws MathUnsupportedOperationException if not implemented.
+ */
+ protected void setStateInternal(byte[] state) {
+ throw new MathUnsupportedOperationException();
+ }
+
+ /**
+ * "Black-box" state.
+ * Its sole 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 to modify the data contained in
+ * instances of this class.
+ */
+ private static class State
+ implements RandomSource.State,
+ Serializable {
+ /** Serializable version identifier. */
+ private static final long serialVersionUID = 4720160226L;
+ /** Internal state. */
+ private byte[] state;
+
+ /**
+ * @param state Mapping of all the data which a subclass of
+ * {@link BaseProvider} needs in order to reset its internal
+ * state.
+ */
+ State(byte[] state) {
+ this.state = Arrays.copyOf(state, state.length);
+ }
+
+ /**
+ * @return the internal state.
+ */
+ byte[] getState() {
+ return Arrays.copyOf(state, state.length);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/ProviderBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/rng/internal/ProviderBuilder.java b/src/main/java/org/apache/commons/math4/rng/internal/ProviderBuilder.java
new file mode 100644
index 0000000..f38b679
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/rng/internal/ProviderBuilder.java
@@ -0,0 +1,346 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.rng.internal;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.commons.math4.exception.MathUnsupportedOperationException;
+import org.apache.commons.math4.exception.MathInternalError;
+import org.apache.commons.math4.rng.UniformRandomProvider;
+import org.apache.commons.math4.rng.internal.util.SeedFactory;
+import org.apache.commons.math4.rng.internal.util.NoOpConverter;
+import org.apache.commons.math4.rng.internal.util.Int2Long;
+import org.apache.commons.math4.rng.internal.util.Long2Int;
+import org.apache.commons.math4.rng.internal.util.Long2IntArray;
+import org.apache.commons.math4.rng.internal.util.Long2LongArray;
+import org.apache.commons.math4.rng.internal.util.IntArray2LongArray;
+import org.apache.commons.math4.rng.internal.util.LongArray2IntArray;
+import org.apache.commons.math4.rng.internal.util.LongArray2Long;
+import org.apache.commons.math4.rng.internal.util.IntArray2Int;
+import org.apache.commons.math4.rng.internal.util.SeedConverter;
+import org.apache.commons.math4.rng.internal.util.SeedConverterComposer;
+import org.apache.commons.math4.rng.internal.source32.JDKRandom;
+import org.apache.commons.math4.rng.internal.source32.Well512a;
+import org.apache.commons.math4.rng.internal.source32.Well1024a;
+import org.apache.commons.math4.rng.internal.source32.Well19937a;
+import org.apache.commons.math4.rng.internal.source32.Well19937c;
+import org.apache.commons.math4.rng.internal.source32.Well44497a;
+import org.apache.commons.math4.rng.internal.source32.Well44497b;
+import org.apache.commons.math4.rng.internal.source32.ISAACRandom;
+import org.apache.commons.math4.rng.internal.source32.MersenneTwister;
+import org.apache.commons.math4.rng.internal.source64.SplitMix64;
+import org.apache.commons.math4.rng.internal.source64.XorShift1024Star;
+import org.apache.commons.math4.rng.internal.source64.TwoCmres;
+import org.apache.commons.math4.rng.internal.source64.MersenneTwister64;
+
+/**
+ * RNG builder.
+ * <p>
+ * It uses reflection to find the factory method of the RNG implementation,
+ * and performs seed type conversions.
+ * </p>
+ */
+public class ProviderBuilder {
+ /** Length of the seed array (for random seed). */
+ private static final int RANDOM_SEED_ARRAY_SIZE = 128;
+ /** Seed converter. */
+ private static final Long2Int LONG_TO_INT = new Long2Int();
+ /** Seed converter. */
+ private static final Int2Long INT_TO_LONG = new Int2Long();
+ /** Seed converter. */
+ private static final Long2IntArray LONG_TO_INT_ARRAY = new Long2IntArray(RANDOM_SEED_ARRAY_SIZE);
+ /** Seed converter. */
+ private static final Long2LongArray LONG_TO_LONG_ARRAY = new Long2LongArray(RANDOM_SEED_ARRAY_SIZE);
+ /** Seed converter. */
+ private static final LongArray2Long LONG_ARRAY_TO_LONG = new LongArray2Long();
+ /** Seed converter. */
+ private static final IntArray2Int INT_ARRAY_TO_INT = new IntArray2Int();
+ /** Seed converter. */
+ private static final LongArray2IntArray LONG_ARRAY_TO_INT_ARRAY = new LongArray2IntArray();
+ /** Seed converter. */
+ private static final IntArray2LongArray INT_ARRAY_TO_LONG_ARRAY = new IntArray2LongArray();
+ /** Map to convert "Integer" seeds. */
+ private static final Map<Class<?>, SeedConverter<Integer,?>> CONV_INT = new HashMap<>();
+ /** Map to convert "int[]" seeds. */
+ private static final Map<Class<?>, SeedConverter<int[],?>> CONV_INT_ARRAY = new HashMap<>();
+ /** Map to convert "Long" seeds. */
+ private static final Map<Class<?>, SeedConverter<Long,?>> CONV_LONG = new HashMap<>();
+ /** Map to convert "long[]" seeds. */
+ private static final Map<Class<?>, SeedConverter<long[],?>> CONV_LONG_ARRAY = new HashMap<>();
+
+ static {
+ // Input seed type is "Long".
+ // Key is the implementation's "native" seed type.
+ CONV_LONG.put(Integer.class, LONG_TO_INT);
+ CONV_LONG.put(Long.class, new NoOpConverter<Long>());
+ CONV_LONG.put(int[].class, LONG_TO_INT_ARRAY);
+ CONV_LONG.put(long[].class, LONG_TO_LONG_ARRAY);
+
+ // Input seed type is "Integer".
+ // Key is the implementation's "native" seed type.
+ CONV_INT.put(Integer.class, new NoOpConverter<Integer>());
+ CONV_INT.put(Long.class, INT_TO_LONG);
+ CONV_INT.put(int[].class, new SeedConverterComposer<Integer,Long,int[]>(INT_TO_LONG, LONG_TO_INT_ARRAY));
+ CONV_INT.put(long[].class, new SeedConverterComposer<Integer,Long,long[]>(INT_TO_LONG, LONG_TO_LONG_ARRAY));
+
+ // Input seed type is "int[]".
+ // Key is the implementation's "native" seed type.
+ CONV_INT_ARRAY.put(Integer.class, INT_ARRAY_TO_INT);
+ CONV_INT_ARRAY.put(Long.class, new SeedConverterComposer<int[],Integer,Long>(INT_ARRAY_TO_INT, INT_TO_LONG));
+ CONV_INT_ARRAY.put(int[].class, new NoOpConverter<int[]>());
+ CONV_INT_ARRAY.put(long[].class, INT_ARRAY_TO_LONG_ARRAY);
+
+ // Input seed type is "long[]".
+ // Key is the implementation's "native" seed type.
+ CONV_LONG_ARRAY.put(Integer.class, new SeedConverterComposer<long[],Long,Integer>(LONG_ARRAY_TO_LONG, LONG_TO_INT));
+ CONV_LONG_ARRAY.put(Long.class, LONG_ARRAY_TO_LONG);
+ CONV_LONG_ARRAY.put(int[].class, LONG_ARRAY_TO_INT_ARRAY);
+ CONV_LONG_ARRAY.put(long[].class, new NoOpConverter<long[]>());
+ }
+
+ /**
+ * Class only contains static method.
+ */
+ private ProviderBuilder() {}
+
+ /**
+ * Creates a RNG instance.
+ *
+ * @param source RNG specification.
+ * @param seed Seed value. It can be {@code null} (in which case a
+ * random value will be used).
+ * @param args Additional arguments to the implementation's constructor.
+ * @return a new RNG instance.
+ * @throws MathUnsupportedOperationException if the seed type is
+ * invalid.
+ */
+ public static UniformRandomProvider create(RandomSourceInternal source,
+ Object seed,
+ Object[] args) {
+ // Convert seed to native type.
+ final Object nativeSeed = createSeed(source, seed);
+
+ // Build a single array with all the arguments to be passed
+ // (in the right order) to the constructor.
+ final List<Object> all = new ArrayList<>();
+ all.add(nativeSeed);
+ if (args != null) {
+ all.addAll(Arrays.asList(args));
+ }
+
+ // Instantiate.
+ return create(createConstructor(source), all.toArray());
+ }
+
+ /**
+ * Creates a native seed from any of the supported seed types.
+ *
+ * @param source Source.
+ * @param seed Input seed.
+ * @return the native seed.
+ * @throw MathUnsupportedOperationException if the {@code seed} type
+ * is invalid.
+ */
+ private static Object createSeed(RandomSourceInternal source,
+ Object seed) {
+ Object nativeSeed = null;
+
+ if (seed == null) {
+ // Create a random seed of the appropriate native type.
+
+ if (source.getSeed().equals(Integer.class)) {
+ nativeSeed = SeedFactory.createInt();
+ } else if (source.getSeed().equals(Long.class)) {
+ nativeSeed = SeedFactory.createLong();
+ } else if (source.getSeed().equals(int[].class)) {
+ nativeSeed = SeedFactory.createIntArray(RANDOM_SEED_ARRAY_SIZE);
+ } else if (source.getSeed().equals(long[].class)) {
+ nativeSeed = SeedFactory.createLongArray(RANDOM_SEED_ARRAY_SIZE);
+ }
+ } else {
+ // Convert to native type.
+
+ if (seed instanceof Integer) {
+ nativeSeed = CONV_INT.get(source.getSeed()).convert((Integer) seed);
+ } else if (seed instanceof Long) {
+ nativeSeed = CONV_LONG.get(source.getSeed()).convert((Long) seed);
+ } else if (seed instanceof int[]) {
+ nativeSeed = CONV_INT_ARRAY.get(source.getSeed()).convert((int[]) seed);
+ } else if (seed instanceof long[]) {
+ nativeSeed = CONV_LONG_ARRAY.get(source.getSeed()).convert((long[]) seed);
+ }
+
+ if (nativeSeed == null) {
+ // Since the input seed was not null, getting here means that
+ // no suitable converter is present in the maps.
+ throw new MathUnsupportedOperationException();
+ }
+
+ if (!source.isNativeSeed(nativeSeed)) {
+ // Conversion setup is wrong.
+ throw new MathInternalError();
+ }
+ }
+
+ return nativeSeed;
+ }
+
+ /**
+ * Creates a constructor.
+ *
+ * @param source RNG specification.
+ * @return a RNG constructor.
+ */
+ private static Constructor<?> createConstructor(RandomSourceInternal source) {
+ try {
+ return source.getRng().getConstructor(source.getArgs());
+ } catch (NoSuchMethodException e) {
+ // Info in "RandomSourceInternal" is inconsistent with the
+ // constructor of the implementation.
+ throw new MathInternalError(e);
+ }
+ }
+
+ /**
+ * Creates a RNG.
+ *
+ * @param rng RNG specification.
+ * @param args Arguments to the implementation's constructor.
+ * @return a new RNG instance.
+ */
+ private static UniformRandomProvider create(Constructor<?> rng,
+ Object[] args) {
+ try {
+ return (UniformRandomProvider) rng.newInstance(args);
+ } catch (InvocationTargetException |
+ InstantiationException |
+ IllegalArgumentException |
+ IllegalAccessException e) {
+ throw new MathInternalError(e);
+ }
+ }
+
+ /**
+ * Identifiers of the generators.
+ */
+ public enum RandomSourceInternal {
+ /** Source of randomness is {@link JDKRandom}. */
+ JDK(JDKRandom.class,
+ Long.class),
+ /** Source of randomness is {@link Well512a}. */
+ WELL_512_A(Well512a.class,
+ int[].class),
+ /** Source of randomness is {@link Well1024a}. */
+ WELL_1024_A(Well1024a.class,
+ int[].class),
+ /** Source of randomness is {@link Well19937a}. */
+ WELL_19937_A(Well19937a.class,
+ int[].class),
+ /** Source of randomness is {@link Well19937c}. */
+ WELL_19937_C(Well19937c.class,
+ int[].class),
+ /** Source of randomness is {@link Well44497a}. */
+ WELL_44497_A(Well44497a.class,
+ int[].class),
+ /** Source of randomness is {@link Well44497b}. */
+ WELL_44497_B(Well44497b.class,
+ int[].class),
+ /** Source of randomness is {@link MersenneTwister}. */
+ MT(MersenneTwister.class,
+ int[].class),
+ /** Source of randomness is {@link ISAACRandom}. */
+ ISAAC(ISAACRandom.class,
+ int[].class),
+ /** Source of randomness is {@link SplitMix64}. */
+ SPLIT_MIX_64(SplitMix64.class,
+ Long.class),
+ /** Source of randomness is {@link XorShift1024Star}. */
+ XOR_SHIFT_1024_S(XorShift1024Star.class,
+ long[].class),
+ /** Source of randomness is {@link TwoCmres}. */
+ TWO_CMRES(TwoCmres.class,
+ Integer.class),
+ /**
+ * Source of randomness is {@link TwoCmres} with explicit selection
+ * of the two subcycle generators.
+ */
+ TWO_CMRES_SELECT(TwoCmres.class,
+ Integer.class,
+ Integer.TYPE,
+ Integer.TYPE),
+ /** Source of randomness is {@link MersenneTwister64}. */
+ MT_64(MersenneTwister64.class,
+ long[].class);
+
+ /** Source type. */
+ private final Class<? extends UniformRandomProvider> rng;
+ /** Data needed to build the generator. */
+ private final Class<?>[] args;
+
+ /**
+ * @param rng Source type.
+ * @param args Data needed to create a generator instance.
+ * The first element must be the native seed type.
+ */
+ RandomSourceInternal(Class<? extends UniformRandomProvider> rng,
+ Class<?> ... args) {
+ this.rng = rng;
+ this.args = Arrays.copyOf(args, args.length);
+ }
+
+ /**
+ * @return the source type.
+ */
+ public Class<?> getRng() {
+ return rng;
+ }
+
+ /**
+ * @return the seed type.
+ */
+ Class<?> getSeed() {
+ return args[0];
+ }
+
+ /**
+ * @return the data needed to build the generator.
+ */
+ Class<?>[] getArgs() {
+ return args;
+ }
+
+ /**
+ * Checks whether the type of given {@code seed} is the native type
+ * of the implementation.
+ *
+ * @param <SEED> Seed type.
+ *
+ * @param seed Seed value.
+ * @return {@code true} if the seed can be passed to the builder
+ * for this RNG type.
+ */
+ public <SEED> boolean isNativeSeed(SEED seed) {
+ return getSeed().equals(seed.getClass());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/StateSettable.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/rng/internal/StateSettable.java b/src/main/java/org/apache/commons/math4/rng/internal/StateSettable.java
new file mode 100644
index 0000000..6c7e7a5
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/rng/internal/StateSettable.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.rng.internal;
+
+import org.apache.commons.math4.rng.RandomSource;
+
+/**
+ * Indicates that the state of the instance can be saved and restored.
+ *
+ * @since 4.0
+ */
+public interface StateSettable {
+ /**
+ * Sets the instance's state.
+ *
+ * @param state State. The given argument must have been retrieved
+ * by a call to {@link #getState()}.
+ *
+ * @throws org.apache.commons.math4.exception.MathUnsupportedOperationException
+ * if not implemented.
+ */
+ void setState(RandomSource.State state);
+
+ /**
+ * Gets the instance's state.
+ *
+ * @return the current state. The given argument can then be passed
+ * to {@link #setState(RandomSource.State)} in order to recover the
+ * current state.
+ *
+ * @throws org.apache.commons.math4.exception.MathUnsupportedOperationException
+ * if not implemented.
+ */
+ RandomSource.State getState();
+}
http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/package-info.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/rng/internal/package-info.java b/src/main/java/org/apache/commons/math4/rng/internal/package-info.java
new file mode 100644
index 0000000..47ad828
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/rng/internal/package-info.java
@@ -0,0 +1,51 @@
+/*
+ * 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.math4.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.math4.rng.internal.source32.RandomIntSource int}
+ * values are defined in the
+ * {@link org.apache.commons.math4.rng.internal.source32 source32} package.
+ * <br>
+ * Implementations that produce
+ * {@link org.apache.commons.math4.rng.internal.source64.RandomLongSource long}
+ * values are defined in the
+ * {@link org.apache.commons.math4.rng.internal.source64 source64} package.
+ * </p>
+ *
+ * <p>
+ * Each implementation must have an identifier in
+ * {@link org.apache.commons.math4.rng.internal.ProviderBuilder.RandomSourceInternal}
+ * which must be referred to from the {@link org.apache.commons.math4.rng.RandomSource public API}.
+ * </p>
+ */
+
+package org.apache.commons.math4.rng.internal;
http://git-wip-us.apache.org/repos/asf/commons-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/AbstractWell.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/AbstractWell.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/AbstractWell.java
new file mode 100644
index 0000000..c9737db
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/AbstractWell.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.rng.internal.source32;
+
+import java.util.Arrays;
+import org.apache.commons.math4.exception.InsufficientDataException;
+import org.apache.commons.math4.rng.internal.util.NumberFactory;
+
+/**
+ * This 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) {
+ if (s.length != (v.length + 1) * 4) {
+ throw new InsufficientDataException();
+ }
+
+ 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-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/ISAACRandom.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/ISAACRandom.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/ISAACRandom.java
new file mode 100644
index 0000000..c7dd73a
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/ISAACRandom.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.rng.internal.source32;
+
+import java.util.Arrays;
+import org.apache.commons.math4.exception.InsufficientDataException;
+import org.apache.commons.math4.rng.internal.util.NumberFactory;
+
+/**
+ * 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) {
+ if (s.length != (2 * SIZE + 4) * 4) {
+ throw new InsufficientDataException();
+ }
+
+ 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-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/IntProvider.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/IntProvider.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/IntProvider.java
new file mode 100644
index 0000000..bae33fc
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/rng/internal/source32/IntProvider.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.rng.internal.source32;
+
+import org.apache.commons.math4.exception.OutOfRangeException;
+import org.apache.commons.math4.rng.internal.util.NumberFactory;
+import org.apache.commons.math4.rng.internal.BaseProvider;
+
+/**
+ * Base class for all implementations that provide 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) {
+ if (start < 0 ||
+ start >= bytes.length) {
+ throw new OutOfRangeException(start, 0, bytes.length);
+ }
+ if (len < 0 ||
+ len > bytes.length - start) {
+ throw new OutOfRangeException(len, 0, bytes.length - start);
+ }
+
+ nextBytesFill(this, bytes, start, len);
+ }
+
+ /**
+ * Generates random bytes and places them into a user-supplied array.
+ *
+ * <p>
+ * The array is filled with bytes extracted from random {@code 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-math/blob/6ddf4769/src/main/java/org/apache/commons/math4/rng/internal/source32/JDKRandom.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/rng/internal/source32/JDKRandom.java b/src/main/java/org/apache/commons/math4/rng/internal/source32/JDKRandom.java
new file mode 100644
index 0000000..e393c12
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/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.math4.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);
+ }
+ }
+}