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 L64X128Random} implements |
36 * generate subtasks. Class {@link L64X128Random} 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 L64X128Random} objects, |
40 * as well as creating new split-off {@link L64X128Random} 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> |
130 * seed unless the {@linkplain System#getProperty system property} |
132 * seed unless the {@linkplain System#getProperty system property} |
131 * {@code java.util.secureRandomSeed} is set to {@code true}. |
133 * {@code java.util.secureRandomSeed} is set to {@code true}. |
132 * |
134 * |
133 * @since 14 |
135 * @since 14 |
134 */ |
136 */ |
135 public final class L64X128Random extends AbstractSplittableRNG { |
137 public final class L64X128Random extends AbstractSplittableGenerator { |
136 |
138 |
137 /* |
139 /* |
138 * Implementation Overview. |
140 * Implementation Overview. |
139 * |
141 * |
140 * The split operation uses the current generator to choose four new 64-bit |
142 * The split operation uses the current generator to choose four new 64-bit |
164 /* ---------------- static fields ---------------- */ |
166 /* ---------------- static fields ---------------- */ |
165 |
167 |
166 /** |
168 /** |
167 * The seed generator for default constructors. |
169 * The seed generator for default constructors. |
168 */ |
170 */ |
169 private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed()); |
171 private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed()); |
170 |
172 |
171 /* |
173 /* |
172 * The period of this generator, which is (2**128 - 1) * 2**64. |
174 * The period of this generator, which is (2**128 - 1) * 2**64. |
173 */ |
175 */ |
174 private static final BigInteger PERIOD = |
176 private static final BigInteger PERIOD = |
215 this.a = a | 1; |
217 this.a = a | 1; |
216 this.s = s; |
218 this.s = s; |
217 // If x0 and x1 are both zero, we must choose nonzero values. |
219 // If x0 and x1 are both zero, we must choose nonzero values. |
218 if ((x0 | x1) == 0) { |
220 if ((x0 | x1) == 0) { |
219 // At least one of the two values generated here will be nonzero. |
221 // At least one of the two values generated here will be nonzero. |
220 this.x0 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64); |
222 this.x0 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64); |
221 this.x1 = RNGSupport.mixStafford13(s + RNGSupport.GOLDEN_RATIO_64); |
223 this.x1 = RandomSupport.mixStafford13(s + RandomSupport.GOLDEN_RATIO_64); |
222 } |
224 } |
223 } |
225 } |
224 |
226 |
225 /** |
227 /** |
226 * Creates a new instance of {@link L64X128Random} using the |
228 * Creates a new instance of {@link L64X128Random} using the |
238 // The seed is hashed by mixMurmur64 to produce the `a` parameter. |
240 // The seed is hashed by mixMurmur64 to produce the `a` parameter. |
239 // The seed is hashed by mixStafford13 to produce the initial `x0`, |
241 // The seed is hashed by mixStafford13 to produce the initial `x0`, |
240 // which will then be used to produce the first generated value. |
242 // which will then be used to produce the first generated value. |
241 // Then x1 is filled in as if by a SplitMix PRNG with |
243 // Then x1 is filled in as if by a SplitMix PRNG with |
242 // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer. |
244 // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer. |
243 this(RNGSupport.mixMurmur64(seed ^= RNGSupport.SILVER_RATIO_64), |
245 this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), |
244 1, |
246 1, |
245 RNGSupport.mixStafford13(seed), |
247 RandomSupport.mixStafford13(seed), |
246 RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64)); |
248 RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); |
247 } |
249 } |
248 |
250 |
249 /** |
251 /** |
250 * Creates a new instance of {@link L64X128Random} that is likely to |
252 * Creates a new instance of {@link L64X128Random} that is likely to |
251 * generate sequences of values that are statistically independent |
253 * generate sequences of values that are statistically independent |
252 * of those of any other instances in the current program execution, |
254 * of those of any other instances in the current program execution, |
253 * but may, and typically does, vary across program invocations. |
255 * but may, and typically does, vary across program invocations. |
254 */ |
256 */ |
255 public L64X128Random() { |
257 public L64X128Random() { |
256 // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. |
258 // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. |
257 this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64)); |
259 this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); |
258 } |
260 } |
259 |
261 |
260 /** |
262 /** |
261 * Creates a new instance of {@link L64X128MixRandom} using the specified array of |
263 * Creates a new instance of {@link L64X128MixRandom} using the specified array of |
262 * initial seed bytes. Instances of {@link L64X128MixRandom} created with the same |
264 * initial seed bytes. Instances of {@link L64X128MixRandom} created with the same |
264 * |
266 * |
265 * @param seed the initial seed |
267 * @param seed the initial seed |
266 */ |
268 */ |
267 public L64X128Random(byte[] seed) { |
269 public L64X128Random(byte[] seed) { |
268 // Convert the seed to 4 long values, of which the last 2 are not all zero. |
270 // Convert the seed to 4 long values, of which the last 2 are not all zero. |
269 long[] data = RNGSupport.convertSeedBytesToLongs(seed, 4, 2); |
271 long[] data = RandomSupport.convertSeedBytesToLongs(seed, 4, 2); |
270 long a = data[0], s = data[1], x0 = data[2], x1 = data[3]; |
272 long a = data[0], s = data[1], x0 = data[2], x1 = data[3]; |
271 // Force a to be odd. |
273 // Force a to be odd. |
272 this.a = a | 1; |
274 this.a = a | 1; |
273 this.s = s; |
275 this.s = s; |
274 this.x0 = x0; |
276 this.x0 = x0; |
286 * a single {@link L64X128Random} object. Either or both of the two |
288 * a single {@link L64X128Random} object. Either or both of the two |
287 * objects may be further split using the {@code split} method, |
289 * objects may be further split using the {@code split} method, |
288 * and the same expected statistical properties apply to the |
290 * and the same expected statistical properties apply to the |
289 * entire set of generators constructed by such recursive splitting. |
291 * entire set of generators constructed by such recursive splitting. |
290 * |
292 * |
291 * @param source a {@link SplittableRNG} instance to be used instead |
293 * @param source a {@link SplittableGenerator} instance to be used instead |
292 * of this one as a source of pseudorandom bits used to |
294 * of this one as a source of pseudorandom bits used to |
293 * initialize the state of the new ones. |
295 * initialize the state of the new ones. |
294 * |
296 * |
295 * @return a new instance of {@link L64X128Random} |
297 * @return a new instance of {@link L64X128Random} |
296 */ |
298 */ |
297 public L64X128Random split(SplittableRNG source) { |
299 public L64X128Random split(SplittableGenerator source) { |
298 // Literally pick a new instance "at random". |
300 // Literally pick a new instance "at random". |
299 return new L64X128Random(source.nextLong(), source.nextLong(), |
301 return new L64X128Random(source.nextLong(), source.nextLong(), |
300 source.nextLong(), source.nextLong()); |
302 source.nextLong(), source.nextLong()); |
301 } |
303 } |
302 |
304 |