/*
* Encog(tm) Core v3.4 - Java Version
* http://www.heatonresearch.com/encog/
* https://github.com/encog/encog-java-core
* Copyright 2008-2016 Heaton Research, Inc.
*
* Licensed 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.
*
* For more information on Heaton Research copyrights, licenses
* and trademarks visit:
* http://www.heatonresearch.com/copyright
*/
package org.encog.mathutil.randomize.generate;
/**
* A Linear Congruential random number generator. A Linear Congruential Generator (LCG) yields a sequence of
* randomized numbers calculated with a linear equation. The method represents one of the oldest and best-known
* pseudorandom number generator algorithms. Most programming languages use this technique.
*
* http://en.wikipedia.org/wiki/Linear_congruential_generator/
* Donald Knuth, The Art of Computer Programming, Volume 3, Section 3.2.1
*/
public class LinearCongruentialRandom extends AbstractBoxMuller {
/**
* First part of default mod.
*/
public static final long DEFAULT_MOD1 = 2L;
/**
* Second part of default mod.
*/
public static final long DEFAULT_MOD2 = 32L;
/**
* Default mult.
*/
public static final long DEFAULT_MULT = 1103515245L;
/**
* Default inc.
*/
public static final long DEFAULT_INC = 12345L;
/**
* The modulus.
*/
private final long modulus;
/**
* The multiplier.
*/
private final long multiplier;
/**
* The amount to increment.
*/
private final long increment;
/**
* The current seed, set to an initial value and always holds the value of
* the last random number generated.
*/
private long seed;
/**
* The maximum rand number that the standard GCC based LCG will generate.
*/
public static final long MAX_RAND = 4294967295L;
/**
* Construct the default LCG. You need only specify a seed.
*
* @param theSeed The seed to use.
*/
public LinearCongruentialRandom(final long theSeed) {
this((long) Math.pow(DEFAULT_MOD1, DEFAULT_MOD2),
DEFAULT_MULT, DEFAULT_INC, theSeed);
}
/**
* Constructor to use a seed equal to system time.
*/
public LinearCongruentialRandom() {
this(System.currentTimeMillis());
}
/**
* Create a LCG with the specified modulus, multiplier and increment. Unless
* you REALLY KNOW WHAT YOU ARE DOING, just use the constructor that just
* takes a seed. It will set these values to the same as set by the GCC C
* compiler. Setting these values wrong can create fairly useless random
* numbers.
*
* @param theModulus The modulus for the LCG algorithm.
* @param theMultiplier The multiplier for the LCG algorithm.
* @param theIncrement The increment for the LCG algorithm.
* @param theSeed The seed for the LCG algorithm. Using the same seed will give
* the same random number sequence each time, whether in Java or
* DotNet.
*/
public LinearCongruentialRandom(final long theModulus,
final long theMultiplier, final long theIncrement,
final long theSeed) {
super();
this.modulus = theModulus;
this.multiplier = theMultiplier;
this.increment = theIncrement;
this.seed = theSeed % MAX_RAND;
}
/**
* @return The LCG increment.
*/
public final long getIncrement() {
return this.increment;
}
/**
* @return The LCG modulus.
*/
public final long getModulus() {
return this.modulus;
}
/**
* @return The LCG multiplier.
*/
public final long getMultiplier() {
return this.multiplier;
}
/**
* @return The current seed. Set to a constant to start, thereafter the
* previously generated random number.
*/
public final long getSeed() {
return this.seed;
}
/**
* @return The next random number as a double between 0 and 1.
*/
@Override
public final double nextDouble() {
return (double) nextLong() / LinearCongruentialRandom.MAX_RAND;
}
/**
* @return The next random number as a long between 0 and MAX_RAND.
*/
@Override
public final long nextLong() {
this.seed = (this.multiplier * this.seed + this.increment)
% this.modulus;
return this.seed;
}
/**
* {@inheritDoc}
*/
@Override
public boolean nextBoolean() {
return nextDouble() > 0.5;
}
/**
* {@inheritDoc}
*/
@Override
public float nextFloat() {
return (float) nextDouble();
}
/**
* {@inheritDoc}
*/
@Override
public int nextInt() {
return (int) nextLong();
}
}