MATH-1610: Functionality moved to "Commons RNG" (cf. RNG-145).

This commit is contained in:
Gilles Sadowski 2021-06-14 22:26:22 +02:00
parent ee73d636de
commit b509678e95
2 changed files with 0 additions and 200 deletions

View File

@ -97,89 +97,5 @@ public class RandomUtils {
return lower + rng.nextLong(max);
}
}
/**
* Generates a uniformly distributed random value from the open interval
* {@code (lower, upper)} (i.e., endpoints excluded).
* <p>
* <strong>Definition</strong>:
* <a href="http://www.itl.nist.gov/div898/handbook/eda/section3/eda3662.htm">
* Uniform Distribution</a> {@code lower} and {@code upper - lower} are the
* <a href = "http://www.itl.nist.gov/div898/handbook/eda/section3/eda364.htm">
* location and scale parameters</a>, respectively.</p>
* <p>
* <strong>Algorithm Description</strong>: scales the output of
* Random.nextDouble(), but rejects 0 values (i.e., will generate another
* random double if Random.nextDouble() returns 0). This is necessary to
* provide a symmetric output interval (both endpoints excluded).
* </p>
*
* @param lower Lower bound of the support (excluded).
* @param upper Upper bound of the support (excluded).
* @return a uniformly distributed random value between lower and upper
* (both excluded).
* @throws NumberIsTooLargeException if {@code lower >= upper}.
* @throws NotFiniteNumberException if one of the bounds is infinite.
* @throws NotANumberException if one of the bounds is NaN.
*/
public double nextUniform(double lower, double upper) {
return nextUniform(lower, upper, false);
}
/**
* Generates a uniformly distributed random value from the interval
* {@code (lower, upper)} or the interval {@code [lower, upper)}. The lower
* bound is thus optionally included, while the upper bound is always
* excluded.
* <p>
* <strong>Definition</strong>:
* <a href="http://www.itl.nist.gov/div898/handbook/eda/section3/eda3662.htm">
* Uniform Distribution</a> {@code lower} and {@code upper - lower} are the
* <a href = "http://www.itl.nist.gov/div898/handbook/eda/section3/eda364.htm">
* location and scale parameters</a>, respectively.</p>
* <p>
* <strong>Algorithm Description</strong>: if the lower bound is excluded,
* scales the output of "nextDouble()", but rejects 0 values (i.e. it
* will generate another random double if "nextDouble()" returns 0).
* This is necessary to provide a symmetric output interval (both
* endpoints excluded).
* </p>
*
* @param lower Lower bound of the support.
* @param upper Exclusive upper bound of the support.
* @param lowerInclusive {@code true} if the lower bound is inclusive.
* @return a uniformly distributed random value in the {@code (lower, upper)}
* interval, if {@code lowerInclusive} is {@code false}, or in the
* {@code [lower, upper)} interval, if {@code lowerInclusive} is
* {@code true}.
* @throws NumberIsTooLargeException if {@code lower >= upper}.
* @throws NotFiniteNumberException if one of the bounds is infinite.
* @throws NotANumberException if one of the bounds is NaN.
*/
public double nextUniform(double lower,
double upper,
boolean lowerInclusive) {
if (lower >= upper) {
throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
lower, upper, false);
}
if (Double.isInfinite(lower)) {
throw new NotFiniteNumberException(LocalizedFormats.INFINITE_BOUND, lower);
}
if (Double.isInfinite(upper)) {
throw new NotFiniteNumberException(LocalizedFormats.INFINITE_BOUND, upper);
}
if (Double.isNaN(lower) || Double.isNaN(upper)) {
throw new NotANumberException();
}
// Ensure nextDouble() isn't 0.0
double u = rng.nextDouble();
while (!lowerInclusive && u <= 0.0) {
u = rng.nextDouble();
}
return u * upper + (1.0 - u) * lower;
}
}
}

View File

