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