/*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If
* not, see <http://www.gnu.org/licenses/>.
*/
package silentium.commons.utils;
import org.apache.commons.math3.random.MersenneTwister;
import org.apache.commons.math3.random.RandomGenerator;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author Forsaiken
* @author Tatanka
*/
public final class Rnd {
// TODO: Config.
private static final RandomGenerator[] RANDOM = new RandomGenerator[]{new MersenneTwister(),
new MersenneTwister(), new MersenneTwister(), new MersenneTwister(), new MersenneTwister()};
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final long MASK = (1L << 48) - 1;
private static final AtomicLong SEED_UNIQUIFIER = new AtomicLong(8682522807148012L);
private static final ThreadLocal<Long> SEED_LOCAL = new ThreadLocal<Long>() {
@Override
public Long initialValue() {
return generateSeed(SEED_UNIQUIFIER.getAndIncrement() + System.nanoTime());
}
};
// TODO: It can be not necessary here such heavy calculations.
private static long generateSeed(final long initialSeed) {
return (initialSeed ^ MULTIPLIER) & MASK;
}
private static AtomicInteger POOL_RANDOMIZER = new AtomicInteger(0);
private static RandomGenerator getRandom() {
final RandomGenerator random = RANDOM[POOL_RANDOMIZER.getAndIncrement() % RANDOM.length];
random.setSeed(SEED_LOCAL.get());
return random;
}
/**
* Get a random double number from 0 to 1
*
* @return A random double number from 0 to 1
* @see silentium.commons.utils.Rnd#nextDouble()
*/
public static double get() {
return getRandom().nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
*
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(final int n) {
return getRandom().nextInt(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
*
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(final int min, final int max) {
return min + getRandom().nextInt(max - min + 1);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
*
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(final long min, final long max) {
return min + (long) (getRandom().nextDouble() * (max - min + 1));
}
/**
* Get a random boolean state (true or false)
*
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public static boolean nextBoolean() {
return getRandom().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
*
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public static void nextBytes(final byte... array) {
getRandom().nextBytes(array);
}
/**
* Get a random double number from 0 to 1
*
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public static double nextDouble() {
return getRandom().nextDouble();
}
/**
* Get a random float number from 0 to 1
*
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public static float nextFloat() {
return getRandom().nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
*
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian() {
return getRandom().nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
*
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public static int nextInt() {
return getRandom().nextInt();
}
/**
* @param n
* @return
* @see silentium.commons.utils.Rnd#get(int n)
*/
public static int nextInt(final int n) {
return get(n);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
*
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public static long nextLong() {
return getRandom().nextLong();
}
}