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

Doug Lea
ViewVC Help
Powered by ViewVC 1.0.8