diff --git a/src/main/java/org/apache/commons/math/random/RandomData.java b/src/main/java/org/apache/commons/math/random/RandomData.java index 976b97804..f39885170 100644 --- a/src/main/java/org/apache/commons/math/random/RandomData.java +++ b/src/main/java/org/apache/commons/math/random/RandomData.java @@ -18,188 +18,161 @@ package org.apache.commons.math.random; import java.util.Collection; +import org.apache.commons.math.exception.NotStrictlyPositiveException; +import org.apache.commons.math.exception.NumberIsTooLargeException; + /** * Random data generation utilities. * @version $Id$ */ public interface RandomData { /** - * Generates a random string of hex characters of length - * len. + * Generates a random string of hex characters of length {@code len}. *

* The generated string will be random, but not cryptographically * secure. To generate cryptographically secure strings, use - * nextSecureHexString

- *

- * Preconditions:

+ * {@link #nextSecureHexString(int)}. + *

* * @param len the length of the string to be generated - * @return random string of hex characters of length len + * @return a random string of hex characters of length {@code len} + * @throws NotStrictlyPositiveException if {@code len <= 0} */ - String nextHexString(int len); + String nextHexString(int len) throws NotStrictlyPositiveException; /** - * Generates a uniformly distributed random integer between - * lower and upper (endpoints included). + * Generates a uniformly distributed random integer between {@code lower} + * and {@code upper} (endpoints included). *

* The generated integer will be random, but not cryptographically secure. * To generate cryptographically secure integer sequences, use - * nextSecureInt.

- *

- * Preconditions:

+ * {@link #nextSecureInt(int, int)}. + *

* * @param lower lower bound for generated integer * @param upper upper bound for generated integer - * @return a random integer greater than or equal to lower - * and less than or equal to upper. + * @return a random integer greater than or equal to {@code lower} + * and less than or equal to {@code upper} + * @throws NumberIsTooLargeException if {@code lower >= upper} */ - int nextInt(int lower, int upper); + int nextInt(int lower, int upper) throws NumberIsTooLargeException; /** * Generates a uniformly distributed random long integer between - * lower and upper (endpoints included). + * {@code lower} and {@code upper} (endpoints included). *

* The generated long integer values will be random, but not - * cryptographically secure. - * To generate cryptographically secure sequences of longs, use - * nextSecureLong

- *

- * Preconditions:

+ * cryptographically secure. To generate cryptographically secure sequences + * of longs, use {@link #nextSecureLong(long, long)}. + *

* - * @param lower lower bound for generated integer - * @param upper upper bound for generated integer - * @return a random integer greater than or equal to lower - * and less than or equal to upper. + * @param lower lower bound for generated long integer + * @param upper upper bound for generated long integer + * @return a random long integer greater than or equal to {@code lower} and + * less than or equal to {@code upper} + * @throws NumberIsTooLargeException if {@code lower >= upper}. */ - long nextLong(long lower, long upper); + long nextLong(long lower, long upper) throws NumberIsTooLargeException; /** * Generates a random string of hex characters from a secure random * sequence. *

- * If cryptographic security is not required, - * use nextHexString().

- *

- * Preconditions:

- * @param len length of return string - * @return the random hex string + * If cryptographic security is not required, use + * {@link #nextHexString(int)}. + *

+ * + * @param len the length of the string to be generated + * @return a random string of hex characters of length {@code len} + * @throws NotStrictlyPositiveException if {@code len <= 0} */ - String nextSecureHexString(int len); + String nextSecureHexString(int len) throws NotStrictlyPositiveException; /** - * Generates a uniformly distributed random integer between - * lower and upper (endpoints included) - * from a secure random sequence. + * Generates a uniformly distributed random integer between {@code lower} + * and {@code upper} (endpoints included) from a secure random sequence. *

* Sequences of integers generated using this method will be * cryptographically secure. If cryptographic security is not required, - * nextInt should be used instead of this method.

+ * {@link #nextInt(int, int)} should be used instead of this method.

*

* Definition: * * Secure Random Sequence

- *

- * Preconditions:

* * @param lower lower bound for generated integer * @param upper upper bound for generated integer - * @return a random integer greater than or equal to lower - * and less than or equal to upper. + * @return a random integer greater than or equal to {@code lower} and less + * than or equal to {@code upper}. + * @throws NumberIsTooLargeException if {@code lower >= upper}. */ - int nextSecureInt(int lower, int upper); + int nextSecureInt(int lower, int upper) throws NumberIsTooLargeException; /** - * Generates a random long integer between lower - * and upper (endpoints included). + * Generates a uniformly distributed random long integer between + * {@code lower} and {@code upper} (endpoints included) from a secure random + * sequence. *

* Sequences of long values generated using this method will be * cryptographically secure. If cryptographic security is not required, - * nextLong should be used instead of this method.

+ * {@link #nextLong(long, long)} should be used instead of this method.

*

* Definition: * * Secure Random Sequence

- *

- * Preconditions:

* * @param lower lower bound for generated integer * @param upper upper bound for generated integer - * @return a long integer greater than or equal to lower - * and less than or equal to upper. + * @return a random long integer greater than or equal to {@code lower} and + * less than or equal to {@code upper}. + * @throws NumberIsTooLargeException if {@code lower >= upper}. */ - long nextSecureLong(long lower, long upper); + long nextSecureLong(long lower, long upper) + throws NumberIsTooLargeException; /** - * Generates a random value from the Poisson distribution with - * the given mean. + * Generates a random value from the Poisson distribution with the given + * mean. *

* Definition: * * Poisson Distribution

- *

- * Preconditions:

- * @param mean Mean of the distribution - * @return poisson deviate with the specified mean + * + * @param mean the mean of the Poisson distribution + * @return a random value following the specified Poisson distribution + * @throws NotStrictlyPositiveException if {@code mean <= 0}. */ - long nextPoisson(double mean); + long nextPoisson(double mean) throws NotStrictlyPositiveException; /** - * Generates a random value from the - * Normal (or Gaussian) distribution with the given mean - * and standard deviation. + * Generates a random value from the Normal (or Gaussian) distribution with + * specified mean and standard deviation. *

* Definition: * * Normal Distribution

- *

- * Preconditions:

- * @param mu Mean of the distribution - * @param sigma Standard deviation of the distribution - * @return random value from Gaussian distribution with mean = mu, - * standard deviation = sigma + * + * @param mu the mean of the distribution + * @param sigma the standard deviation of the distribution + * @return a random value following the specified Gaussian distribution + * @throws NotStrictlyPositiveException if {@code sigma <= 0}. */ - double nextGaussian(double mu, double sigma); + double nextGaussian(double mu, double sigma) + throws NotStrictlyPositiveException; /** * Generates a random value from the exponential distribution - * with expected value = mean. + * with specified mean. *

* Definition: * * Exponential Distribution

- *

- * Preconditions:

- * @param mean Mean of the distribution - * @return random value from exponential distribution + * + * @param mean the mean of the distribution + * @return a random value following the specified exponential distribution + * @throws NotStrictlyPositiveException if {@code mean <= 0}. */ - double nextExponential(double mean); + double nextExponential(double mean) throws NotStrictlyPositiveException; /** * Generates a uniformly distributed random value from the open interval @@ -207,17 +180,18 @@ public interface RandomData { *

* Definition: * - * Uniform Distribution lower and - * upper - lower are the + * Uniform Distribution {@code lower} and {@code upper - lower} are the * * location and scale parameters, respectively.

* - * @param lower lower endpoint of the interval of support - * @param upper upper endpoint of the interval of support - * @return uniformly distributed random value between lower - * and upper (exclusive) + * @param lower the exclusive lower bound of the support + * @param upper the exclusive upper bound of the support + * @return a uniformly distributed random value between lower and upper + * (exclusive) + * @throws NumberIsTooLargeException if {@code lower >= upper} */ - double nextUniform(double lower, double upper); + double nextUniform(double lower, double upper) + throws NumberIsTooLargeException; /** * Generates a uniformly distributed random value from the interval @@ -227,64 +201,56 @@ public interface RandomData { *

* Definition: * - * Uniform Distribution lower and - * upper - lower are the + * Uniform Distribution {@code lower} and {@code upper - lower} are the * * location and scale parameters, respectively.

* - * @param lower lower endpoint of the interval of support - * @param upper upper endpoint of the interval of support - * @param lowerInclusive {@code true} if the lower bound is included in the - * interval + * @param lower the lower bound of the support + * @param upper the exclusive upper bound of the support + * @param lowerInclusive {@code true} if the lower bound is inclusive * @return 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} */ - double nextUniform(double lower, double upper, boolean lowerInclusive); + double nextUniform(double lower, double upper, boolean lowerInclusive) + throws NumberIsTooLargeException; /** - * Generates an integer array of length k whose entries - * are selected randomly, without repetition, from the integers - * 0 through n-1 (inclusive). + * Generates an integer array of length {@code k} whose entries are selected + * randomly, without repetition, from the integers {@code 0, ..., n - 1} + * (inclusive). *

- * Generated arrays represent permutations - * of n taken k at a time.

- *

- * Preconditions:

- * If the preconditions are not met, an IllegalArgumentException is - * thrown.

+ * Generated arrays represent permutations of {@code n} taken {@code k} at a + * time.

* - * @param n domain of the permutation - * @param k size of the permutation - * @return random k-permutation of n + * @param n the domain of the permutation + * @param k the size of the permutation + * @return a random {@code k}-permutation of {@code n}, as an array of + * integers + * @throws NumberIsTooLargeException if {@code k > n}. + * @throws NotStrictlyPositiveException if {@code k <= 0}. */ - int[] nextPermutation(int n, int k); + int[] nextPermutation(int n, int k) + throws NumberIsTooLargeException, NotStrictlyPositiveException; /** - * Returns an array of k objects selected randomly - * from the Collection c. + * Returns an array of {@code k} objects selected randomly from the + * Collection {@code c}. *

- * Sampling from c - * is without replacement; but if c contains identical - * objects, the sample may include repeats. If all elements of - * c are distinct, the resulting object array represents a + * Sampling from {@code c} is without replacement; but if {@code c} contains + * identical objects, the sample may include repeats. If all elements of + * {@code c} are distinct, the resulting object array represents a * - * Simple Random Sample of size - * k from the elements of c.

- *

- * Preconditions:

- * If the preconditions are not met, an IllegalArgumentException is - * thrown.

+ * Simple Random Sample of size {@code k} from the elements of + * {@code c}.

* - * @param c collection to be sampled - * @param k size of the sample - * @return random sample of k elements from c + * @param c the collection to be sampled + * @param k the size of the sample + * @return a random sample of {@code k} elements from {@code c} + * @throws NumberIsTooLargeException if {@code k > c.size()}. + * @throws NotStrictlyPositiveException if {@code k <= 0}. */ - Object[] nextSample(Collection c, int k); + Object[] nextSample(Collection c, int k) + throws NumberIsTooLargeException, NotStrictlyPositiveException; } diff --git a/src/main/java/org/apache/commons/math/random/RandomDataImpl.java b/src/main/java/org/apache/commons/math/random/RandomDataImpl.java index 3d64ac2a2..b70f68816 100644 --- a/src/main/java/org/apache/commons/math/random/RandomDataImpl.java +++ b/src/main/java/org/apache/commons/math/random/RandomDataImpl.java @@ -187,19 +187,17 @@ public class RandomDataImpl implements RandomData, Serializable { * Algorithm Description: hex strings are generated using a * 2-step process. *
    - *
  1. - * len/2+1 binary bytes are generated using the underlying Random
  2. - *
  3. - * Each binary byte is translated into 2 hex digits
  4. + *
  5. {@code len / 2 + 1} binary bytes are generated using the underlying + * Random
  6. + *
  7. Each binary byte is translated into 2 hex digits
  8. *
*

* - * @param len - * the desired string length. + * @param len the desired string length. * @return the random string. * @throws NotStrictlyPositiveException if {@code len <= 0}. */ - public String nextHexString(int len) { + public String nextHexString(int len) throws NotStrictlyPositiveException { if (len <= 0) { throw new NotStrictlyPositiveException(LocalizedFormats.LENGTH, len); } @@ -234,38 +232,18 @@ public class RandomDataImpl implements RandomData, Serializable { return outBuffer.toString().substring(0, len); } - /** - * Generate a random int value uniformly distributed between - * lower and upper, inclusive. - * - * @param lower - * the lower bound. - * @param upper - * the upper bound. - * @return the random integer. - * @throws NumberIsTooLargeException if {@code lower >= upper}. - */ - public int nextInt(int lower, int upper) { + /** {@inheritDoc} */ + public int nextInt(int lower, int upper) throws NumberIsTooLargeException { if (lower >= upper) { throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND, lower, upper, false); } double r = getRan().nextDouble(); double scaled = r * upper + (1.0 - r) * lower + r; - return (int)FastMath.floor(scaled); + return (int) FastMath.floor(scaled); } - /** - * Generate a random long value uniformly distributed between - * lower and upper, inclusive. - * - * @param lower - * the lower bound. - * @param upper - * the upper bound. - * @return the random integer. - * @throws NumberIsTooLargeException if {@code lower >= upper}. - */ + /** {@inheritDoc} */ public long nextLong(long lower, long upper) { if (lower >= upper) { throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND, @@ -291,13 +269,8 @@ public class RandomDataImpl implements RandomData, Serializable { * Each byte of the binary digest is converted to 2 hex digits. * *

- * - * @param len - * the length of the generated string - * @return the random string - * @throws NotStrictlyPositiveException if {@code len <= 0}. */ - public String nextSecureHexString(int len) { + public String nextSecureHexString(int len) throws NotStrictlyPositiveException { if (len <= 0) { throw new NotStrictlyPositiveException(LocalizedFormats.LENGTH, len); } @@ -323,7 +296,7 @@ public class RandomDataImpl implements RandomData, Serializable { alg.update(randomBytes); // Compute hash -- will create 20-byte binary hash - byte hash[] = alg.digest(); + byte[] hash = alg.digest(); // Loop over the hash, converting each byte to 2 hex digits for (int i = 0; i < hash.length; i++) { @@ -346,18 +319,7 @@ public class RandomDataImpl implements RandomData, Serializable { return outBuffer.toString().substring(0, len); } - /** - * Generate a random int value uniformly distributed between - * lower and upper, inclusive. This algorithm uses - * a secure random number generator. - * - * @param lower - * the lower bound. - * @param upper - * the upper bound. - * @return the random integer. - * @throws NumberIsTooLargeException if {@code lower >= upper}. - */ + /** {@inheritDoc} */ public int nextSecureInt(int lower, int upper) { if (lower >= upper) { throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND, @@ -369,19 +331,10 @@ public class RandomDataImpl implements RandomData, Serializable { return (int)FastMath.floor(scaled); } - /** - * Generate a random long value uniformly distributed between - * lower and upper, inclusive. This algorithm uses - * a secure random number generator. - * - * @param lower - * the lower bound. - * @param upper - * the upper bound. - * @return the random integer. - * @throws NumberIsTooLargeException if {@code lower >= upper}. - */ - public long nextSecureLong(long lower, long upper) { + /** {@inheritDoc} */ + public long nextSecureLong(long lower, long upper) + throws NumberIsTooLargeException { + if (lower >= upper) { throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND, lower, upper, false); @@ -404,12 +357,8 @@ public class RandomDataImpl implements RandomData, Serializable { *
  • For large means, uses the rejection algorithm described in
    * Devroye, Luc. (1981).The Computer Generation of Poisson Random Variables * Computing vol. 26 pp. 197-207.
  • - * - * @param mean mean of the Poisson distribution. - * @return the random Poisson value. - * @throws NotStrictlyPositiveException if {@code mean <= 0}. */ - public long nextPoisson(double mean) { + public long nextPoisson(double mean) throws NotStrictlyPositiveException { if (mean <= 0) { throw new NotStrictlyPositiveException(LocalizedFormats.MEAN, mean); } @@ -500,19 +449,10 @@ public class RandomDataImpl implements RandomData, Serializable { } } - /** - * Generate a random value from a Normal (a.k.a. Gaussian) distribution with - * the given mean, mu and the given standard deviation, - * sigma. - * - * @param mu - * the mean of the distribution - * @param sigma - * the standard deviation of the distribution - * @return the random Normal value - * @throws NotStrictlyPositiveException if {@code sigma <= 0}. - */ - public double nextGaussian(double mu, double sigma) { + /** {@inheritDoc} */ + public double nextGaussian(double mu, double sigma) + throws NotStrictlyPositiveException { + if (sigma <= 0) { throw new NotStrictlyPositiveException(LocalizedFormats.STANDARD_DEVIATION, sigma); } @@ -520,8 +460,8 @@ public class RandomDataImpl implements RandomData, Serializable { } /** - * Returns a random value from an Exponential distribution with the given - * mean. + * {@inheritDoc} + * *

    * Algorithm Description: Uses the Algorithm SA (Ahrens) * from p. 876 in: @@ -529,12 +469,10 @@ public class RandomDataImpl implements RandomData, Serializable { * sampling from the exponential and normal distributions. * Communications of the ACM, 15, 873-882. *

    - * - * @param mean the mean of the distribution - * @return the random Exponential value - * @throws NotStrictlyPositiveException if {@code mean <= 0}. */ - public double nextExponential(double mean) { + public double nextExponential(double mean) + throws NotStrictlyPositiveException { + if (mean <= 0.0) { throw new NotStrictlyPositiveException(LocalizedFormats.MEAN, mean); } @@ -579,6 +517,7 @@ public class RandomDataImpl implements RandomData, Serializable { /** * {@inheritDoc} + * *

    * Algorithm Description: scales the output of * Random.nextDouble(), but rejects 0 values (i.e., will generate another @@ -586,20 +525,18 @@ public class RandomDataImpl implements RandomData, Serializable { * provide a symmetric output interval (both endpoints excluded). *

    * - * @param lower the lower bound. - * @param upper the upper bound. - * @return a uniformly distributed random value from the interval (lower, upper) - * @throws NumberIsTooLargeException if {@code lower >= upper} * @throws MathIllegalArgumentException if one of the bounds is infinite or - * {@code NaN} - * or either bound is infinite or NaN + * {@code NaN} or either bound is infinite or NaN */ - public double nextUniform(double lower, double upper) { + public double nextUniform(double lower, double upper) + throws NumberIsTooLargeException, MathIllegalArgumentException { + return nextUniform(lower, upper, false); } /** * {@inheritDoc} + * *

    * Algorithm Description: if the lower bound is excluded, * scales the output of Random.nextDouble(), but rejects 0 values (i.e., @@ -608,20 +545,14 @@ public class RandomDataImpl implements RandomData, Serializable { * endpoints excluded). *

    * - * @param lower - * the lower bound. - * @param upper - * the upper bound. - * @param lowerInclusive - * whether the lower bound is included in the interval - * @return a uniformly distributed random value from the interval (lower, - * upper) - * @throws NumberIsTooLargeException if {@code lower >= upper} * @throws MathIllegalArgumentException if one of the bounds is infinite or * {@code NaN} * @since 3.0 */ - public double nextUniform(double lower, double upper, boolean lowerInclusive) { + public double nextUniform(double lower, double upper, + boolean lowerInclusive) + throws NumberIsTooLargeException, MathIllegalArgumentException { + if (lower >= upper) { throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND, lower, upper, false); @@ -997,41 +928,20 @@ public class RandomDataImpl implements RandomData, Serializable { } /** - * Generates an integer array of length k whose entries are - * selected randomly, without repetition, from the integers - * 0 through n-1 (inclusive). - *

    - * Generated arrays represent permutations of n taken - * k at a time. - *

    - *

    - * Preconditions: - *

    - * If the preconditions are not met, an IllegalArgumentException is thrown. - *

    + * {@inheritDoc} + * *

    * Uses a 2-cycle permutation shuffle. The shuffling process is described * here. *

    - * - * @param n - * domain of the permutation (must be positive) - * @param k - * size of the permutation (must satisfy 0 < k <= n). - * @return the random permutation as an int array - * @throws NumberIsTooLargeException if {@code k > n}. - * @throws NotStrictlyPositiveException if {@code k <= 0}. */ public int[] nextPermutation(int n, int k) { if (k > n) { throw new NumberIsTooLargeException(LocalizedFormats.PERMUTATION_EXCEEDS_N, k, n, true); } - if (k == 0) { + if (k <= 0) { throw new NotStrictlyPositiveException(LocalizedFormats.PERMUTATION_SIZE, k); } @@ -1047,24 +957,21 @@ public class RandomDataImpl implements RandomData, Serializable { } /** - * Uses a 2-cycle permutation shuffle to generate a random permutation. + * {@inheritDoc} + * + *

    * Algorithm Description: Uses a 2-cycle permutation * shuffle to generate a random permutation of c.size() and * then returns the elements whose indexes correspond to the elements of the * generated permutation. This technique is described, and proven to - * generate random samples, * here - * - * @param c - * Collection to sample from. - * @param k - * sample size. - * @return the random sample. - * @throws NumberIsTooLargeException if {@code k > c.size()}. - * @throws NotStrictlyPositiveException if {@code k <= 0}. + *

    */ - public Object[] nextSample(Collection c, int k) { + public Object[] nextSample(Collection c, int k) + throws NumberIsTooLargeException, NotStrictlyPositiveException { + int len = c.size(); if (k > len) { throw new NumberIsTooLargeException(LocalizedFormats.SAMPLE_SIZE_EXCEEDS_COLLECTION_SIZE,