View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math3.random;
19  
20  import java.io.Serializable;
21  import java.security.MessageDigest;
22  import java.security.NoSuchAlgorithmException;
23  import java.security.NoSuchProviderException;
24  import java.security.SecureRandom;
25  import java.util.Collection;
26  
27  import org.apache.commons.math3.distribution.BetaDistribution;
28  import org.apache.commons.math3.distribution.BinomialDistribution;
29  import org.apache.commons.math3.distribution.CauchyDistribution;
30  import org.apache.commons.math3.distribution.ChiSquaredDistribution;
31  import org.apache.commons.math3.distribution.ExponentialDistribution;
32  import org.apache.commons.math3.distribution.FDistribution;
33  import org.apache.commons.math3.distribution.GammaDistribution;
34  import org.apache.commons.math3.distribution.HypergeometricDistribution;
35  import org.apache.commons.math3.distribution.PascalDistribution;
36  import org.apache.commons.math3.distribution.PoissonDistribution;
37  import org.apache.commons.math3.distribution.TDistribution;
38  import org.apache.commons.math3.distribution.WeibullDistribution;
39  import org.apache.commons.math3.distribution.ZipfDistribution;
40  import org.apache.commons.math3.exception.MathInternalError;
41  import org.apache.commons.math3.exception.NotANumberException;
42  import org.apache.commons.math3.exception.NotFiniteNumberException;
43  import org.apache.commons.math3.exception.NotPositiveException;
44  import org.apache.commons.math3.exception.NotStrictlyPositiveException;
45  import org.apache.commons.math3.exception.NumberIsTooLargeException;
46  import org.apache.commons.math3.exception.OutOfRangeException;
47  import org.apache.commons.math3.exception.util.LocalizedFormats;
48  
49  /**
50   * Implements the {@link RandomData} interface using a {@link RandomGenerator}
51   * instance to generate non-secure data and a {@link java.security.SecureRandom}
52   * instance to provide data for the <code>nextSecureXxx</code> methods. If no
53   * <code>RandomGenerator</code> is provided in the constructor, the default is
54   * to use a {@link Well19937c} generator. To plug in a different
55   * implementation, either implement <code>RandomGenerator</code> directly or
56   * extend {@link AbstractRandomGenerator}.
57   * <p>
58   * Supports reseeding the underlying pseudo-random number generator (PRNG). The
59   * <code>SecurityProvider</code> and <code>Algorithm</code> used by the
60   * <code>SecureRandom</code> instance can also be reset.
61   * </p>
62   * <p>
63   * For details on the default PRNGs, see {@link java.util.Random} and
64   * {@link java.security.SecureRandom}.
65   * </p>
66   * <p>
67   * <strong>Usage Notes</strong>:
68   * <ul>
69   * <li>
70   * Instance variables are used to maintain <code>RandomGenerator</code> and
71   * <code>SecureRandom</code> instances used in data generation. Therefore, to
72   * generate a random sequence of values or strings, you should use just
73   * <strong>one</strong> <code>RandomDataImpl</code> instance repeatedly.</li>
74   * <li>
75   * The "secure" methods are *much* slower. These should be used only when a
76   * cryptographically secure random sequence is required. A secure random
77   * sequence is a sequence of pseudo-random values which, in addition to being
78   * well-dispersed (so no subsequence of values is an any more likely than other
79   * subsequence of the the same length), also has the additional property that
80   * knowledge of values generated up to any point in the sequence does not make
81   * it any easier to predict subsequent values.</li>
82   * <li>
83   * When a new <code>RandomDataImpl</code> is created, the underlying random
84   * number generators are <strong>not</strong> initialized. If you do not
85   * explicitly seed the default non-secure generator, it is seeded with the
86   * current time in milliseconds plus the system identity hash code on first use.
87   * The same holds for the secure generator. If you provide a <code>RandomGenerator</code>
88   * to the constructor, however, this generator is not reseeded by the constructor
89   * nor is it reseeded on first use.</li>
90   * <li>
91   * The <code>reSeed</code> and <code>reSeedSecure</code> methods delegate to the
92   * corresponding methods on the underlying <code>RandomGenerator</code> and
93   * <code>SecureRandom</code> instances. Therefore, <code>reSeed(long)</code>
94   * fully resets the initial state of the non-secure random number generator (so
95   * that reseeding with a specific value always results in the same subsequent
96   * random sequence); whereas reSeedSecure(long) does <strong>not</strong>
97   * reinitialize the secure random number generator (so secure sequences started
98   * with calls to reseedSecure(long) won't be identical).</li>
99   * <li>
100  * This implementation is not synchronized. The underlying <code>RandomGenerator</code>
101  * or <code>SecureRandom</code> instances are not protected by synchronization and
102  * are not guaranteed to be thread-safe.  Therefore, if an instance of this class
103  * is concurrently utilized by multiple threads, it is the responsibility of
104  * client code to synchronize access to seeding and data generation methods.
105  * </li>
106  * </ul>
107  * </p>
108  * @since 3.1
109  * @version $Id: RandomDataGenerator.java 1462423 2013-03-29 07:25:18Z luc $
110  */
111 public class RandomDataGenerator implements RandomData, Serializable {
112 
113     /** Serializable version identifier */
114     private static final long serialVersionUID = -626730818244969716L;
115 
116     /** underlying random number generator */
117     private RandomGenerator rand = null;
118 
119     /** underlying secure random number generator */
120     private SecureRandom secRand = null;
121 
122     /**
123      * Construct a RandomDataGenerator, using a default random generator as the source
124      * of randomness.
125      *
126      * <p>The default generator is a {@link Well19937c} seeded
127      * with {@code System.currentTimeMillis() + System.identityHashCode(this))}.
128      * The generator is initialized and seeded on first use.</p>
129      */
130     public RandomDataGenerator() {
131     }
132 
133     /**
134      * Construct a RandomDataGenerator using the supplied {@link RandomGenerator} as
135      * the source of (non-secure) random data.
136      *
137      * @param rand the source of (non-secure) random data
138      * (may be null, resulting in the default generator)
139      */
140     public RandomDataGenerator(RandomGenerator rand) {
141         this.rand = rand;
142     }
143 
144     /**
145      * {@inheritDoc}
146      * <p>
147      * <strong>Algorithm Description:</strong> hex strings are generated using a
148      * 2-step process.
149      * <ol>
150      * <li>{@code len / 2 + 1} binary bytes are generated using the underlying
151      * Random</li>
152      * <li>Each binary byte is translated into 2 hex digits</li>
153      * </ol>
154      * </p>
155      *
156      * @param len the desired string length.
157      * @return the random string.
158      * @throws NotStrictlyPositiveException if {@code len <= 0}.
159      */
160     public String nextHexString(int len) throws NotStrictlyPositiveException {
161         if (len <= 0) {
162             throw new NotStrictlyPositiveException(LocalizedFormats.LENGTH, len);
163         }
164 
165         // Get a random number generator
166         RandomGenerator ran = getRandomGenerator();
167 
168         // Initialize output buffer
169         StringBuilder outBuffer = new StringBuilder();
170 
171         // Get int(len/2)+1 random bytes
172         byte[] randomBytes = new byte[(len / 2) + 1];
173         ran.nextBytes(randomBytes);
174 
175         // Convert each byte to 2 hex digits
176         for (int i = 0; i < randomBytes.length; i++) {
177             Integer c = Integer.valueOf(randomBytes[i]);
178 
179             /*
180              * Add 128 to byte value to make interval 0-255 before doing hex
181              * conversion. This guarantees <= 2 hex digits from toHexString()
182              * toHexString would otherwise add 2^32 to negative arguments.
183              */
184             String hex = Integer.toHexString(c.intValue() + 128);
185 
186             // Make sure we add 2 hex digits for each byte
187             if (hex.length() == 1) {
188                 hex = "0" + hex;
189             }
190             outBuffer.append(hex);
191         }
192         return outBuffer.toString().substring(0, len);
193     }
194 
195     /** {@inheritDoc} */
196     public int nextInt(final int lower, final int upper) throws NumberIsTooLargeException {
197         if (lower >= upper) {
198             throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
199                                                 lower, upper, false);
200         }
201         final int max = (upper - lower) + 1;
202         if (max <= 0) {
203             // the range is too wide to fit in a positive int (larger than 2^31); as it covers
204             // more than half the integer range, we use directly a simple rejection method
205             final RandomGenerator rng = getRandomGenerator();
206             while (true) {
207                 final int r = rng.nextInt();
208                 if (r >= lower && r <= upper) {
209                     return r;
210                 }
211             }
212         } else {
213             // we can shift the range and generate directly a positive int
214             return lower + getRandomGenerator().nextInt(max);
215         }
216     }
217 
218     /** {@inheritDoc} */
219     public long nextLong(final long lower, final long upper) throws NumberIsTooLargeException {
220         if (lower >= upper) {
221             throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
222                                                 lower, upper, false);
223         }
224         final long max = (upper - lower) + 1;
225         if (max <= 0) {
226             // the range is too wide to fit in a positive long (larger than 2^63); as it covers
227             // more than half the long range, we use directly a simple rejection method
228             final RandomGenerator rng = getRandomGenerator();
229             while (true) {
230                 final long r = rng.nextLong();
231                 if (r >= lower && r <= upper) {
232                     return r;
233                 }
234             }
235         } else if (max < Integer.MAX_VALUE){
236             // we can shift the range and generate directly a positive int
237             return lower + getRandomGenerator().nextInt((int) max);
238         } else {
239             // we can shift the range and generate directly a positive long
240             return lower + nextLong(getRandomGenerator(), max);
241         }
242     }
243 
244     /**
245      * Returns a pseudorandom, uniformly distributed <tt>long</tt> value
246      * between 0 (inclusive) and the specified value (exclusive), drawn from
247      * this random number generator's sequence.
248      *
249      * @param rng random generator to use
250      * @param n the bound on the random number to be returned.  Must be
251      * positive.
252      * @return  a pseudorandom, uniformly distributed <tt>long</tt>
253      * value between 0 (inclusive) and n (exclusive).
254      * @throws IllegalArgumentException  if n is not positive.
255      */
256     private static long nextLong(final RandomGenerator rng, final long n) throws IllegalArgumentException {
257         if (n > 0) {
258             final byte[] byteArray = new byte[8];
259             long bits;
260             long val;
261             do {
262                 rng.nextBytes(byteArray);
263                 bits = 0;
264                 for (final byte b : byteArray) {
265                     bits = (bits << 8) | (((long) b) & 0xffL);
266                 }
267                 bits = bits & 0x7fffffffffffffffL;
268                 val  = bits % n;
269             } while (bits - val + (n - 1) < 0);
270             return val;
271         }
272         throw new NotStrictlyPositiveException(n);
273     }
274 
275     /**
276      * {@inheritDoc}
277      * <p>
278      * <strong>Algorithm Description:</strong> hex strings are generated in
279      * 40-byte segments using a 3-step process.
280      * <ol>
281      * <li>
282      * 20 random bytes are generated using the underlying
283      * <code>SecureRandom</code>.</li>
284      * <li>
285      * SHA-1 hash is applied to yield a 20-byte binary digest.</li>
286      * <li>
287      * Each byte of the binary digest is converted to 2 hex digits.</li>
288      * </ol>
289      * </p>
290      * @throws NotStrictlyPositiveException if {@code len <= 0}
291      */
292     public String nextSecureHexString(int len) throws NotStrictlyPositiveException {
293         if (len <= 0) {
294             throw new NotStrictlyPositiveException(LocalizedFormats.LENGTH, len);
295         }
296 
297         // Get SecureRandom and setup Digest provider
298         SecureRandom secRan = getSecRan();
299         MessageDigest alg = null;
300         try {
301             alg = MessageDigest.getInstance("SHA-1");
302         } catch (NoSuchAlgorithmException ex) {
303             // this should never happen
304             throw new MathInternalError(ex);
305         }
306         alg.reset();
307 
308         // Compute number of iterations required (40 bytes each)
309         int numIter = (len / 40) + 1;
310 
311         StringBuilder outBuffer = new StringBuilder();
312         for (int iter = 1; iter < numIter + 1; iter++) {
313             byte[] randomBytes = new byte[40];
314             secRan.nextBytes(randomBytes);
315             alg.update(randomBytes);
316 
317             // Compute hash -- will create 20-byte binary hash
318             byte[] hash = alg.digest();
319 
320             // Loop over the hash, converting each byte to 2 hex digits
321             for (int i = 0; i < hash.length; i++) {
322                 Integer c = Integer.valueOf(hash[i]);
323 
324                 /*
325                  * Add 128 to byte value to make interval 0-255 This guarantees
326                  * <= 2 hex digits from toHexString() toHexString would
327                  * otherwise add 2^32 to negative arguments
328                  */
329                 String hex = Integer.toHexString(c.intValue() + 128);
330 
331                 // Keep strings uniform length -- guarantees 40 bytes
332                 if (hex.length() == 1) {
333                     hex = "0" + hex;
334                 }
335                 outBuffer.append(hex);
336             }
337         }
338         return outBuffer.toString().substring(0, len);
339     }
340 
341     /**  {@inheritDoc} */
342     public int nextSecureInt(final int lower, final int upper) throws NumberIsTooLargeException {
343         if (lower >= upper) {
344             throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
345                                                 lower, upper, false);
346         }
347         final int max = (upper - lower) + 1;
348         if (max <= 0) {
349             // the range is too wide to fit in a positive int (larger than 2^31); as it covers
350             // more than half the integer range, we use directly a simple rejection method
351             final SecureRandom rng = getSecRan();
352             while (true) {
353                 final int r = rng.nextInt();
354                 if (r >= lower && r <= upper) {
355                     return r;
356                 }
357             }
358         } else {
359             // we can shift the range and generate directly a positive int
360             return lower + getSecRan().nextInt(max);
361         }
362     }
363 
364     /** {@inheritDoc} */
365     public long nextSecureLong(final long lower, final long upper) throws NumberIsTooLargeException {
366         if (lower >= upper) {
367             throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
368                                                 lower, upper, false);
369         }
370         final long max = (upper - lower) + 1;
371         if (max <= 0) {
372             // the range is too wide to fit in a positive long (larger than 2^63); as it covers
373             // more than half the long range, we use directly a simple rejection method
374             final SecureRandom rng = getSecRan();
375             while (true) {
376                 final long r = rng.nextLong();
377                 if (r >= lower && r <= upper) {
378                     return r;
379                 }
380             }
381         } else if (max < Integer.MAX_VALUE){
382             // we can shift the range and generate directly a positive int
383             return lower + getSecRan().nextInt((int) max);
384         } else {
385             // we can shift the range and generate directly a positive long
386             return lower + nextLong(getSecRan(), max);
387         }
388     }
389 
390     /**
391      * Returns a pseudorandom, uniformly distributed <tt>long</tt> value
392      * between 0 (inclusive) and the specified value (exclusive), drawn from
393      * this random number generator's sequence.
394      *
395      * @param rng random generator to use
396      * @param n the bound on the random number to be returned.  Must be
397      * positive.
398      * @return  a pseudorandom, uniformly distributed <tt>long</tt>
399      * value between 0 (inclusive) and n (exclusive).
400      * @throws IllegalArgumentException  if n is not positive.
401      */
402     private static long nextLong(final SecureRandom rng, final long n) throws IllegalArgumentException {
403         if (n > 0) {
404             final byte[] byteArray = new byte[8];
405             long bits;
406             long val;
407             do {
408                 rng.nextBytes(byteArray);
409                 bits = 0;
410                 for (final byte b : byteArray) {
411                     bits = (bits << 8) | (((long) b) & 0xffL);
412                 }
413                 bits = bits & 0x7fffffffffffffffL;
414                 val  = bits % n;
415             } while (bits - val + (n - 1) < 0);
416             return val;
417         }
418         throw new NotStrictlyPositiveException(n);
419     }
420 
421     /**
422      * {@inheritDoc}
423      * <p>
424      * <strong>Algorithm Description</strong>:
425      * <ul><li> For small means, uses simulation of a Poisson process
426      * using Uniform deviates, as described
427      * <a href="http://irmi.epfl.ch/cmos/Pmmi/interactive/rng7.htm"> here.</a>
428      * The Poisson process (and hence value returned) is bounded by 1000 * mean.</li>
429      *
430      * <li> For large means, uses the rejection algorithm described in <br/>
431      * Devroye, Luc. (1981).<i>The Computer Generation of Poisson Random Variables</i>
432      * <strong>Computing</strong> vol. 26 pp. 197-207.</li></ul></p>
433      * @throws NotStrictlyPositiveException if {@code len <= 0}
434      */
435     public long nextPoisson(double mean) throws NotStrictlyPositiveException {
436         return new PoissonDistribution(getRandomGenerator(), mean,
437                 PoissonDistribution.DEFAULT_EPSILON,
438                 PoissonDistribution.DEFAULT_MAX_ITERATIONS).sample();
439     }
440 
441     /** {@inheritDoc} */
442     public double nextGaussian(double mu, double sigma) throws NotStrictlyPositiveException {
443         if (sigma <= 0) {
444             throw new NotStrictlyPositiveException(LocalizedFormats.STANDARD_DEVIATION, sigma);
445         }
446         return sigma * getRandomGenerator().nextGaussian() + mu;
447     }
448 
449     /**
450      * {@inheritDoc}
451      *
452      * <p>
453      * <strong>Algorithm Description</strong>: Uses the Algorithm SA (Ahrens)
454      * from p. 876 in:
455      * [1]: Ahrens, J. H. and Dieter, U. (1972). Computer methods for
456      * sampling from the exponential and normal distributions.
457      * Communications of the ACM, 15, 873-882.
458      * </p>
459      */
460     public double nextExponential(double mean) throws NotStrictlyPositiveException {
461         return new ExponentialDistribution(getRandomGenerator(), mean,
462                 ExponentialDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY).sample();
463     }
464 
465     /**
466      * <p>Generates a random value from the
467      * {@link org.apache.commons.math3.distribution.GammaDistribution Gamma Distribution}.</p>
468      *
469      * <p>This implementation uses the following algorithms: </p>
470      *
471      * <p>For 0 < shape < 1: <br/>
472      * Ahrens, J. H. and Dieter, U., <i>Computer methods for
473      * sampling from gamma, beta, Poisson and binomial distributions.</i>
474      * Computing, 12, 223-246, 1974.</p>
475      *
476      * <p>For shape >= 1: <br/>
477      * Marsaglia and Tsang, <i>A Simple Method for Generating
478      * Gamma Variables.</i> ACM Transactions on Mathematical Software,
479      * Volume 26 Issue 3, September, 2000.</p>
480      *
481      * @param shape the median of the Gamma distribution
482      * @param scale the scale parameter of the Gamma distribution
483      * @return random value sampled from the Gamma(shape, scale) distribution
484      * @throws NotStrictlyPositiveException if {@code shape <= 0} or
485      * {@code scale <= 0}.
486      */
487     public double nextGamma(double shape, double scale) throws NotStrictlyPositiveException {
488         return new GammaDistribution(getRandomGenerator(),shape, scale,
489                 GammaDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY).sample();
490     }
491 
492     /**
493      * Generates a random value from the {@link HypergeometricDistribution Hypergeometric Distribution}.
494      *
495      * @param populationSize the population size of the Hypergeometric distribution
496      * @param numberOfSuccesses number of successes in the population of the Hypergeometric distribution
497      * @param sampleSize the sample size of the Hypergeometric distribution
498      * @return random value sampled from the Hypergeometric(numberOfSuccesses, sampleSize) distribution
499      * @throws NumberIsTooLargeException  if {@code numberOfSuccesses > populationSize},
500      * or {@code sampleSize > populationSize}.
501      * @throws NotStrictlyPositiveException if {@code populationSize <= 0}.
502      * @throws NotPositiveException  if {@code numberOfSuccesses < 0}.
503      */
504     public int nextHypergeometric(int populationSize, int numberOfSuccesses, int sampleSize) throws NotPositiveException, NotStrictlyPositiveException, NumberIsTooLargeException {
505         return new HypergeometricDistribution(getRandomGenerator(),populationSize,
506                 numberOfSuccesses, sampleSize).sample();
507     }
508 
509     /**
510      * Generates a random value from the {@link PascalDistribution Pascal Distribution}.
511      *
512      * @param r the number of successes of the Pascal distribution
513      * @param p the probability of success of the Pascal distribution
514      * @return random value sampled from the Pascal(r, p) distribution
515      * @throws NotStrictlyPositiveException if the number of successes is not positive
516      * @throws OutOfRangeException if the probability of success is not in the
517      * range {@code [0, 1]}.
518      */
519     public int nextPascal(int r, double p) throws NotStrictlyPositiveException, OutOfRangeException {
520         return new PascalDistribution(getRandomGenerator(), r, p).sample();
521     }
522 
523     /**
524      * Generates a random value from the {@link TDistribution T Distribution}.
525      *
526      * @param df the degrees of freedom of the T distribution
527      * @return random value from the T(df) distribution
528      * @throws NotStrictlyPositiveException if {@code df <= 0}
529      */
530     public double nextT(double df) throws NotStrictlyPositiveException {
531         return new TDistribution(getRandomGenerator(), df,
532                 TDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY).sample();
533     }
534 
535     /**
536      * Generates a random value from the {@link WeibullDistribution Weibull Distribution}.
537      *
538      * @param shape the shape parameter of the Weibull distribution
539      * @param scale the scale parameter of the Weibull distribution
540      * @return random value sampled from the Weibull(shape, size) distribution
541      * @throws NotStrictlyPositiveException if {@code shape <= 0} or
542      * {@code scale <= 0}.
543      */
544     public double nextWeibull(double shape, double scale) throws NotStrictlyPositiveException {
545         return new WeibullDistribution(getRandomGenerator(), shape, scale,
546                 WeibullDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY).sample();
547     }
548 
549     /**
550      * Generates a random value from the {@link ZipfDistribution Zipf Distribution}.
551      *
552      * @param numberOfElements the number of elements of the ZipfDistribution
553      * @param exponent the exponent of the ZipfDistribution
554      * @return random value sampled from the Zipf(numberOfElements, exponent) distribution
555      * @exception NotStrictlyPositiveException if {@code numberOfElements <= 0}
556      * or {@code exponent <= 0}.
557      */
558     public int nextZipf(int numberOfElements, double exponent) throws NotStrictlyPositiveException {
559         return new ZipfDistribution(getRandomGenerator(), numberOfElements, exponent).sample();
560     }
561 
562     /**
563      * Generates a random value from the {@link BetaDistribution Beta Distribution}.
564      *
565      * @param alpha first distribution shape parameter
566      * @param beta second distribution shape parameter
567      * @return random value sampled from the beta(alpha, beta) distribution
568      */
569     public double nextBeta(double alpha, double beta) {
570         return new BetaDistribution(getRandomGenerator(), alpha, beta,
571                 BetaDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY).sample();
572     }
573 
574     /**
575      * Generates a random value from the {@link BinomialDistribution Binomial Distribution}.
576      *
577      * @param numberOfTrials number of trials of the Binomial distribution
578      * @param probabilityOfSuccess probability of success of the Binomial distribution
579      * @return random value sampled from the Binomial(numberOfTrials, probabilityOfSuccess) distribution
580      */
581     public int nextBinomial(int numberOfTrials, double probabilityOfSuccess) {
582         return new BinomialDistribution(getRandomGenerator(), numberOfTrials, probabilityOfSuccess).sample();
583     }
584 
585     /**
586      * Generates a random value from the {@link CauchyDistribution Cauchy Distribution}.
587      *
588      * @param median the median of the Cauchy distribution
589      * @param scale the scale parameter of the Cauchy distribution
590      * @return random value sampled from the Cauchy(median, scale) distribution
591      */
592     public double nextCauchy(double median, double scale) {
593         return new CauchyDistribution(getRandomGenerator(), median, scale,
594                 CauchyDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY).sample();
595     }
596 
597     /**
598      * Generates a random value from the {@link ChiSquaredDistribution ChiSquare Distribution}.
599      *
600      * @param df the degrees of freedom of the ChiSquare distribution
601      * @return random value sampled from the ChiSquare(df) distribution
602      */
603     public double nextChiSquare(double df) {
604         return new ChiSquaredDistribution(getRandomGenerator(), df,
605                 ChiSquaredDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY).sample();
606     }
607 
608     /**
609      * Generates a random value from the {@link FDistribution F Distribution}.
610      *
611      * @param numeratorDf the numerator degrees of freedom of the F distribution
612      * @param denominatorDf the denominator degrees of freedom of the F distribution
613      * @return random value sampled from the F(numeratorDf, denominatorDf) distribution
614      * @throws NotStrictlyPositiveException if
615      * {@code numeratorDf <= 0} or {@code denominatorDf <= 0}.
616      */
617     public double nextF(double numeratorDf, double denominatorDf) throws NotStrictlyPositiveException {
618         return new FDistribution(getRandomGenerator(), numeratorDf, denominatorDf,
619                 FDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY).sample();
620     }
621 
622     /**
623      * {@inheritDoc}
624      *
625      * <p>
626      * <strong>Algorithm Description</strong>: scales the output of
627      * Random.nextDouble(), but rejects 0 values (i.e., will generate another
628      * random double if Random.nextDouble() returns 0). This is necessary to
629      * provide a symmetric output interval (both endpoints excluded).
630      * </p>
631      * @throws NumberIsTooLargeException if {@code lower >= upper}
632      * @throws NotFiniteNumberException if one of the bounds is infinite
633      * @throws NotANumberException if one of the bounds is NaN
634      */
635     public double nextUniform(double lower, double upper)
636         throws NumberIsTooLargeException, NotFiniteNumberException, NotANumberException {
637         return nextUniform(lower, upper, false);
638     }
639 
640     /**
641      * {@inheritDoc}
642      *
643      * <p>
644      * <strong>Algorithm Description</strong>: if the lower bound is excluded,
645      * scales the output of Random.nextDouble(), but rejects 0 values (i.e.,
646      * will generate another random double if Random.nextDouble() returns 0).
647      * This is necessary to provide a symmetric output interval (both
648      * endpoints excluded).
649      * </p>
650      *
651      * @throws NumberIsTooLargeException if {@code lower >= upper}
652      * @throws NotFiniteNumberException if one of the bounds is infinite
653      * @throws NotANumberException if one of the bounds is NaN
654      */
655     public double nextUniform(double lower, double upper, boolean lowerInclusive)
656         throws NumberIsTooLargeException, NotFiniteNumberException, NotANumberException {
657 
658         if (lower >= upper) {
659             throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
660                                                 lower, upper, false);
661         }
662 
663         if (Double.isInfinite(lower)) {
664             throw new NotFiniteNumberException(LocalizedFormats.INFINITE_BOUND, lower);
665         }
666         if (Double.isInfinite(upper)) {
667             throw new NotFiniteNumberException(LocalizedFormats.INFINITE_BOUND, upper);
668         }
669 
670         if (Double.isNaN(lower) || Double.isNaN(upper)) {
671             throw new NotANumberException();
672         }
673 
674         final RandomGenerator generator = getRandomGenerator();
675 
676         // ensure nextDouble() isn't 0.0
677         double u = generator.nextDouble();
678         while (!lowerInclusive && u <= 0.0) {
679             u = generator.nextDouble();
680         }
681 
682         return u * upper + (1.0 - u) * lower;
683     }
684 
685     /**
686      * {@inheritDoc}
687      *
688      * <p>
689      * Uses a 2-cycle permutation shuffle. The shuffling process is described <a
690      * href="http://www.maths.abdn.ac.uk/~igc/tch/mx4002/notes/node83.html">
691      * here</a>.
692      * </p>
693      * @throws NumberIsTooLargeException if {@code k > n}.
694      * @throws NotStrictlyPositiveException if {@code k <= 0}.
695      */
696     public int[] nextPermutation(int n, int k)
697         throws NumberIsTooLargeException, NotStrictlyPositiveException {
698         if (k > n) {
699             throw new NumberIsTooLargeException(LocalizedFormats.PERMUTATION_EXCEEDS_N,
700                                                 k, n, true);
701         }
702         if (k <= 0) {
703             throw new NotStrictlyPositiveException(LocalizedFormats.PERMUTATION_SIZE,
704                                                    k);
705         }
706 
707         int[] index = getNatural(n);
708         shuffle(index, n - k);
709         int[] result = new int[k];
710         for (int i = 0; i < k; i++) {
711             result[i] = index[n - i - 1];
712         }
713 
714         return result;
715     }
716 
717     /**
718      * {@inheritDoc}
719      *
720      * <p>
721      * <strong>Algorithm Description</strong>: Uses a 2-cycle permutation
722      * shuffle to generate a random permutation of <code>c.size()</code> and
723      * then returns the elements whose indexes correspond to the elements of the
724      * generated permutation. This technique is described, and proven to
725      * generate random samples <a
726      * href="http://www.maths.abdn.ac.uk/~igc/tch/mx4002/notes/node83.html">
727      * here</a>
728      * </p>
729      */
730     public Object[] nextSample(Collection<?> c, int k) throws NumberIsTooLargeException, NotStrictlyPositiveException {
731 
732         int len = c.size();
733         if (k > len) {
734             throw new NumberIsTooLargeException(LocalizedFormats.SAMPLE_SIZE_EXCEEDS_COLLECTION_SIZE,
735                                                 k, len, true);
736         }
737         if (k <= 0) {
738             throw new NotStrictlyPositiveException(LocalizedFormats.NUMBER_OF_SAMPLES, k);
739         }
740 
741         Object[] objects = c.toArray();
742         int[] index = nextPermutation(len, k);
743         Object[] result = new Object[k];
744         for (int i = 0; i < k; i++) {
745             result[i] = objects[index[i]];
746         }
747         return result;
748     }
749 
750 
751 
752     /**
753      * Reseeds the random number generator with the supplied seed.
754      * <p>
755      * Will create and initialize if null.
756      * </p>
757      *
758      * @param seed the seed value to use
759      */
760     public void reSeed(long seed) {
761        getRandomGenerator().setSeed(seed);
762     }
763 
764     /**
765      * Reseeds the secure random number generator with the current time in
766      * milliseconds.
767      * <p>
768      * Will create and initialize if null.
769      * </p>
770      */
771     public void reSeedSecure() {
772         getSecRan().setSeed(System.currentTimeMillis());
773     }
774 
775     /**
776      * Reseeds the secure random number generator with the supplied seed.
777      * <p>
778      * Will create and initialize if null.
779      * </p>
780      *
781      * @param seed the seed value to use
782      */
783     public void reSeedSecure(long seed) {
784         getSecRan().setSeed(seed);
785     }
786 
787     /**
788      * Reseeds the random number generator with
789      * {@code System.currentTimeMillis() + System.identityHashCode(this))}.
790      */
791     public void reSeed() {
792         getRandomGenerator().setSeed(System.currentTimeMillis() + System.identityHashCode(this));
793     }
794 
795     /**
796      * Sets the PRNG algorithm for the underlying SecureRandom instance using
797      * the Security Provider API. The Security Provider API is defined in <a
798      * href =
799      * "http://java.sun.com/j2se/1.3/docs/guide/security/CryptoSpec.html#AppA">
800      * Java Cryptography Architecture API Specification & Reference.</a>
801      * <p>
802      * <strong>USAGE NOTE:</strong> This method carries <i>significant</i>
803      * overhead and may take several seconds to execute.
804      * </p>
805      *
806      * @param algorithm the name of the PRNG algorithm
807      * @param provider the name of the provider
808      * @throws NoSuchAlgorithmException if the specified algorithm is not available
809      * @throws NoSuchProviderException if the specified provider is not installed
810      */
811     public void setSecureAlgorithm(String algorithm, String provider)
812             throws NoSuchAlgorithmException, NoSuchProviderException {
813         secRand = SecureRandom.getInstance(algorithm, provider);
814     }
815 
816     /**
817      * Returns the RandomGenerator used to generate non-secure random data.
818      * <p>
819      * Creates and initializes a default generator if null. Uses a {@link Well19937c}
820      * generator with {@code System.currentTimeMillis() + System.identityHashCode(this))}
821      * as the default seed.
822      * </p>
823      *
824      * @return the Random used to generate random data
825      * @since 3.2
826      */
827     public RandomGenerator getRandomGenerator() {
828         if (rand == null) {
829             initRan();
830         }
831         return rand;
832     }
833 
834     /**
835      * Sets the default generator to a {@link Well19937c} generator seeded with
836      * {@code System.currentTimeMillis() + System.identityHashCode(this))}.
837      */
838     private void initRan() {
839         rand = new Well19937c(System.currentTimeMillis() + System.identityHashCode(this));
840     }
841 
842     /**
843      * Returns the SecureRandom used to generate secure random data.
844      * <p>
845      * Creates and initializes if null.  Uses
846      * {@code System.currentTimeMillis() + System.identityHashCode(this)} as the default seed.
847      * </p>
848      *
849      * @return the SecureRandom used to generate secure random data
850      */
851     private SecureRandom getSecRan() {
852         if (secRand == null) {
853             secRand = new SecureRandom();
854             secRand.setSeed(System.currentTimeMillis() + System.identityHashCode(this));
855         }
856         return secRand;
857     }
858 
859     /**
860      * Uses a 2-cycle permutation shuffle to randomly re-order the last elements
861      * of list.
862      *
863      * @param list list to be shuffled
864      * @param end element past which shuffling begins
865      */
866     private void shuffle(int[] list, int end) {
867         int target = 0;
868         for (int i = list.length - 1; i >= end; i--) {
869             if (i == 0) {
870                 target = 0;
871             } else {
872                 // NumberIsTooLargeException cannot occur
873                 target = nextInt(0, i);
874             }
875             int temp = list[target];
876             list[target] = list[i];
877             list[i] = temp;
878         }
879     }
880 
881     /**
882      * Returns an array representing n.
883      *
884      * @param n the natural number to represent
885      * @return array with entries = elements of n
886      */
887     private int[] getNatural(int n) {
888         int[] natural = new int[n];
889         for (int i = 0; i < n; i++) {
890             natural[i] = i;
891         }
892         return natural;
893     }
894 }