Randomizer.java
/*
* Copyright (C) 2012 Alberto Irurueta Carro (alberto@irurueta.com)
*
* 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.
*/
package com.irurueta.statistics;
import java.security.SecureRandom;
import java.util.Random;
/**
* Parent class of all Randomizers. Specific subclasses exist for different
* distribution types (currently only uniform and gaussian distributions are
* implemented).
* This class provides static methods to ease the instantiation of a Randomizer.
* For instance, a UniformRandomizer can be created like this:
* <pre>
* {@code
* Randomizer.create(RandomizerType.UNIFORM_RANDOMIZER);
* }
* </pre>
* whereas a GaussianRandomizer can be created like this:
* <pre>
* {@code
* Randomizer.create(RandomizerType.GAUSSIAN_RANDOMIZER);
* }
* </pre>
*/
public abstract class Randomizer {
/**
* Indicates that by default non-secured random instance is used if none
* is provided.
*/
public static final boolean USE_SECURE_RANDOM_BY_DEFAULT = false;
/**
* Indicates default randomizer type if non is provided. By default, uniform
* randomizers are created.
*/
public static final RandomizerType DEFAULT_RANDOMIZER_TYPE = RandomizerType.UNIFORM_RANDOMIZER;
/**
* Instance in charge of generating pseudo-random values. Secure instances
* can be used if the generated values need to be ensured to be "more"
* random at the expense of higher computational cost.
*/
private Random internalRandom;
/**
* Constructor.
* Uses default {@link Random} implementation.
*/
protected Randomizer() {
this(new Random());
}
/**
* Constructor.
*
* @param internalRandom Instance in charge of generating pseudo-random
* values.
* @throws NullPointerException if provided value is null.
*/
protected Randomizer(final Random internalRandom) {
if (internalRandom == null) {
throw new NullPointerException();
}
this.internalRandom = internalRandom;
}
/**
* Returns internal instance in charge of generating pseudo-random values.
*
* @return instance in charge of generating pseudo-random values.
*/
public Random getInternalRandom() {
return internalRandom;
}
/**
* Sets internal instance in charge of generating pseudo-random values.
*
* @param internalRandom Instance in charge of generating pseudo-random
* values.
* @throws NullPointerException if provided value is null.
*/
public void setInternalRandom(final Random internalRandom) {
if (internalRandom == null) {
throw new NullPointerException();
}
this.internalRandom = internalRandom;
}
/**
* Sets the seed for the internal randomizer.
* A seed determines the sequence of pseudo-random numbers to be generated.
* Whenever the same seed is used on different executions, the generated
* sequence will be the same.
* To alleviate this issue and allow the generation of "more" random values
* the system clock can be used as the seed.
* Example:
* <pre>
* {@code
* Randomizer randomizer = Randomizer.create();
* randomizer.setSeed(System.currentTimeMillis());
* }
* </pre>
* Notice that using the clock as seed is not a secure solution to generate
* random values. If a secure solution is required (i.e. for encryption
* purposes, then a SecureRandom instance must be provided as the internal
* random instance)
*
* @param seed Value to be used as seed
*/
public void setSeed(final long seed) {
internalRandom.setSeed(seed);
}
/**
* Returns next random boolean value following a given distribution
* depending on the randomizer type.
*
* @return Next random boolean value
*/
public abstract boolean nextBoolean();
/**
* Fills provided array with random booleans.
*
* @param array Array to be filled.
*/
public void fill(final boolean[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = nextBoolean();
}
}
/**
* Returns array of booleans.
*
* @param length Length of array to be returned.
* @return Array of uniform booleans.
* @throws IllegalArgumentException if provided value is zero or negative.
*/
public boolean[] nextBooleans(final int length) {
if (length <= 0) {
throw new IllegalArgumentException();
}
final boolean[] array = new boolean[length];
fill(array);
return array;
}
/**
* Returns next random integer value following a given distribution
* depending on the randomizer type.
*
* @return Next random integer value.
*/
public abstract int nextInt();
/**
* Fills provided array with random integer values.
*
* @param array Array to be filled.
*/
public void fill(final int[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = nextInt();
}
}
/**
* Returns array of random integers.
*
* @param length Length of array to be returned.
* @return Array of random integers.
* @throws IllegalArgumentException if provided value is zero or negative.
*/
public int[] nextInts(final int length) {
if (length <= 0) {
throw new IllegalArgumentException();
}
final int[] array = new int[length];
fill(array);
return array;
}
/**
* Returns next random long value following a given distribution depending
* on the randomizer type.
*
* @return Next random integer value.
*/
public abstract long nextLong();
/**
* Fills provided array with random long values.
*
* @param array Array to be filled.
*/
public void fill(final long[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = nextLong();
}
}
/**
* Returns array of random long values.
*
* @param length Length of array to be returned.
* @return Array of random long values.
* @throws IllegalArgumentException if provided value is zero or negative.
*/
public long[] nextLongs(final int length) {
if (length <= 0) {
throw new IllegalArgumentException();
}
final long[] array = new long[length];
fill(array);
return array;
}
/**
* Returns next random floating-point value following a given distribution
* depending on the randomizer type.
*
* @return Next random integer value.
*/
public abstract float nextFloat();
/**
* Fills provided array with random floating point values.
*
* @param array Array to be filled.
*/
public void fill(final float[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = nextFloat();
}
}
/**
* Returns array of floating point values.
*
* @param length Length of array to be returned.
* @return Array of random float values.
* @throws IllegalArgumentException if provided value is zero or negative.
*/
public float[] nextFloats(final int length) {
if (length <= 0) {
throw new IllegalArgumentException();
}
final float[] array = new float[length];
fill(array);
return array;
}
/**
* Returns next random double precision floating-point value following a
* given distribution depending on the randomizer type.
*
* @return Next random double precision floating-point value.
*/
public abstract double nextDouble();
/**
* Fills provided array with random double precision floating point values.
*
* @param array Array to be filled.
*/
public void fill(final double[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = nextDouble();
}
}
/**
* Returns array of double precision floating point values.
*
* @param length Length of array to be returned.
* @return Array of random double values.
* @throws IllegalArgumentException if provided value is zero or negative.
*/
public double[] nextDoubles(final int length) {
if (length <= 0) {
throw new IllegalArgumentException();
}
final double[] array = new double[length];
fill(array);
return array;
}
/**
* Returns the randomizer type of this instance.
*
* @return Randomizer type.
*/
public abstract RandomizerType getType();
/**
* Creates a new Randomizer instance using DEFAULT_RANDOMIZER_TYPE and
* USE_SECURE_RANDOM_By_DEFAULT to determine what type of random
* distribution is to be used and whether the random generator must be
* secure or not.
*
* @return A Randomizer instance using default randomizer type and secure
* mode.
*/
public static Randomizer create() {
return create(DEFAULT_RANDOMIZER_TYPE);
}
/**
* Creates a new Randomizer instance using DEFAULT_RANDOMIZER_TYPE. The
* instantiated Randomizer will generate secure values depending on provided
* parameter. When secure random generator is requested, generated values
* tend to be more "random" at the expense of larger computational cost.
* Secure mode should only be used on specific applications, such as
* cryptography, and hence the name of the parameter.
*
* @param useSecureRandom Parameter indicating whether generated values will
* be used for security purposes such as cryptography.
* @return A Randomizer instance using provided secure mode.
*/
public static Randomizer create(final boolean useSecureRandom) {
return create(DEFAULT_RANDOMIZER_TYPE, useSecureRandom);
}
/**
* Creates a new Randomizer instance using provided internal randomizer
* instance.
*
* @param internalRandomizer Internal instance to be used for generation of
* pseudo-random values.
* @return A Randomizer instance using provided internal randomizer.
* @throws NullPointerException Exception thrown if provided internal
* randomizer is null.
*/
public static Randomizer create(final Random internalRandomizer) {
return create(DEFAULT_RANDOMIZER_TYPE, internalRandomizer);
}
/**
* Creates a new Randomizer instance using provided randomizer type and
* the default secure mode specified by USE_SECURE_RANDOM_BY_DEFAULT.
*
* @param type Randomizer type to be used when creating an instance.
* @return A Randomizer instance using provided randomizer type.
*/
public static Randomizer create(final RandomizerType type) {
return create(type, USE_SECURE_RANDOM_BY_DEFAULT);
}
/**
* Creates a new Randomizer instance using provided randomizer type and
* provided secure mode.
*
* @param type Randomizer type to be used when creating an instance.
* @param useSecureRandom Boolean indicating whether generated values will
* be secure for specific purposes such as cryptography. Secure mode
* generates more "random" values at the expense of higher computational
* cost.
* @return A Randomizer instance using provided randomizer type and secure
* mode.
*/
public static Randomizer create(final RandomizerType type, final boolean useSecureRandom) {
if (useSecureRandom) {
return create(type, new SecureRandom());
} else {
return create(type, new Random());
}
}
/**
* Creates a new Randomizer instance using provided randomizer type and
* internal randomizer.
*
* @param type Randomizer type to be used when creating an instance.
* @param internalRandom Internal random instance to be used to generate
* pseudo-random values.
* @return A Randomizer instance using provided randomizer type and internal
* random instance.
* @throws NullPointerException Exception thrown if internal random is null.
*/
public static Randomizer create(final RandomizerType type, final Random internalRandom) {
if (internalRandom == null) {
throw new NullPointerException();
}
if (type == RandomizerType.GAUSSIAN_RANDOMIZER) {
return new GaussianRandomizer(internalRandom);
} else {
return new UniformRandomizer(internalRandom);
}
}
}