25 |
25 |
26 package java.util.random; |
26 package java.util.random; |
27 |
27 |
28 import java.math.BigInteger; |
28 import java.math.BigInteger; |
29 import java.util.concurrent.atomic.AtomicLong; |
29 import java.util.concurrent.atomic.AtomicLong; |
|
30 import java.util.random.RandomGenerator.SplittableGenerator; |
|
31 import java.util.random.RandomSupport.AbstractSplittableGenerator; |
30 |
32 |
31 /** |
33 /** |
32 * A generator of uniform pseudorandom values applicable for use in |
34 * A generator of uniform pseudorandom values applicable for use in |
33 * (among other contexts) isolated parallel computations that may |
35 * (among other contexts) isolated parallel computations that may |
34 * generate subtasks. Class {@link L64X1024MixRandom} implements |
36 * generate subtasks. Class {@link L64X1024MixRandom} implements |
35 * interfaces {@link RandomNumberGenerator} and {@link SplittableRNG}, |
37 * interfaces {@link RandomGenerator} and {@link SplittableGenerator}, |
36 * and therefore supports methods for producing pseudorandomly chosen |
38 * and therefore supports methods for producing pseudorandomly chosen |
37 * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} |
39 * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} |
38 * as well as creating new split-off {@link L64X1024MixRandom} objects, |
40 * as well as creating new split-off {@link L64X1024MixRandom} objects, |
39 * with similar usages as for class {@link java.util.SplittableRandom}. |
41 * with similar usages as for class {@link java.util.SplittableRandom}. |
40 * <p> |
42 * <p> |
285 // The seed is hashed by mixMurmur64 to produce the `a` parameter. |
287 // The seed is hashed by mixMurmur64 to produce the `a` parameter. |
286 // The seed is hashed by mixStafford13 to produce the initial `x[0]`, |
288 // The seed is hashed by mixStafford13 to produce the initial `x[0]`, |
287 // which will then be used to produce the first generated value. |
289 // which will then be used to produce the first generated value. |
288 // The other x values are filled in as if by a SplitMix PRNG with |
290 // The other x values are filled in as if by a SplitMix PRNG with |
289 // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer. |
291 // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer. |
290 this(RNGSupport.mixMurmur64(seed ^= RNGSupport.SILVER_RATIO_64), |
292 this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), |
291 1, |
293 1, |
292 RNGSupport.mixStafford13(seed), |
294 RandomSupport.mixStafford13(seed), |
293 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
295 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
294 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
296 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
295 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
297 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
296 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
298 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
297 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
299 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
298 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
300 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
299 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
301 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
300 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
302 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
301 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
303 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
302 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
304 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
303 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
305 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
304 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
306 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
305 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
307 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
306 RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64), |
308 RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), |
307 RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64)); |
309 RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); |
308 } |
310 } |
309 |
311 |
310 /** |
312 /** |
311 * Creates a new instance of {@link L64X1024MixRandom} that is likely to |
313 * Creates a new instance of {@link L64X1024MixRandom} that is likely to |
312 * generate sequences of values that are statistically independent |
314 * generate sequences of values that are statistically independent |
313 * of those of any other instances in the current program execution, |
315 * of those of any other instances in the current program execution, |
314 * but may, and typically does, vary across program invocations. |
316 * but may, and typically does, vary across program invocations. |
315 */ |
317 */ |
316 public L64X1024MixRandom() { |
318 public L64X1024MixRandom() { |
317 // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. |
319 // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. |
318 this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64)); |
320 this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); |
319 } |
321 } |
320 |
322 |
321 /** |
323 /** |
322 * Creates a new instance of {@link L64X1024MixRandom} using the specified array of |
324 * Creates a new instance of {@link L64X1024MixRandom} using the specified array of |
323 * initial seed bytes. Instances of {@link L64X1024MixRandom} created with the same |
325 * initial seed bytes. Instances of {@link L64X1024MixRandom} created with the same |
349 * a single {@link L64X1024MixRandom} object. Either or both of the two |
351 * a single {@link L64X1024MixRandom} object. Either or both of the two |
350 * objects may be further split using the {@code split} method, |
352 * objects may be further split using the {@code split} method, |
351 * and the same expected statistical properties apply to the |
353 * and the same expected statistical properties apply to the |
352 * entire set of generators constructed by such recursive splitting. |
354 * entire set of generators constructed by such recursive splitting. |
353 * |
355 * |
354 * @param source a {@link SplittableRNG} instance to be used instead |
356 * @param source a {@link SplittableGenerator} instance to be used instead |
355 * of this one as a source of pseudorandom bits used to |
357 * of this one as a source of pseudorandom bits used to |
356 * initialize the state of the new ones. |
358 * initialize the state of the new ones. |
357 * @return a new instance of {@link L64X1024MixRandom} |
359 * @return a new instance of {@link L64X1024MixRandom} |
358 */ |
360 */ |
359 public L64X1024MixRandom split(SplittableRNG source) { |
361 public L64X1024MixRandom split(SplittableGenerator source) { |
360 // Literally pick a new instance "at random". |
362 // Literally pick a new instance "at random". |
361 return new L64X1024MixRandom(source.nextLong(), source.nextLong(), |
363 return new L64X1024MixRandom(source.nextLong(), source.nextLong(), |
362 source.nextLong(), source.nextLong(), |
364 source.nextLong(), source.nextLong(), |
363 source.nextLong(), source.nextLong(), |
365 source.nextLong(), source.nextLong(), |
364 source.nextLong(), source.nextLong(), |
366 source.nextLong(), source.nextLong(), |