@ -51,17 +51,6 @@ public abstract class RandomUtilsDataGeneratorAbstractTest {
Assert.assertFalse(x == y);
}
@Test
public void testNextUniformExtremeValues() {
double x = randomData.nextUniform(-Double.MAX_VALUE, Double.MAX_VALUE);
double y = randomData.nextUniform(-Double.MAX_VALUE, Double.MAX_VALUE);
Assert.assertFalse(x == y);
Assert.assertFalse(Double.isNaN(x));
Assert.assertFalse(Double.isNaN(y));
Assert.assertFalse(Double.isInfinite(x));
Assert.assertFalse(Double.isInfinite(y));
}
@Test
public void testNextLongIAE() {
try {
@ -136,109 +125,4 @@ public abstract class RandomUtilsDataGeneratorAbstractTest {
(((double) upper) - ((double) lower));
Assert.assertTrue(ratio > 0.99999);
}
@Test
public void testNextUniformIAE() {
try {
randomData.nextUniform(4, 3);
Assert.fail("MathIllegalArgumentException expected");
} catch (MathIllegalArgumentException ex) {
// ignored
}
try {
randomData.nextUniform(0, Double.POSITIVE_INFINITY);
Assert.fail("MathIllegalArgumentException expected");
} catch (MathIllegalArgumentException ex) {
// ignored
}
try {
randomData.nextUniform(Double.NEGATIVE_INFINITY, 0);
Assert.fail("MathIllegalArgumentException expected");
} catch (MathIllegalArgumentException ex) {
// ignored
}
try {
randomData.nextUniform(0, Double.NaN);
Assert.fail("MathIllegalArgumentException expected");
} catch (MathIllegalArgumentException ex) {
// ignored
}
try {
randomData.nextUniform(Double.NaN, 0);
Assert.fail("MathIllegalArgumentException expected");
} catch (MathIllegalArgumentException ex) {
// ignored
}
}
@Test
public void testNextUniformPositiveBounds() {
for (int i = 0; i < 5; i++) {
checkNextUniform(0, 10);
}
}
@Test
public void testNextUniformNegativeToPositiveBounds() {
for (int i = 0; i < 5; i++) {
checkNextUniform(-3, 5);
}
}
@Test
public void testNextUniformNegativeBounds() {
for (int i = 0; i < 5; i++) {
checkNextUniform(-7, -3);
}
}
@Test
public void testNextUniformMaximalInterval() {
for (int i = 0; i < 5; i++) {
checkNextUniform(-Double.MAX_VALUE, Double.MAX_VALUE);
}
}
private void checkNextUniform(double min, double max) {
// Set up bin bounds - min, binBound[0], ..., binBound[binCount-2], max
final int binCount = 5;
final double binSize = max / binCount - min/binCount; // Prevent overflow in extreme value case
final double[] binBounds = new double[binCount - 1];
binBounds[0] = min + binSize;
for (int i = 1; i < binCount - 1; i++) {
binBounds[i] = binBounds[i - 1] + binSize; // + instead of * to avoid overflow in extreme case
}
final Frequency<Integer> freq = new Frequency<>();
for (int i = 0; i < smallSampleSize; i++) {
final double value = randomData.nextUniform(min, max);
Assert.assertTrue("nextUniform range", (value > min) && (value < max));
// Find bin
int j = 0;
while (j < binCount - 1 && value > binBounds[j]) {
j++;
}
freq.addValue(j);
}
final long[] observed = new long[binCount];
for (int i = 0; i < binCount; i++) {
observed[i] = freq.getCount(i);
}
final double[] expected = new double[binCount];
for (int i = 0; i < binCount; i++) {
expected[i] = 1d / binCount;
}
TestUtils.assertChiSquareAccept(expected, observed, 0.01);
}
/** test exclusive endpoints of nextUniform **/
@Test
public void testNextUniformExclusiveEndpoints() {
for (int i = 0; i < 1000; i++) {
double u = randomData.nextUniform(0.99, 1);
Assert.assertTrue(u > 0.99 && u < 1);
}
}
}