51 |
|
* href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version |
52 |
|
* 3.31.1</a>.) These tests validate only the methods for certain |
53 |
|
* types and ranges, but similar properties are expected to hold, at |
54 |
< |
* least approximately, for others as well. </li> |
54 |
> |
* least approximately, for others as well. The <em>period</em> |
55 |
> |
* (length of any series of generated values before it repeats) is at |
56 |
> |
* least 2<sup>64</sup>. </li> |
57 |
|
* |
58 |
|
* <li> Method {@link #split} constructs and returns a new |
59 |
|
* SplittableRandom instance that shares no mutable state with the |
158 |
|
* SplittableRandom. Unlike other cases, this split must be |
159 |
|
* performed in a thread-safe manner. We use |
160 |
|
* AtomicLong.compareAndSet as the (typically) most efficient |
161 |
< |
* mechanism. To bootstrap, we start off using System.nanotime(), |
162 |
< |
* and update using another "genuinely random" constant |
163 |
< |
* DEFAULT_SEED_GAMMA. The default constructor uses GAMMA_GAMMA, |
164 |
< |
* not 0, for its splitSeed argument (addGammaModGeorge(0, |
165 |
< |
* GAMMA_GAMMA) == GAMMA_GAMMA) to reflect that each is split from |
166 |
< |
* this root generator, even though the root is not explicitly |
167 |
< |
* represented as a SplittableRandom. |
161 |
> |
* mechanism. To bootstrap, we start off using a function of the |
162 |
> |
* current System time as seed, and update using another |
163 |
> |
* "genuinely random" constant DEFAULT_SEED_GAMMA. The default |
164 |
> |
* constructor uses GAMMA_GAMMA, not 0, for its splitSeed argument |
165 |
> |
* (addGammaModGeorge(0, GAMMA_GAMMA) == GAMMA_GAMMA) to reflect |
166 |
> |
* that each is split from this root generator, even though the |
167 |
> |
* root is not explicitly represented as a SplittableRandom. When |
168 |
> |
* establishing the initial seed, we use both |
169 |
> |
* System.currentTimeMillis and System.nanoTime(), to avoid |
170 |
> |
* regularities that may occur if using either alone. |
171 |
|
*/ |
172 |
|
|
173 |
|
/** |
185 |
|
private static final long DEFAULT_SEED_GAMMA = 0xBD24B73A95FB84D9L; |
186 |
|
|
187 |
|
/** |
188 |
+ |
* The value 13 with 64bit sign bit set. Used in the signed |
189 |
+ |
* comparison in addGammaModGeorge. |
190 |
+ |
*/ |
191 |
+ |
private static final long BOTTOM13 = 0x800000000000000DL; |
192 |
+ |
|
193 |
+ |
/** |
194 |
|
* The least non-zero value returned by nextDouble(). This value |
195 |
|
* is scaled by a random value of 53 bits to produce a result. |
196 |
|
*/ |
200 |
|
* The next seed for default constructors. |
201 |
|
*/ |
202 |
|
private static final AtomicLong defaultSeedGenerator = |
203 |
< |
new AtomicLong(System.nanoTime()); |
203 |
> |
new AtomicLong(mix64(System.currentTimeMillis()) ^ |
204 |
> |
mix64(System.nanoTime())); |
205 |
|
|
206 |
|
/** |
207 |
|
* The seed, updated only via method nextSeed. |
229 |
|
* George < 2^64; thus we need only a conditional, not a loop, |
230 |
|
* to be sure of getting a representable value. |
231 |
|
* |
232 |
< |
* @param s a seed value |
232 |
> |
* Because Java comparison operators are signed, we implement this |
233 |
> |
* by conceptually offsetting seed values downwards by 2^63, so |
234 |
> |
* 0..13 is represented as Long.MIN_VALUE..BOTTOM13. |
235 |
> |
* |
236 |
> |
* @param s a seed value, viewed as a signed long |
237 |
|
* @param g a gamma value, 13 <= g (as unsigned) |
238 |
|
*/ |
239 |
|
private static long addGammaModGeorge(long s, long g) { |
240 |
|
long p = s + g; |
241 |
< |
if (Long.compareUnsigned(p, g) >= 0) |
226 |
< |
return p; |
227 |
< |
long q = p - 13L; |
228 |
< |
return (Long.compareUnsigned(p, 13L) >= 0) ? q : (q + g); |
241 |
> |
return (p >= s) ? p : ((p >= BOTTOM13) ? p : p + g) - 13L; |
242 |
|
} |
243 |
|
|
244 |
|
/** |
277 |
|
do { // ensure gamma >= 13, considered as an unsigned integer |
278 |
|
s = addGammaModGeorge(s, GAMMA_GAMMA); |
279 |
|
g = mix64(s); |
280 |
< |
} while (Long.compareUnsigned(g, 13L) < 0); |
280 |
> |
} while (g >= 0L && g < 13L); |
281 |
|
this.gamma = g; |
282 |
|
this.nextSplit = s; |
283 |
|
} |
416 |
|
/** |
417 |
|
* Creates a new SplittableRandom instance using the specified |
418 |
|
* initial seed. SplittableRandom instances created with the same |
419 |
< |
* seed generate identical sequences of values. |
419 |
> |
* seed in the same program generate identical sequences of values. |
420 |
|
* |
421 |
|
* @param seed the initial seed |
422 |
|
*/ |
468 |
|
* @param bound the bound on the random number to be returned. Must be |
469 |
|
* positive. |
470 |
|
* @return a pseudorandom {@code int} value between zero |
471 |
< |
* (inclusive) and the bound (exclusive). |
471 |
> |
* (inclusive) and the bound (exclusive) |
472 |
|
* @throws IllegalArgumentException if the bound is less than zero |
473 |
|
*/ |
474 |
|
public int nextInt(int bound) { |
495 |
|
* @param origin the least value returned |
496 |
|
* @param bound the upper bound (exclusive) |
497 |
|
* @return a pseudorandom {@code int} value between the origin |
498 |
< |
* (inclusive) and the bound (exclusive). |
498 |
> |
* (inclusive) and the bound (exclusive) |
499 |
|
* @throws IllegalArgumentException if {@code origin} is greater than |
500 |
|
* or equal to {@code bound} |
501 |
|
*/ |
521 |
|
* @param bound the bound on the random number to be returned. Must be |
522 |
|
* positive. |
523 |
|
* @return a pseudorandom {@code long} value between zero |
524 |
< |
* (inclusive) and the bound (exclusive). |
524 |
> |
* (inclusive) and the bound (exclusive) |
525 |
|
* @throws IllegalArgumentException if {@code bound} is less than zero |
526 |
|
*/ |
527 |
|
public long nextLong(long bound) { |
548 |
|
* @param origin the least value returned |
549 |
|
* @param bound the upper bound (exclusive) |
550 |
|
* @return a pseudorandom {@code long} value between the origin |
551 |
< |
* (inclusive) and the bound (exclusive). |
551 |
> |
* (inclusive) and the bound (exclusive) |
552 |
|
* @throws IllegalArgumentException if {@code origin} is greater than |
553 |
|
* or equal to {@code bound} |
554 |
|
*/ |
566 |
|
* (inclusive) and one (exclusive) |
567 |
|
*/ |
568 |
|
public double nextDouble() { |
569 |
< |
return (nextLong() >>> 11) * DOUBLE_UNIT; |
569 |
> |
return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT; |
570 |
|
} |
571 |
|
|
572 |
|
/** |
576 |
|
* @param bound the bound on the random number to be returned. Must be |
577 |
|
* positive. |
578 |
|
* @return a pseudorandom {@code double} value between zero |
579 |
< |
* (inclusive) and the bound (exclusive). |
579 |
> |
* (inclusive) and the bound (exclusive) |
580 |
|
* @throws IllegalArgumentException if {@code bound} is less than zero |
581 |
|
*/ |
582 |
|
public double nextDouble(double bound) { |
583 |
|
if (!(bound > 0.0)) |
584 |
|
throw new IllegalArgumentException("bound must be positive"); |
585 |
< |
double result = nextDouble() * bound; |
585 |
> |
double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound; |
586 |
|
return (result < bound) ? result : // correct for rounding |
587 |
|
Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); |
588 |
|
} |
594 |
|
* @param origin the least value returned |
595 |
|
* @param bound the upper bound |
596 |
|
* @return a pseudorandom {@code double} value between the origin |
597 |
< |
* (inclusive) and the bound (exclusive). |
597 |
> |
* (inclusive) and the bound (exclusive) |
598 |
|
* @throws IllegalArgumentException if {@code origin} is greater than |
599 |
|
* or equal to {@code bound} |
600 |
|
*/ |
604 |
|
return internalNextDouble(origin, bound); |
605 |
|
} |
606 |
|
|
607 |
+ |
/** |
608 |
+ |
* Returns a pseudorandom {@code boolean} value. |
609 |
+ |
* |
610 |
+ |
* @return a pseudorandom {@code boolean} value |
611 |
+ |
*/ |
612 |
+ |
public boolean nextBoolean() { |
613 |
+ |
return mix32(nextSeed()) < 0; |
614 |
+ |
} |
615 |
+ |
|
616 |
|
// stream methods, coded in a way intended to better isolate for |
617 |
|
// maintenance purposes the small differences across forms. |
618 |
|
|
636 |
|
|
637 |
|
/** |
638 |
|
* Returns an effectively unlimited stream of pseudorandom {@code int} |
639 |
< |
* values |
639 |
> |
* values. |
640 |
|
* |
641 |
|
* @implNote This method is implemented to be equivalent to {@code |
642 |
|
* ints(Long.MAX_VALUE)}. |
659 |
|
* @param randomNumberOrigin the origin of each random value |
660 |
|
* @param randomNumberBound the bound of each random value |
661 |
|
* @return a stream of pseudorandom {@code int} values, |
662 |
< |
* each with the given origin and bound. |
662 |
> |
* each with the given origin and bound |
663 |
|
* @throws IllegalArgumentException if {@code streamSize} is |
664 |
|
* less than zero, or {@code randomNumberOrigin} |
665 |
|
* is greater than or equal to {@code randomNumberBound} |
686 |
|
* @param randomNumberOrigin the origin of each random value |
687 |
|
* @param randomNumberBound the bound of each random value |
688 |
|
* @return a stream of pseudorandom {@code int} values, |
689 |
< |
* each with the given origin and bound. |
689 |
> |
* each with the given origin and bound |
690 |
|
* @throws IllegalArgumentException if {@code randomNumberOrigin} |
691 |
|
* is greater than or equal to {@code randomNumberBound} |
692 |
|
*/ |
742 |
|
* @param randomNumberOrigin the origin of each random value |
743 |
|
* @param randomNumberBound the bound of each random value |
744 |
|
* @return a stream of pseudorandom {@code long} values, |
745 |
< |
* each with the given origin and bound. |
745 |
> |
* each with the given origin and bound |
746 |
|
* @throws IllegalArgumentException if {@code streamSize} is |
747 |
|
* less than zero, or {@code randomNumberOrigin} |
748 |
|
* is greater than or equal to {@code randomNumberBound} |
769 |
|
* @param randomNumberOrigin the origin of each random value |
770 |
|
* @param randomNumberBound the bound of each random value |
771 |
|
* @return a stream of pseudorandom {@code long} values, |
772 |
< |
* each with the given origin and bound. |
772 |
> |
* each with the given origin and bound |
773 |
|
* @throws IllegalArgumentException if {@code randomNumberOrigin} |
774 |
|
* is greater than or equal to {@code randomNumberBound} |
775 |
|
*/ |
827 |
|
* @param randomNumberOrigin the origin of each random value |
828 |
|
* @param randomNumberBound the bound of each random value |
829 |
|
* @return a stream of pseudorandom {@code double} values, |
830 |
< |
* each with the given origin and bound. |
830 |
> |
* each with the given origin and bound |
831 |
|
* @throws IllegalArgumentException if {@code streamSize} is |
832 |
< |
* less than zero. |
832 |
> |
* less than zero |
833 |
|
* @throws IllegalArgumentException if {@code randomNumberOrigin} |
834 |
|
* is greater than or equal to {@code randomNumberBound} |
835 |
|
*/ |
855 |
|
* @param randomNumberOrigin the origin of each random value |
856 |
|
* @param randomNumberBound the bound of each random value |
857 |
|
* @return a stream of pseudorandom {@code double} values, |
858 |
< |
* each with the given origin and bound. |
858 |
> |
* each with the given origin and bound |
859 |
|
* @throws IllegalArgumentException if {@code randomNumberOrigin} |
860 |
|
* is greater than or equal to {@code randomNumberBound} |
861 |
|
*/ |
876 |
|
* approach. The long and double versions of this class are |
877 |
|
* identical except for types. |
878 |
|
*/ |
879 |
< |
static class RandomIntsSpliterator implements Spliterator.OfInt { |
879 |
> |
static final class RandomIntsSpliterator implements Spliterator.OfInt { |
880 |
|
final SplittableRandom rng; |
881 |
|
long index; |
882 |
|
final long fence; |
930 |
|
/** |
931 |
|
* Spliterator for long streams. |
932 |
|
*/ |
933 |
< |
static class RandomLongsSpliterator implements Spliterator.OfLong { |
933 |
> |
static final class RandomLongsSpliterator implements Spliterator.OfLong { |
934 |
|
final SplittableRandom rng; |
935 |
|
long index; |
936 |
|
final long fence; |
985 |
|
/** |
986 |
|
* Spliterator for double streams. |
987 |
|
*/ |
988 |
< |
static class RandomDoublesSpliterator implements Spliterator.OfDouble { |
988 |
> |
static final class RandomDoublesSpliterator implements Spliterator.OfDouble { |
989 |
|
final SplittableRandom rng; |
990 |
|
long index; |
991 |
|
final long fence; |