|
1 /* |
|
2 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. |
|
3 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. |
|
4 * |
|
5 * |
|
6 * |
|
7 * |
|
8 * |
|
9 * |
|
10 * |
|
11 * |
|
12 * |
|
13 * |
|
14 * |
|
15 * |
|
16 * |
|
17 * |
|
18 * |
|
19 * |
|
20 * |
|
21 * |
|
22 * |
|
23 * |
|
24 */ |
|
25 // package java.util; |
|
26 |
|
27 import java.util.stream.Stream; |
|
28 import java.util.stream.StreamSupport; |
|
29 |
|
30 /** |
|
31 * This interface is designed to provide a common protocol for objects |
|
32 * that generate sequences of pseudorandom numbers (or Boolean values) |
|
33 * and furthermore can easily <it>jump</it> to an arbitrarily specified |
|
34 * distant point in the state cycle. |
|
35 * |
|
36 * <p>Ideally, all {@code ArbitrarilyJumpableRng} objects produced by |
|
37 * iterative jumping from a single original {@code ArbtrarilyJumpableRng} |
|
38 * object are statistically independent of one another and |
|
39 * individually uniform, provided that they do not traverse |
|
40 * overlapping portions of the state cycle. In practice, one must |
|
41 * settle for some approximation to independence and uniformity. In |
|
42 * particular, a specific implementation may assume that each |
|
43 * generator in a stream produced by the {@code jumps} method is used |
|
44 * to produce a number of values no larger than the jump distance |
|
45 * specified. Implementors are advised to use algorithms whose period |
|
46 * is at least 2<sup>127</sup>. |
|
47 * |
|
48 * <p>For many applications, it suffices to jump forward by a power of |
|
49 * two or some small multiple of a power of two, but this power of two |
|
50 * may not be representable as a {@code long} value. To avoid the |
|
51 * use of {@code BigInteger} values as jump distances, {@code double} |
|
52 * values are used instead. |
|
53 * |
|
54 * <p>Methods are provided to perform a single jump operation and also |
|
55 * to produce a stream of generators produced from the original by |
|
56 * iterative copying and jumping of internal state. A typical |
|
57 * strategy for a multithreaded application is to create a single |
|
58 * {@code ArbitrarilyJumpableRng} object, call its {@code jumps} |
|
59 * method exactly once, and then parcel out generators from the |
|
60 * resulting stream, one to each thread. However, each generator |
|
61 * produced also has type {@code ArbitrarilyJumpableRng}; with care, |
|
62 * different jump distances can be used to traverse the entire |
|
63 * state cycle in various ways. |
|
64 * |
|
65 * <p>An implementation of the {@code ArbitrarilyJumpableRng} interface must |
|
66 * provide concrete definitions for the methods {@code nextInt()}, |
|
67 * {@code nextLong}, {@code period()}, {@code copy()}, {@code jump(double)}, |
|
68 * {@code defaultJumpDistance()}, and {@code defaultLeapDistance()}. |
|
69 * Default implementations are provided for all other methods. |
|
70 * Perhaps the most convenient |
|
71 * way to implement this interface is to extend the abstract class |
|
72 * {@link java.util.AbstractArbitrarilyJumpableRng}, which provides |
|
73 * spliterator-based implementations of the methods {@code ints}, {@code longs}, |
|
74 * {@code doubles}, {@code rngs}, {@code jumps}, and {@code leaps}. |
|
75 * |
|
76 * <p>Objects that implement {@code java.util.ArbitrarilyJumpableRng} |
|
77 * are typically not cryptographically secure. Consider instead using |
|
78 * {@link java.security.SecureRandom} to get a cryptographically |
|
79 * secure pseudo-random number generator for use by |
|
80 * security-sensitive applications. |
|
81 * |
|
82 * @author Guy Steele |
|
83 * @since 1.9 |
|
84 */ |
|
85 interface ArbitrarilyJumpableRng extends LeapableRng { |
|
86 /** |
|
87 * Returns a new generator whose internal state is an exact copy |
|
88 * of this generator (therefore their future behavior should be |
|
89 * identical if subjected to the same series of operations). |
|
90 * |
|
91 * @return a new object that is a copy of this generator |
|
92 */ |
|
93 ArbitrarilyJumpableRng copy(); |
|
94 |
|
95 /** |
|
96 * Alter the state of this pseudorandom number generator so as to |
|
97 * jump forward a distance equal to 2<sup>{@code logDistance}</sup> |
|
98 * within its state cycle. |
|
99 * |
|
100 * @param logDistance the base-2 logarithm of the distance to jump |
|
101 * forward within the state cycle |
|
102 * @throws IllegalArgumentException if {@code logDistance} is NaN |
|
103 * or negative, or if 2<sup>{@code logDistance}</sup> is |
|
104 * greater than the period of this generator |
|
105 */ |
|
106 void jumpPowerOfTwo(int logDistance); |
|
107 |
|
108 /** |
|
109 * Alter the state of this pseudorandom number generator so as to |
|
110 * jump forward a specified distance within its state cycle. |
|
111 * |
|
112 * @param distance the distance to jump forward within the state cycle |
|
113 * @throws IllegalArgumentException if {@code distance} is Nan, |
|
114 * negative, or greater than the period of this generator |
|
115 */ |
|
116 void jump(double distance); |
|
117 |
|
118 /** |
|
119 * Alter the state of this pseudorandom number generator so as to |
|
120 * jump forward a large, fixed distance (typically 2<sup>64</sup> |
|
121 * or more) within its state cycle. The distance used is that |
|
122 * returned by method {@code defaultJumpDistance()}. |
|
123 */ |
|
124 default void jump() { jump(defaultJumpDistance()); } |
|
125 |
|
126 /** |
|
127 * Returns an effectively unlimited stream of new pseudorandom |
|
128 * number generators, each of which implements the {@code ArbitrarilyJumpableRng} |
|
129 * interface, produced by jumping copies of this generator |
|
130 * by different integer multiples of the specified jump distance. |
|
131 * |
|
132 * @implNote This method is implemented to be equivalent to |
|
133 * {@code jumps(Long.MAX_VALUE)}. |
|
134 * |
|
135 * @param distance a distance to jump forward within the state cycle |
|
136 * @return a stream of objects that implement the {@code Rng} interface |
|
137 */ |
|
138 default Stream<ArbitrarilyJumpableRng> jumps(double distance) { |
|
139 return Stream.generate(() -> copyAndJump(distance)).sequential(); |
|
140 } |
|
141 |
|
142 /** |
|
143 * Returns a stream producing the given {@code streamSize} number of |
|
144 * new pseudorandom number generators, each of which implements the |
|
145 * {@code ArbitrarilyJumpableRng} interface, produced by jumping copies of this generator |
|
146 * by different integer multiples of the specified jump distance. |
|
147 * |
|
148 * @param streamSize the number of generators to generate |
|
149 * @param distance a distance to jump forward within the state cycle |
|
150 * @return a stream of objects that implement the {@code Rng} interface |
|
151 * @throws IllegalArgumentException if {@code streamSize} is |
|
152 * less than zero |
|
153 */ |
|
154 default Stream<ArbitrarilyJumpableRng> jumps(long streamSize, double distance) { |
|
155 return jumps(distance).limit(streamSize); |
|
156 } |
|
157 |
|
158 /** |
|
159 * Alter the state of this pseudorandom number generator so as to |
|
160 * jump forward a very large, fixed distance (typically 2<sup>128</sup> |
|
161 * or more) within its state cycle. The distance used is that |
|
162 * returned by method {@code defaultJLeapDistance()}. |
|
163 */ |
|
164 default void leap() { jump(defaultLeapDistance()); } |
|
165 |
|
166 /** |
|
167 * Copy this generator, jump this generator forward, then return the copy. |
|
168 */ |
|
169 default ArbitrarilyJumpableRng copyAndJump(double distance) { |
|
170 ArbitrarilyJumpableRng result = copy(); |
|
171 jump(distance); |
|
172 return result; |
|
173 } |
|
174 |
|
175 } |