[cvs] / jsr166 / src / main / java / util / SplittableRandom.java Repository:
ViewVC logotype

Annotation of /jsr166/src/main/java/util/SplittableRandom.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.19 - (view) (download)

1 : dl 1.1 /*
2 :     * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
3 :     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 :     *
5 :     * This code is free software; you can redistribute it and/or modify it
6 :     * under the terms of the GNU General Public License version 2 only, as
7 :     * published by the Free Software Foundation. Oracle designates this
8 :     * particular file as subject to the "Classpath" exception as provided
9 :     * by Oracle in the LICENSE file that accompanied this code.
10 :     *
11 :     * This code is distributed in the hope that it will be useful, but WITHOUT
12 :     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 :     * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 :     * version 2 for more details (a copy is included in the LICENSE file that
15 :     * accompanied this code).
16 :     *
17 :     * You should have received a copy of the GNU General Public License version
18 :     * 2 along with this work; if not, write to the Free Software Foundation,
19 :     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 :     *
21 :     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 :     * or visit www.oracle.com if you need additional information or have any
23 :     * questions.
24 :     */
25 :    
26 :     package java.util;
27 :    
28 : dl 1.18 import java.security.SecureRandom;
29 : dl 1.15 import java.net.InetAddress;
30 : dl 1.1 import java.util.concurrent.atomic.AtomicLong;
31 :     import java.util.function.IntConsumer;
32 :     import java.util.function.LongConsumer;
33 :     import java.util.function.DoubleConsumer;
34 :     import java.util.stream.StreamSupport;
35 :     import java.util.stream.IntStream;
36 :     import java.util.stream.LongStream;
37 :     import java.util.stream.DoubleStream;
38 :    
39 :     /**
40 :     * A generator of uniform pseudorandom values applicable for use in
41 :     * (among other contexts) isolated parallel computations that may
42 : dl 1.18 * generate subtasks. Class {@code SplittableRandom} supports methods for
43 : jsr166 1.3 * producing pseudorandom numbers of type {@code int}, {@code long},
44 : dl 1.1 * and {@code double} with similar usages as for class
45 : jsr166 1.9 * {@link java.util.Random} but differs in the following ways:
46 :     *
47 :     * <ul>
48 : dl 1.1 *
49 :     * <li>Series of generated values pass the DieHarder suite testing
50 :     * independence and uniformity properties of random number generators.
51 :     * (Most recently validated with <a
52 :     * href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version
53 :     * 3.31.1</a>.) These tests validate only the methods for certain
54 :     * types and ranges, but similar properties are expected to hold, at
55 : dl 1.11 * least approximately, for others as well. The <em>period</em>
56 :     * (length of any series of generated values before it repeats) is at
57 :     * least 2<sup>64</sup>. </li>
58 : dl 1.1 *
59 :     * <li> Method {@link #split} constructs and returns a new
60 :     * SplittableRandom instance that shares no mutable state with the
61 : dl 1.7 * current instance. However, with very high probability, the
62 :     * values collectively generated by the two objects have the same
63 : dl 1.1 * statistical properties as if the same quantity of values were
64 :     * generated by a single thread using a single {@code
65 :     * SplittableRandom} object. </li>
66 :     *
67 :     * <li>Instances of SplittableRandom are <em>not</em> thread-safe.
68 :     * They are designed to be split, not shared, across threads. For
69 :     * example, a {@link java.util.concurrent.ForkJoinTask
70 :     * fork/join-style} computation using random numbers might include a
71 :     * construction of the form {@code new
72 :     * Subtask(aSplittableRandom.split()).fork()}.
73 :     *
74 :     * <li>This class provides additional methods for generating random
75 :     * streams, that employ the above techniques when used in {@code
76 :     * stream.parallel()} mode.</li>
77 :     *
78 :     * </ul>
79 :     *
80 : dl 1.18 * <p>Instances of {@code SplittableRandom} are not cryptographically
81 :     * secure. Consider instead using {@link java.security.SecureRandom}
82 :     * in security-sensitive applications. Additionally,
83 :     * default-constructed instances do not use a cryptographically random
84 :     * seed unless the {@linkplain System#getProperty system property}
85 :     * {@code java.util.secureRandomSeed} is set to {@code true}.
86 :     *
87 : dl 1.1 * @author Guy Steele
88 : dl 1.2 * @author Doug Lea
89 : dl 1.1 * @since 1.8
90 :     */
91 :     public class SplittableRandom {
92 :    
93 :     /*
94 :     * Implementation Overview.
95 :     *
96 :     * This algorithm was inspired by the "DotMix" algorithm by
97 :     * Leiserson, Schardl, and Sukha "Deterministic Parallel
98 :     * Random-Number Generation for Dynamic-Multithreading Platforms",
99 : dl 1.15 * PPoPP 2012, as well as those in "Parallel random numbers: as
100 :     * easy as 1, 2, 3" by Salmon, Morae, Dror, and Shaw, SC 2011. It
101 :     * differs mainly in simplifying and cheapening operations.
102 :     *
103 :     * The primary update step (method nextSeed()) is to add a
104 :     * constant ("gamma") to the current (64 bit) seed, forming a
105 :     * simple sequence. The seed and the gamma values for any two
106 :     * SplittableRandom instances are highly likely to be different.
107 :     *
108 :     * Methods nextLong, nextInt, and derivatives do not return the
109 :     * sequence (seed) values, but instead a hash-like bit-mix of
110 :     * their bits, producing more independently distributed sequences.
111 :     * For nextLong, the mix64 bit-mixing function computes the same
112 :     * value as the "64-bit finalizer" function in Austin Appleby's
113 :     * MurmurHash3 algorithm. See
114 : dl 1.1 * http://code.google.com/p/smhasher/wiki/MurmurHash3 , which
115 :     * comments: "The constants for the finalizers were generated by a
116 :     * simple simulated-annealing algorithm, and both avalanche all
117 : dl 1.15 * bits of 'h' to within 0.25% bias." The mix32 function is
118 :     * equivalent to (int)(mix64(seed) >>> 32), but faster because it
119 :     * omits a step that doesn't contribute to result.
120 :     *
121 :     * The split operation uses the current generator to form the seed
122 :     * and gamma for another SplittableRandom. To conservatively
123 :     * avoid potential correlations between seed and value generation,
124 :     * gamma selection (method nextGamma) uses the "Mix13" constants
125 :     * for MurmurHash3 described by David Stafford
126 :     * (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)
127 :     * To avoid potential weaknesses in bit-mixing transformations, we
128 :     * restrict gammas to odd values with at least 12 and no more than
129 :     * 52 bits set. Rather than rejecting candidates with too few or
130 :     * too many bits set, method nextGamma flips some bits (which has
131 :     * the effect of mapping at most 4 to any given gamma value).
132 :     * This reduces the effective set of 64bit odd gamma values by
133 :     * about 2<sup>14</sup>, a very tiny percentage, and serves as an
134 :     * automated screening for sequence constant selection that is
135 :     * left as an empirical decision in some other hashing and crypto
136 :     * algorithms.
137 :     *
138 :     * The resulting generator thus transforms a sequence in which
139 :     * (typically) many bits change on each step, with an inexpensive
140 :     * mixer with good (but less than cryptographically secure)
141 :     * avalanching.
142 :     *
143 :     * The default (no-argument) constructor, in essence, invokes
144 :     * split() for a common "seeder" SplittableRandom. Unlike other
145 :     * cases, this split must be performed in a thread-safe manner, so
146 :     * we use an AtomicLong to represent the seed rather than use an
147 :     * explicit SplittableRandom. To bootstrap the seeder, we start
148 : dl 1.18 * off using a seed based on current time and host unless the
149 :     * SecureRandomSeed property is set. This serves as a
150 :     * slimmed-down (and insecure) variant of SecureRandom that also
151 : dl 1.15 * avoids stalls that may occur when using /dev/random.
152 :     *
153 :     * It is a relatively simple matter to apply the basic design here
154 :     * to use 128 bit seeds. However, emulating 128bit arithmetic and
155 :     * carrying around twice the state add more overhead than appears
156 :     * warranted for current usages.
157 : dl 1.13 *
158 : dl 1.15 * File organization: First the non-public methods that constitute
159 :     * the main algorithm, then the main public methods, followed by
160 :     * some custom spliterator classes needed for stream methods.
161 : dl 1.1 */
162 :    
163 :     /**
164 : dl 1.15 * The initial gamma value for (unsplit) SplittableRandoms. Must
165 :     * be odd with at least 12 and no more than 52 bits set. Currently
166 :     * set to the golden ratio scaled to 64bits.
167 : dl 1.1 */
168 : dl 1.15 private static final long INITIAL_GAMMA = 0x9e3779b97f4a7c15L;
169 : dl 1.11
170 :     /**
171 : dl 1.5 * The least non-zero value returned by nextDouble(). This value
172 : dl 1.7 * is scaled by a random value of 53 bits to produce a result.
173 : dl 1.5 */
174 :     private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
175 :    
176 :     /**
177 : dl 1.15 * The seed. Updated only via method nextSeed.
178 : dl 1.1 */
179 :     private long seed;
180 :    
181 :     /**
182 : dl 1.15 * The step value.
183 : dl 1.1 */
184 :     private final long gamma;
185 :    
186 :     /**
187 : dl 1.15 * Internal constructor used by all others except default constructor.
188 : dl 1.1 */
189 : dl 1.15 private SplittableRandom(long seed, long gamma) {
190 :     this.seed = seed;
191 :     this.gamma = gamma;
192 : dl 1.1 }
193 :    
194 :     /**
195 : dl 1.15 * Computes MurmurHash3 64bit mix function.
196 : dl 1.1 */
197 :     private static long mix64(long z) {
198 : dl 1.15 z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
199 :     z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
200 :     return z ^ (z >>> 33);
201 : dl 1.1 }
202 :    
203 :     /**
204 : dl 1.15 * Returns the 32 high bits of mix64(z) as int.
205 : dl 1.1 */
206 :     private static int mix32(long z) {
207 : dl 1.15 z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
208 :     return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);
209 : dl 1.1 }
210 :    
211 :     /**
212 : dl 1.15 * Returns the gamma value to use for a new split instance.
213 : dl 1.13 */
214 : dl 1.15 private static long nextGamma(long z) {
215 :     z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L; // Stafford "Mix13"
216 : dl 1.14 z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
217 : dl 1.15 z = (z ^ (z >>> 31)) | 1L; // force to be odd
218 :     int n = Long.bitCount(z); // ensure enough 0 and 1 bits
219 :     return (n < 12 || n > 52) ? z ^ 0xaaaaaaaaaaaaaaaaL : z;
220 : dl 1.13 }
221 :    
222 :     /**
223 : dl 1.15 * Adds gamma to seed.
224 : dl 1.7 */
225 : dl 1.15 private long nextSeed() {
226 :     return seed += gamma;
227 : dl 1.7 }
228 :    
229 :     /**
230 : dl 1.15 * The seed generator for default constructors.
231 : dl 1.7 */
232 : dl 1.18 private static final AtomicLong seeder = new AtomicLong(initialSeed());
233 : dl 1.7
234 : dl 1.18 private static long initialSeed() {
235 :     try { // ignore exceptions in accessing/parsing properties
236 :     String pp = System.getProperty
237 :     ("java.util.secureRandomSeed");
238 :     if (pp != null && pp.equalsIgnoreCase("true")) {
239 :     byte[] seedBytes = java.security.SecureRandom.getSeed(8);
240 :     long s = (long)(seedBytes[0]) & 0xffL;
241 :     for (int i = 1; i < 8; ++i)
242 :     s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
243 :     return s;
244 :     }
245 :     } catch (Exception ignore) {
246 :     }
247 :     int hh = 0; // hashed host address
248 : jsr166 1.17 try {
249 : dl 1.18 hh = InetAddress.getLocalHost().hashCode();
250 :     } catch (Exception ignore) {
251 : jsr166 1.17 }
252 : dl 1.18 return (mix64((((long)hh) << 32) ^ System.currentTimeMillis()) ^
253 :     mix64(System.nanoTime()));
254 : dl 1.1 }
255 :    
256 : dl 1.15 // IllegalArgumentException messages
257 :     static final String BadBound = "bound must be positive";
258 :     static final String BadRange = "bound must be greater than origin";
259 :     static final String BadSize = "size must be non-negative";
260 : dl 1.12
261 : dl 1.1 /*
262 :     * Internal versions of nextX methods used by streams, as well as
263 :     * the public nextX(origin, bound) methods. These exist mainly to
264 :     * avoid the need for multiple versions of stream spliterators
265 :     * across the different exported forms of streams.
266 :     */
267 :    
268 :     /**
269 :     * The form of nextLong used by LongStream Spliterators. If
270 :     * origin is greater than bound, acts as unbounded form of
271 :     * nextLong, else as bounded form.
272 :     *
273 :     * @param origin the least value, unless greater than bound
274 :     * @param bound the upper bound (exclusive), must not equal origin
275 :     * @return a pseudorandom value
276 :     */
277 :     final long internalNextLong(long origin, long bound) {
278 :     /*
279 :     * Four Cases:
280 :     *
281 :     * 1. If the arguments indicate unbounded form, act as
282 :     * nextLong().
283 :     *
284 :     * 2. If the range is an exact power of two, apply the
285 :     * associated bit mask.
286 :     *
287 :     * 3. If the range is positive, loop to avoid potential bias
288 :     * when the implicit nextLong() bound (2<sup>64</sup>) is not
289 :     * evenly divisible by the range. The loop rejects candidates
290 :     * computed from otherwise over-represented values. The
291 :     * expected number of iterations under an ideal generator
292 : dl 1.4 * varies from 1 to 2, depending on the bound. The loop itself
293 :     * takes an unlovable form. Because the first candidate is
294 :     * already available, we need a break-in-the-middle
295 :     * construction, which is concisely but cryptically performed
296 :     * within the while-condition of a body-less for loop.
297 : dl 1.1 *
298 :     * 4. Otherwise, the range cannot be represented as a positive
299 : dl 1.4 * long. The loop repeatedly generates unbounded longs until
300 :     * obtaining a candidate meeting constraints (with an expected
301 :     * number of iterations of less than two).
302 : dl 1.1 */
303 :    
304 :     long r = mix64(nextSeed());
305 :     if (origin < bound) {
306 :     long n = bound - origin, m = n - 1;
307 : dl 1.7 if ((n & m) == 0L) // power of two
308 : dl 1.1 r = (r & m) + origin;
309 : dl 1.7 else if (n > 0L) { // reject over-represented candidates
310 : dl 1.1 for (long u = r >>> 1; // ensure nonnegative
311 : dl 1.7 u + m - (r = u % n) < 0L; // rejection check
312 : dl 1.1 u = mix64(nextSeed()) >>> 1) // retry
313 :     ;
314 :     r += origin;
315 :     }
316 : dl 1.7 else { // range not representable as long
317 : dl 1.1 while (r < origin || r >= bound)
318 :     r = mix64(nextSeed());
319 :     }
320 :     }
321 :     return r;
322 :     }
323 :    
324 :     /**
325 :     * The form of nextInt used by IntStream Spliterators.
326 :     * Exactly the same as long version, except for types.
327 :     *
328 :     * @param origin the least value, unless greater than bound
329 :     * @param bound the upper bound (exclusive), must not equal origin
330 :     * @return a pseudorandom value
331 :     */
332 :     final int internalNextInt(int origin, int bound) {
333 :     int r = mix32(nextSeed());
334 :     if (origin < bound) {
335 :     int n = bound - origin, m = n - 1;
336 : dl 1.13 if ((n & m) == 0)
337 : dl 1.1 r = (r & m) + origin;
338 :     else if (n > 0) {
339 :     for (int u = r >>> 1;
340 : dl 1.7 u + m - (r = u % n) < 0;
341 : dl 1.1 u = mix32(nextSeed()) >>> 1)
342 :     ;
343 :     r += origin;
344 :     }
345 :     else {
346 :     while (r < origin || r >= bound)
347 :     r = mix32(nextSeed());
348 :     }
349 :     }
350 :     return r;
351 :     }
352 :    
353 :     /**
354 :     * The form of nextDouble used by DoubleStream Spliterators.
355 :     *
356 :     * @param origin the least value, unless greater than bound
357 :     * @param bound the upper bound (exclusive), must not equal origin
358 :     * @return a pseudorandom value
359 :     */
360 :     final double internalNextDouble(double origin, double bound) {
361 : dl 1.5 double r = (nextLong() >>> 11) * DOUBLE_UNIT;
362 : dl 1.1 if (origin < bound) {
363 :     r = r * (bound - origin) + origin;
364 : dl 1.7 if (r >= bound) // correct for rounding
365 : dl 1.1 r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
366 :     }
367 :     return r;
368 :     }
369 :    
370 :     /* ---------------- public methods ---------------- */
371 :    
372 :     /**
373 : dl 1.7 * Creates a new SplittableRandom instance using the specified
374 :     * initial seed. SplittableRandom instances created with the same
375 : dl 1.11 * seed in the same program generate identical sequences of values.
376 : dl 1.1 *
377 :     * @param seed the initial seed
378 :     */
379 :     public SplittableRandom(long seed) {
380 : dl 1.15 this(seed, INITIAL_GAMMA);
381 : dl 1.1 }
382 :    
383 :     /**
384 :     * Creates a new SplittableRandom instance that is likely to
385 :     * generate sequences of values that are statistically independent
386 :     * of those of any other instances in the current program; and
387 :     * may, and typically does, vary across program invocations.
388 :     */
389 : dl 1.15 public SplittableRandom() { // emulate seeder.split()
390 :     this.gamma = nextGamma(this.seed = seeder.addAndGet(INITIAL_GAMMA));
391 : dl 1.1 }
392 :    
393 :     /**
394 :     * Constructs and returns a new SplittableRandom instance that
395 :     * shares no mutable state with this instance. However, with very
396 :     * high probability, the set of values collectively generated by
397 :     * the two objects has the same statistical properties as if the
398 :     * same quantity of values were generated by a single thread using
399 :     * a single SplittableRandom object. Either or both of the two
400 :     * objects may be further split using the {@code split()} method,
401 :     * and the same expected statistical properties apply to the
402 :     * entire set of generators constructed by such recursive
403 :     * splitting.
404 :     *
405 :     * @return the new SplittableRandom instance
406 :     */
407 :     public SplittableRandom split() {
408 : dl 1.15 long s = nextSeed();
409 :     return new SplittableRandom(s, nextGamma(s));
410 : dl 1.1 }
411 :    
412 :     /**
413 :     * Returns a pseudorandom {@code int} value.
414 :     *
415 : dl 1.7 * @return a pseudorandom {@code int} value
416 : dl 1.1 */
417 :     public int nextInt() {
418 :     return mix32(nextSeed());
419 :     }
420 :    
421 :     /**
422 : dl 1.7 * Returns a pseudorandom {@code int} value between zero (inclusive)
423 : dl 1.1 * and the specified bound (exclusive).
424 :     *
425 : dl 1.18 * @param bound the upper bound (exclusive). Must be positive.
426 : dl 1.7 * @return a pseudorandom {@code int} value between zero
427 : jsr166 1.10 * (inclusive) and the bound (exclusive)
428 : dl 1.16 * @throws IllegalArgumentException if {@code bound} is not positive
429 : dl 1.1 */
430 :     public int nextInt(int bound) {
431 :     if (bound <= 0)
432 : dl 1.15 throw new IllegalArgumentException(BadBound);
433 : dl 1.1 // Specialize internalNextInt for origin 0
434 :     int r = mix32(nextSeed());
435 :     int m = bound - 1;
436 : dl 1.13 if ((bound & m) == 0) // power of two
437 : dl 1.1 r &= m;
438 :     else { // reject over-represented candidates
439 :     for (int u = r >>> 1;
440 : dl 1.7 u + m - (r = u % bound) < 0;
441 : dl 1.1 u = mix32(nextSeed()) >>> 1)
442 :     ;
443 :     }
444 :     return r;
445 :     }
446 :    
447 :     /**
448 :     * Returns a pseudorandom {@code int} value between the specified
449 :     * origin (inclusive) and the specified bound (exclusive).
450 :     *
451 :     * @param origin the least value returned
452 :     * @param bound the upper bound (exclusive)
453 :     * @return a pseudorandom {@code int} value between the origin
454 : jsr166 1.10 * (inclusive) and the bound (exclusive)
455 : dl 1.7 * @throws IllegalArgumentException if {@code origin} is greater than
456 : dl 1.1 * or equal to {@code bound}
457 :     */
458 :     public int nextInt(int origin, int bound) {
459 :     if (origin >= bound)
460 : dl 1.15 throw new IllegalArgumentException(BadRange);
461 : dl 1.1 return internalNextInt(origin, bound);
462 :     }
463 :    
464 :     /**
465 :     * Returns a pseudorandom {@code long} value.
466 :     *
467 : dl 1.7 * @return a pseudorandom {@code long} value
468 : dl 1.1 */
469 :     public long nextLong() {
470 :     return mix64(nextSeed());
471 :     }
472 :    
473 :     /**
474 : dl 1.7 * Returns a pseudorandom {@code long} value between zero (inclusive)
475 : dl 1.1 * and the specified bound (exclusive).
476 :     *
477 : dl 1.18 * @param bound the upper bound (exclusive). Must be positive.
478 : dl 1.7 * @return a pseudorandom {@code long} value between zero
479 : jsr166 1.10 * (inclusive) and the bound (exclusive)
480 : dl 1.16 * @throws IllegalArgumentException if {@code bound} is not positive
481 : dl 1.1 */
482 :     public long nextLong(long bound) {
483 :     if (bound <= 0)
484 : dl 1.15 throw new IllegalArgumentException(BadBound);
485 : dl 1.1 // Specialize internalNextLong for origin 0
486 :     long r = mix64(nextSeed());
487 :     long m = bound - 1;
488 :     if ((bound & m) == 0L) // power of two
489 :     r &= m;
490 :     else { // reject over-represented candidates
491 :     for (long u = r >>> 1;
492 :     u + m - (r = u % bound) < 0L;
493 :     u = mix64(nextSeed()) >>> 1)
494 :     ;
495 :     }
496 :     return r;
497 :     }
498 :    
499 :     /**
500 :     * Returns a pseudorandom {@code long} value between the specified
501 :     * origin (inclusive) and the specified bound (exclusive).
502 :     *
503 :     * @param origin the least value returned
504 :     * @param bound the upper bound (exclusive)
505 :     * @return a pseudorandom {@code long} value between the origin
506 : jsr166 1.10 * (inclusive) and the bound (exclusive)
507 : dl 1.7 * @throws IllegalArgumentException if {@code origin} is greater than
508 : dl 1.1 * or equal to {@code bound}
509 :     */
510 :     public long nextLong(long origin, long bound) {
511 :     if (origin >= bound)
512 : dl 1.15 throw new IllegalArgumentException(BadRange);
513 : dl 1.1 return internalNextLong(origin, bound);
514 :     }
515 :    
516 :     /**
517 : dl 1.7 * Returns a pseudorandom {@code double} value between zero
518 :     * (inclusive) and one (exclusive).
519 : dl 1.1 *
520 : dl 1.7 * @return a pseudorandom {@code double} value between zero
521 : dl 1.18 * (inclusive) and one (exclusive)
522 : dl 1.1 */
523 :     public double nextDouble() {
524 : dl 1.11 return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
525 : dl 1.1 }
526 :    
527 :     /**
528 :     * Returns a pseudorandom {@code double} value between 0.0
529 :     * (inclusive) and the specified bound (exclusive).
530 :     *
531 : dl 1.18 * @param bound the upper bound (exclusive). Must be positive.
532 : dl 1.7 * @return a pseudorandom {@code double} value between zero
533 : jsr166 1.10 * (inclusive) and the bound (exclusive)
534 : dl 1.16 * @throws IllegalArgumentException if {@code bound} is not positive
535 : dl 1.1 */
536 :     public double nextDouble(double bound) {
537 : dl 1.7 if (!(bound > 0.0))
538 : dl 1.15 throw new IllegalArgumentException(BadBound);
539 : dl 1.11 double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
540 : dl 1.1 return (result < bound) ? result : // correct for rounding
541 :     Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
542 :     }
543 :    
544 :     /**
545 : dl 1.7 * Returns a pseudorandom {@code double} value between the specified
546 : dl 1.1 * origin (inclusive) and bound (exclusive).
547 :     *
548 :     * @param origin the least value returned
549 : dl 1.18 * @param bound the upper bound (exclusive)
550 : dl 1.1 * @return a pseudorandom {@code double} value between the origin
551 : jsr166 1.10 * (inclusive) and the bound (exclusive)
552 : dl 1.1 * @throws IllegalArgumentException if {@code origin} is greater than
553 :     * or equal to {@code bound}
554 :     */
555 :     public double nextDouble(double origin, double bound) {
556 : dl 1.7 if (!(origin < bound))
557 : dl 1.15 throw new IllegalArgumentException(BadRange);
558 : dl 1.1 return internalNextDouble(origin, bound);
559 :     }
560 :    
561 : dl 1.11 /**
562 :     * Returns a pseudorandom {@code boolean} value.
563 :     *
564 :     * @return a pseudorandom {@code boolean} value
565 :     */
566 :     public boolean nextBoolean() {
567 :     return mix32(nextSeed()) < 0;
568 :     }
569 :    
570 : dl 1.1 // stream methods, coded in a way intended to better isolate for
571 :     // maintenance purposes the small differences across forms.
572 :    
573 :     /**
574 : dl 1.16 * Returns a stream producing the given {@code streamSize} number
575 :     * of pseudorandom {@code int} values from this generator and/or
576 :     * one split from it.
577 : dl 1.1 *
578 :     * @param streamSize the number of values to generate
579 :     * @return a stream of pseudorandom {@code int} values
580 :     * @throws IllegalArgumentException if {@code streamSize} is
581 : dl 1.7 * less than zero
582 : dl 1.1 */
583 :     public IntStream ints(long streamSize) {
584 :     if (streamSize < 0L)
585 : dl 1.15 throw new IllegalArgumentException(BadSize);
586 : dl 1.1 return StreamSupport.intStream
587 :     (new RandomIntsSpliterator
588 :     (this, 0L, streamSize, Integer.MAX_VALUE, 0),
589 :     false);
590 :     }
591 :    
592 :     /**
593 :     * Returns an effectively unlimited stream of pseudorandom {@code int}
594 : dl 1.16 * values from this generator and/or one split from it.
595 : dl 1.1 *
596 :     * @implNote This method is implemented to be equivalent to {@code
597 :     * ints(Long.MAX_VALUE)}.
598 :     *
599 :     * @return a stream of pseudorandom {@code int} values
600 :     */
601 :     public IntStream ints() {
602 :     return StreamSupport.intStream
603 :     (new RandomIntsSpliterator
604 :     (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
605 :     false);
606 :     }
607 :    
608 :     /**
609 : dl 1.16 * Returns a stream producing the given {@code streamSize} number
610 : dl 1.18 * of pseudorandom {@code int} values from this generator and/or one split
611 :     * from it; each value conforms to the given origin (inclusive) and bound
612 :     * (exclusive).
613 : dl 1.1 *
614 :     * @param streamSize the number of values to generate
615 : dl 1.18 * @param randomNumberOrigin the origin (inclusive) of each random value
616 :     * @param randomNumberBound the bound (exclusive) of each random value
617 : dl 1.1 * @return a stream of pseudorandom {@code int} values,
618 : dl 1.18 * each with the given origin (inclusive) and bound (exclusive)
619 : dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
620 : dl 1.7 * less than zero, or {@code randomNumberOrigin}
621 : dl 1.1 * is greater than or equal to {@code randomNumberBound}
622 :     */
623 :     public IntStream ints(long streamSize, int randomNumberOrigin,
624 :     int randomNumberBound) {
625 :     if (streamSize < 0L)
626 : dl 1.15 throw new IllegalArgumentException(BadSize);
627 : dl 1.1 if (randomNumberOrigin >= randomNumberBound)
628 : dl 1.15 throw new IllegalArgumentException(BadRange);
629 : dl 1.1 return StreamSupport.intStream
630 :     (new RandomIntsSpliterator
631 :     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
632 :     false);
633 :     }
634 :    
635 :     /**
636 :     * Returns an effectively unlimited stream of pseudorandom {@code
637 : dl 1.18 * int} values from this generator and/or one split from it; each value
638 :     * conforms to the given origin (inclusive) and bound (exclusive).
639 : dl 1.1 *
640 :     * @implNote This method is implemented to be equivalent to {@code
641 :     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
642 :     *
643 : dl 1.18 * @param randomNumberOrigin the origin (inclusive) of each random value
644 :     * @param randomNumberBound the bound (exclusive) of each random value
645 : dl 1.1 * @return a stream of pseudorandom {@code int} values,
646 : dl 1.18 * each with the given origin (inclusive) and bound (exclusive)
647 : dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
648 :     * is greater than or equal to {@code randomNumberBound}
649 :     */
650 :     public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
651 :     if (randomNumberOrigin >= randomNumberBound)
652 : dl 1.15 throw new IllegalArgumentException(BadRange);
653 : dl 1.1 return StreamSupport.intStream
654 :     (new RandomIntsSpliterator
655 :     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
656 :     false);
657 :     }
658 :    
659 :     /**
660 : dl 1.16 * Returns a stream producing the given {@code streamSize} number
661 :     * of pseudorandom {@code long} values from this generator and/or
662 :     * one split from it.
663 : dl 1.1 *
664 :     * @param streamSize the number of values to generate
665 : dl 1.7 * @return a stream of pseudorandom {@code long} values
666 : dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
667 : dl 1.7 * less than zero
668 : dl 1.1 */
669 :     public LongStream longs(long streamSize) {
670 :     if (streamSize < 0L)
671 : dl 1.15 throw new IllegalArgumentException(BadSize);
672 : dl 1.1 return StreamSupport.longStream
673 :     (new RandomLongsSpliterator
674 :     (this, 0L, streamSize, Long.MAX_VALUE, 0L),
675 :     false);
676 :     }
677 :    
678 :     /**
679 : dl 1.16 * Returns an effectively unlimited stream of pseudorandom {@code
680 :     * long} values from this generator and/or one split from it.
681 : dl 1.1 *
682 :     * @implNote This method is implemented to be equivalent to {@code
683 :     * longs(Long.MAX_VALUE)}.
684 :     *
685 :     * @return a stream of pseudorandom {@code long} values
686 :     */
687 :     public LongStream longs() {
688 :     return StreamSupport.longStream
689 :     (new RandomLongsSpliterator
690 :     (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
691 :     false);
692 :     }
693 :    
694 :     /**
695 : dl 1.7 * Returns a stream producing the given {@code streamSize} number of
696 : dl 1.18 * pseudorandom {@code long} values from this generator and/or one split
697 :     * from it; each value conforms to the given origin (inclusive) and bound
698 :     * (exclusive).
699 : dl 1.1 *
700 :     * @param streamSize the number of values to generate
701 : dl 1.18 * @param randomNumberOrigin the origin (inclusive) of each random value
702 :     * @param randomNumberBound the bound (exclusive) of each random value
703 : dl 1.1 * @return a stream of pseudorandom {@code long} values,
704 : dl 1.18 * each with the given origin (inclusive) and bound (exclusive)
705 : dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
706 : dl 1.7 * less than zero, or {@code randomNumberOrigin}
707 : dl 1.1 * is greater than or equal to {@code randomNumberBound}
708 :     */
709 :     public LongStream longs(long streamSize, long randomNumberOrigin,
710 :     long randomNumberBound) {
711 :     if (streamSize < 0L)
712 : dl 1.15 throw new IllegalArgumentException(BadSize);
713 : dl 1.1 if (randomNumberOrigin >= randomNumberBound)
714 : dl 1.15 throw new IllegalArgumentException(BadRange);
715 : dl 1.1 return StreamSupport.longStream
716 :     (new RandomLongsSpliterator
717 :     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
718 :     false);
719 :     }
720 :    
721 :     /**
722 :     * Returns an effectively unlimited stream of pseudorandom {@code
723 : dl 1.18 * long} values from this generator and/or one split from it; each value
724 :     * conforms to the given origin (inclusive) and bound (exclusive).
725 : dl 1.1 *
726 :     * @implNote This method is implemented to be equivalent to {@code
727 :     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
728 :     *
729 : dl 1.18 * @param randomNumberOrigin the origin (inclusive) of each random value
730 :     * @param randomNumberBound the bound (exclusive) of each random value
731 : dl 1.1 * @return a stream of pseudorandom {@code long} values,
732 : dl 1.18 * each with the given origin (inclusive) and bound (exclusive)
733 : dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
734 :     * is greater than or equal to {@code randomNumberBound}
735 :     */
736 :     public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
737 :     if (randomNumberOrigin >= randomNumberBound)
738 : dl 1.15 throw new IllegalArgumentException(BadRange);
739 : dl 1.1 return StreamSupport.longStream
740 :     (new RandomLongsSpliterator
741 :     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
742 :     false);
743 :     }
744 :    
745 :     /**
746 : dl 1.7 * Returns a stream producing the given {@code streamSize} number of
747 : dl 1.18 * pseudorandom {@code double} values from this generator and/or one split
748 :     * from it; each value is between zero (inclusive) and one (exclusive).
749 : dl 1.1 *
750 :     * @param streamSize the number of values to generate
751 :     * @return a stream of {@code double} values
752 :     * @throws IllegalArgumentException if {@code streamSize} is
753 : dl 1.7 * less than zero
754 : dl 1.1 */
755 :     public DoubleStream doubles(long streamSize) {
756 :     if (streamSize < 0L)
757 : dl 1.15 throw new IllegalArgumentException(BadSize);
758 : dl 1.1 return StreamSupport.doubleStream
759 :     (new RandomDoublesSpliterator
760 :     (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
761 :     false);
762 :     }
763 :    
764 :     /**
765 :     * Returns an effectively unlimited stream of pseudorandom {@code
766 : dl 1.18 * double} values from this generator and/or one split from it; each value
767 :     * is between zero (inclusive) and one (exclusive).
768 : dl 1.1 *
769 :     * @implNote This method is implemented to be equivalent to {@code
770 :     * doubles(Long.MAX_VALUE)}.
771 :     *
772 :     * @return a stream of pseudorandom {@code double} values
773 :     */
774 :     public DoubleStream doubles() {
775 :     return StreamSupport.doubleStream
776 :     (new RandomDoublesSpliterator
777 :     (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
778 :     false);
779 :     }
780 :    
781 :     /**
782 : dl 1.7 * Returns a stream producing the given {@code streamSize} number of
783 : dl 1.18 * pseudorandom {@code double} values from this generator and/or one split
784 :     * from it; each value conforms to the given origin (inclusive) and bound
785 :     * (exclusive).
786 : dl 1.1 *
787 :     * @param streamSize the number of values to generate
788 : dl 1.18 * @param randomNumberOrigin the origin (inclusive) of each random value
789 :     * @param randomNumberBound the bound (exclusive) of each random value
790 : dl 1.1 * @return a stream of pseudorandom {@code double} values,
791 : dl 1.18 * each with the given origin (inclusive) and bound (exclusive)
792 : dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
793 : dl 1.18 * less than zero
794 : dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
795 :     * is greater than or equal to {@code randomNumberBound}
796 :     */
797 :     public DoubleStream doubles(long streamSize, double randomNumberOrigin,
798 :     double randomNumberBound) {
799 :     if (streamSize < 0L)
800 : dl 1.15 throw new IllegalArgumentException(BadSize);
801 : dl 1.7 if (!(randomNumberOrigin < randomNumberBound))
802 : dl 1.15 throw new IllegalArgumentException(BadRange);
803 : dl 1.1 return StreamSupport.doubleStream
804 :     (new RandomDoublesSpliterator
805 :     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
806 :     false);
807 :     }
808 :    
809 :     /**
810 :     * Returns an effectively unlimited stream of pseudorandom {@code
811 : dl 1.18 * double} values from this generator and/or one split from it; each value
812 :     * conforms to the given origin (inclusive) and bound (exclusive).
813 : dl 1.1 *
814 :     * @implNote This method is implemented to be equivalent to {@code
815 :     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
816 :     *
817 : dl 1.18 * @param randomNumberOrigin the origin (inclusive) of each random value
818 :     * @param randomNumberBound the bound (exclusive) of each random value
819 : dl 1.1 * @return a stream of pseudorandom {@code double} values,
820 : dl 1.18 * each with the given origin (inclusive) and bound (exclusive)
821 : dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
822 :     * is greater than or equal to {@code randomNumberBound}
823 :     */
824 :     public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
825 : dl 1.7 if (!(randomNumberOrigin < randomNumberBound))
826 : dl 1.15 throw new IllegalArgumentException(BadRange);
827 : dl 1.1 return StreamSupport.doubleStream
828 :     (new RandomDoublesSpliterator
829 :     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
830 :     false);
831 :     }
832 :    
833 :     /**
834 :     * Spliterator for int streams. We multiplex the four int
835 : dl 1.7 * versions into one class by treating a bound less than origin as
836 : dl 1.1 * unbounded, and also by treating "infinite" as equivalent to
837 :     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
838 :     * approach. The long and double versions of this class are
839 :     * identical except for types.
840 :     */
841 : dl 1.11 static final class RandomIntsSpliterator implements Spliterator.OfInt {
842 : dl 1.1 final SplittableRandom rng;
843 :     long index;
844 :     final long fence;
845 :     final int origin;
846 :     final int bound;
847 :     RandomIntsSpliterator(SplittableRandom rng, long index, long fence,
848 :     int origin, int bound) {
849 :     this.rng = rng; this.index = index; this.fence = fence;
850 :     this.origin = origin; this.bound = bound;
851 :     }
852 :    
853 :     public RandomIntsSpliterator trySplit() {
854 :     long i = index, m = (i + fence) >>> 1;
855 :     return (m <= i) ? null :
856 :     new RandomIntsSpliterator(rng.split(), i, index = m, origin, bound);
857 :     }
858 :    
859 :     public long estimateSize() {
860 :     return fence - index;
861 :     }
862 :    
863 :     public int characteristics() {
864 :     return (Spliterator.SIZED | Spliterator.SUBSIZED |
865 : dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
866 : dl 1.1 }
867 :    
868 :     public boolean tryAdvance(IntConsumer consumer) {
869 :     if (consumer == null) throw new NullPointerException();
870 :     long i = index, f = fence;
871 :     if (i < f) {
872 :     consumer.accept(rng.internalNextInt(origin, bound));
873 :     index = i + 1;
874 :     return true;
875 :     }
876 :     return false;
877 :     }
878 :    
879 :     public void forEachRemaining(IntConsumer consumer) {
880 :     if (consumer == null) throw new NullPointerException();
881 :     long i = index, f = fence;
882 :     if (i < f) {
883 :     index = f;
884 : dl 1.15 SplittableRandom r = rng;
885 : dl 1.1 int o = origin, b = bound;
886 :     do {
887 : dl 1.15 consumer.accept(r.internalNextInt(o, b));
888 : dl 1.1 } while (++i < f);
889 :     }
890 :     }
891 :     }
892 :    
893 :     /**
894 :     * Spliterator for long streams.
895 :     */
896 : dl 1.11 static final class RandomLongsSpliterator implements Spliterator.OfLong {
897 : dl 1.1 final SplittableRandom rng;
898 :     long index;
899 :     final long fence;
900 :     final long origin;
901 :     final long bound;
902 :     RandomLongsSpliterator(SplittableRandom rng, long index, long fence,
903 :     long origin, long bound) {
904 :     this.rng = rng; this.index = index; this.fence = fence;
905 :     this.origin = origin; this.bound = bound;
906 :     }
907 :    
908 :     public RandomLongsSpliterator trySplit() {
909 :     long i = index, m = (i + fence) >>> 1;
910 :     return (m <= i) ? null :
911 :     new RandomLongsSpliterator(rng.split(), i, index = m, origin, bound);
912 :     }
913 :    
914 :     public long estimateSize() {
915 :     return fence - index;
916 :     }
917 :    
918 :     public int characteristics() {
919 :     return (Spliterator.SIZED | Spliterator.SUBSIZED |
920 : dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
921 : dl 1.1 }
922 :    
923 :     public boolean tryAdvance(LongConsumer consumer) {
924 :     if (consumer == null) throw new NullPointerException();
925 :     long i = index, f = fence;
926 :     if (i < f) {
927 :     consumer.accept(rng.internalNextLong(origin, bound));
928 :     index = i + 1;
929 :     return true;
930 :     }
931 :     return false;
932 :     }
933 :    
934 :     public void forEachRemaining(LongConsumer consumer) {
935 :     if (consumer == null) throw new NullPointerException();
936 :     long i = index, f = fence;
937 :     if (i < f) {
938 :     index = f;
939 : dl 1.15 SplittableRandom r = rng;
940 : dl 1.1 long o = origin, b = bound;
941 :     do {
942 : dl 1.15 consumer.accept(r.internalNextLong(o, b));
943 : dl 1.1 } while (++i < f);
944 :     }
945 :     }
946 :    
947 :     }
948 :    
949 :     /**
950 :     * Spliterator for double streams.
951 :     */
952 : dl 1.11 static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
953 : dl 1.1 final SplittableRandom rng;
954 :     long index;
955 :     final long fence;
956 :     final double origin;
957 :     final double bound;
958 :     RandomDoublesSpliterator(SplittableRandom rng, long index, long fence,
959 :     double origin, double bound) {
960 :     this.rng = rng; this.index = index; this.fence = fence;
961 :     this.origin = origin; this.bound = bound;
962 :     }
963 :    
964 :     public RandomDoublesSpliterator trySplit() {
965 :     long i = index, m = (i + fence) >>> 1;
966 :     return (m <= i) ? null :
967 :     new RandomDoublesSpliterator(rng.split(), i, index = m, origin, bound);
968 :     }
969 :    
970 :     public long estimateSize() {
971 :     return fence - index;
972 :     }
973 :    
974 :     public int characteristics() {
975 :     return (Spliterator.SIZED | Spliterator.SUBSIZED |
976 : dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
977 : dl 1.1 }
978 :    
979 :     public boolean tryAdvance(DoubleConsumer consumer) {
980 :     if (consumer == null) throw new NullPointerException();
981 :     long i = index, f = fence;
982 :     if (i < f) {
983 :     consumer.accept(rng.internalNextDouble(origin, bound));
984 :     index = i + 1;
985 :     return true;
986 :     }
987 :     return false;
988 :     }
989 :    
990 :     public void forEachRemaining(DoubleConsumer consumer) {
991 :     if (consumer == null) throw new NullPointerException();
992 :     long i = index, f = fence;
993 :     if (i < f) {
994 :     index = f;
995 : dl 1.15 SplittableRandom r = rng;
996 : dl 1.1 double o = origin, b = bound;
997 :     do {
998 : dl 1.15 consumer.accept(r.internalNextDouble(o, b));
999 : dl 1.1 } while (++i < f);
1000 :     }
1001 :     }
1002 :     }
1003 :    
1004 :     }

Doug Lea
ViewVC Help
Powered by ViewVC 1.0.8