1 /*
2  * Copyright (c) 2021, 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 jdk.random;
27 
28 import java.util.concurrent.atomic.AtomicLong;
29 import java.util.random.RandomGenerator;
30 import jdk.internal.util.random.RandomSupport;
31 import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
32 import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
33 
34 /**
35  * A "splittable" pseudorandom number generator (PRNG) whose period
36  * is roughly 2<sup>384</sup>.  Class {@link L128X256MixRandom} implements
37  * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
38  * and therefore supports methods for producing pseudorandomly chosen
39  * values of type {@code int}, {@code long}, {@code float}, {@code double},
40  * and {@code boolean} (and for producing streams of pseudorandomly chosen
41  * numbers of type {@code int}, {@code long}, and {@code double}),
42  * as well as methods for creating new split-off {@link L128X256MixRandom}
43  * objects or streams of such objects.
44  *
45  * <p>The {@link L128X256MixRandom} algorithm is a specific member of
46  * the LXM family of algorithms for pseudorandom number generators;
47  * for more information, see the documentation for package
48  * {@link jdk.random}.  Each instance of {@link L128X256MixRandom}
49  * has 384 bits of state plus one 128-bit instance-specific parameter.
50  *
51  * <p>If two instances of {@link L128X256MixRandom} are created with
52  * the same seed within the same program execution, and the same
53  * sequence of method calls is made for each, they will generate and
54  * return identical sequences of values.
55  *
56  * <p>As with {@link java.util.SplittableRandom}, instances of
57  * {@link L128X256MixRandom} are <em>not</em> thread-safe.  They are
58  * designed to be split, not shared, across threads (see the {@link #split}
59  * method). For example, a {@link java.util.concurrent.ForkJoinTask}
60  * fork/join-style computation using random numbers might include a
61  * construction of the form
62  * {@code new Subtask(someL128X256MixRandom.split()).fork()}.
63  *
64  * <p>This class provides additional methods for generating random
65  * streams, that employ the above techniques when used in
66  * {@code stream.parallel()} mode.
67  *
68  * <p>Instances of {@link L128X256MixRandom} are not cryptographically
69  * secure.  Consider instead using {@link java.security.SecureRandom}
70  * in security-sensitive applications. Additionally,
71  * default-constructed instances do not use a cryptographically random
72  * seed unless the {@linkplain System#getProperty system property}
73  * {@code java.util.secureRandomSeed} is set to {@code true}.
74  *
75  * @since   17
76  *
77  */
78 @RandomGeneratorProperties(
79         name = "L128X256MixRandom",
80         group = "LXM",
81         i = 256, j = 1, k = 128,
82         equidistribution = 1
83 )
84 public final class L128X256MixRandom extends AbstractSplittableWithBrineGenerator {
85 
86     /*
87      * Implementation Overview.
88      *
89      * The 128-bit parameter `a` is represented as two long fields `ah` and `al`.
90      * The 128-bit state variable `s` is represented as two long fields `sh` and `sl`.
91      *
92      * The split operation uses the current generator to choose eight
93      * new 64-bit long values that are then used to initialize the
94      * parameters `ah` and `al` and the state variables `sh`, `sl`,
95      * `x0`, `x1`, `x2`, and `x3` for a newly constructed generator.
96      *
97      * With extremely high probability, no two generators so chosen
98      * will have the same `a` parameter, and testing has indicated
99      * that the values generated by two instances of {@link L128X256MixRandom}
100      * will be (approximately) independent if have different values for `a`.
101      *
102      * The default (no-argument) constructor, in essence, uses
103      * "defaultGen" to generate eight new 64-bit values for the same
104      * purpose.  Multiple generators created in this way will certainly
105      * differ in their `a` parameters.  The defaultGen state must be accessed
106      * in a thread-safe manner, so we use an AtomicLong to represent
107      * this state.  To bootstrap the defaultGen, we start off using a
108      * seed based on current time unless the
109      * java.util.secureRandomSeed property is set. This serves as a
110      * slimmed-down (and insecure) variant of SecureRandom that also
111      * avoids stalls that may occur when using /dev/random.
112      *
113      * File organization: First static fields, then instance
114      * fields, then constructors, then instance methods.
115      */
116 
117     /* ---------------- static fields ---------------- */
118 
119     /**
120      * The seed generator for default constructors.
121      */
122     private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
123 
124     /*
125      * The equidistribution of the algorithm.
126      */
127     private static final int EQUIDISTRIBUTION = 1;
128 
129     /*
130      * Low half of multiplier used in the LCG portion of the algorithm;
131      * the overall multiplier is (2**64 + ML).
132      * Chosen based on research by Sebastiano Vigna and Guy Steele (2019).
133      * The spectral scores for dimensions 2 through 8 for the multiplier 0x1d605bbb58c8abbfdLL
134      * are [0.991889, 0.907938, 0.830964, 0.837980, 0.780378, 0.797464, 0.761493].
135      */
136 
137     private static final long ML = 0xd605bbb58c8abbfdL;
138 
139     /* ---------------- instance fields ---------------- */
140 
141     /**
142      * The parameter that is used as an additive constant for the LCG.
143      * Must be odd (therefore al must be odd).
144      */
145     private final long ah, al;
146 
147     /**
148      * The per-instance state: sh and sl for the LCG; x0, x1, x2, and x3 for the XBG.
149      * At least one of the four fields x0, x1, x2, and x3 must be nonzero.
150      */
151     private long sh, sl, x0, x1, x2, x3;
152 
153     /* ---------------- constructors ---------------- */
154 
155     /**
156      * Basic constructor that initializes all fields from parameters.
157      * It then adjusts the field values if necessary to ensure that
158      * all constraints on the values of fields are met.
159      *
160      * @param ah high half of the additive parameter for the LCG
161      * @param al low half of the additive parameter for the LCG
162      * @param sh high half of the initial state for the LCG
163      * @param sl low half of the initial state for the LCG
164      * @param x0 first word of the initial state for the XBG
165      * @param x1 second word of the initial state for the XBG
166      * @param x2 third word of the initial state for the XBG
167      * @param x3 fourth word of the initial state for the XBG
168      */
L128X256MixRandom(long ah, long al, long sh, long sl, long x0, long x1, long x2, long x3)169     public L128X256MixRandom(long ah, long al, long sh, long sl, long x0, long x1, long x2, long x3) {
170         // Force a to be odd.
171         this.ah = ah;
172         this.al = al | 1;
173         this.sh = sh;
174         this.sl = sl;
175         this.x0 = x0;
176         this.x1 = x1;
177         this.x2 = x2;
178         this.x3 = x3;
179         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
180         if ((x0 | x1 | x2 | x3) == 0) {
181        long v = sh;
182             // At least three of the four values generated here will be nonzero.
183             this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
184             this.x1 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
185             this.x2 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
186             this.x3 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64);
187         }
188     }
189 
190     /**
191      * Creates a new instance of {@link L128X256MixRandom} using the
192      * specified {@code long} value as the initial seed. Instances of
193      * {@link L128X256MixRandom} created with the same seed in the same
194      * program generate identical sequences of values.
195      *
196      * @param seed the initial seed
197      */
L128X256MixRandom(long seed)198     public L128X256MixRandom(long seed) {
199         // Using a value with irregularly spaced 1-bits to xor the seed
200         // argument tends to improve "pedestrian" seeds such as 0 or
201         // other small integers.  We may as well use SILVER_RATIO_64.
202         //
203         // The seed is hashed by mixMurmur64 to produce the `a` parameter.
204         // The seed is hashed by mixStafford13 to produce the initial `x0`,
205         // which will then be used to produce the first generated value.
206         // The other x values are filled in as if by a SplitMix PRNG with
207         // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer.
208         this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
209              RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64),
210              0,
211              1,
212              RandomSupport.mixStafford13(seed),
213              RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
214              RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
215              RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
216     }
217 
218     /**
219      * Creates a new instance of {@link L128X256MixRandom} that is likely to
220      * generate sequences of values that are statistically independent
221      * of those of any other instances in the current program execution,
222      * but may, and typically does, vary across program invocations.
223      */
L128X256MixRandom()224     public L128X256MixRandom() {
225         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
226         this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
227     }
228 
229     /**
230      * Creates a new instance of {@link L128X256MixRandom} using the specified array of
231      * initial seed bytes. Instances of {@link L128X256MixRandom} created with the same
232      * seed array in the same program execution generate identical sequences of values.
233      *
234      * @param seed the initial seed
235      */
L128X256MixRandom(byte[] seed)236     public L128X256MixRandom(byte[] seed) {
237         // Android-changed: backport https://bugs.openjdk.org/browse/JDK-8283083.
238         // Convert the seed to 8 long values, of which the last 4 are not all zero.
239         // long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 4);
240         long[] data = RandomSupport.convertSeedBytesToLongs(seed, 8, 4);
241         long ah = data[0], al = data[1], sh = data[2], sl = data[3],
242              x0 = data[4], x1 = data[5], x2 = data[6], x3 = data[7];
243         // Force a to be odd.
244         this.ah = ah;
245         this.al = al | 1;
246         this.sh = sh;
247         this.sl = sl;
248         this.x0 = x0;
249         this.x1 = x1;
250         this.x2 = x2;
251         this.x3 = x3;
252     }
253 
254     /* ---------------- public methods ---------------- */
255 
256     @Override
split(SplittableGenerator source, long brine)257     public SplittableGenerator split(SplittableGenerator source, long brine) {
258        // Pick a new instance "at random", but use the brine for (the low half of) `a`.
259         return new L128X256MixRandom(source.nextLong(), brine << 1,
260                     source.nextLong(), source.nextLong(),
261                     source.nextLong(), source.nextLong(),
262                     source.nextLong(), source.nextLong());
263     }
264 
265     @Override
nextLong()266     public long nextLong() {
267        // Compute the result based on current state information
268        // (this allows the computation to be overlapped with state update).
269         final long result = RandomSupport.mixLea64(sh + x0);
270 
271        // Update the LCG subgenerator
272         // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic.
273         final long u = ML * sl;
274        // Note that Math.multiplyHigh computes the high half of the product of signed values,
275        // but what we need is the high half of the product of unsigned values; for this we use the
276        // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)";
277        // in effect, each operand is added to the result iff the sign bit of the other operand is 1.
278        // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013),
279        // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.)
280        // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become:
281        //         sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah;
282        // and this entire comment can be deleted.
283         sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah;
284         sl = u + al;
285         if (Long.compareUnsigned(sl, u) < 0) ++sh;  // Handle the carry propagation from low half to high half.
286 
287        // Update the XBG subgenerator
288         long q0 = x0, q1 = x1, q2 = x2, q3 = x3;
289         {   // xoshiro256 1.0
290             long t = q1 << 17;
291             q2 ^= q0;
292             q3 ^= q1;
293             q1 ^= q2;
294             q0 ^= q3;
295             q2 ^= t;
296             q3 = Long.rotateLeft(q3, 45);
297         }
298         x0 = q0; x1 = q1; x2 = q2; x3 = q3;
299 
300         return result;
301     }
302 
303 }
304