src/java.base/share/classes/java/util/random/L64X256MixRandom.java
branchJDK-8193209-branch
changeset 59080 1b314be4feb2
parent 57684 7cb325557832
equal deleted inserted replaced
57940:7e791393cc4d 59080:1b314be4feb2
    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;
    30 import java.util.random.RandomGenerator.SplittableGenerator;
    31 import java.util.random.RandomSupport.AbstractSplittableGenerator;
    31 import java.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
    32 
    32 
    33 /**
    33 /**
    34  * A generator of uniform pseudorandom values applicable for use in
    34  * A generator of uniform pseudorandom values applicable for use in
    35  * (among other contexts) isolated parallel computations that may
    35  * (among other contexts) isolated parallel computations that may
    36  * generate subtasks.  Class {@link L64X256MixRandom} implements
    36  * generate subtasks.  Class {@link L64X256MixRandom} implements
    52  * least approximately, for others as well.
    52  * least approximately, for others as well.
    53  * <p>
    53  * <p>
    54  * {@link L64X256MixRandom} is a specific member of the LXM family of algorithms
    54  * {@link L64X256MixRandom} is a specific member of the LXM family of algorithms
    55  * for pseudorandom number generators.  Every LXM generator consists of two
    55  * for pseudorandom number generators.  Every LXM generator consists of two
    56  * subgenerators; one is an LCG (Linear Congruential Generator) and the other is
    56  * subgenerators; one is an LCG (Linear Congruential Generator) and the other is
    57  * an Xorshift generator.  Each output of an LXM generator is the sum of one
    57  * an Xorshift generator.  Each output of an LXM generator is the result of
    58  * output from each subgenerator, possibly processed by a final mixing function
    58  * combining state from the LCG with state from the Xorshift generator by
    59  * (and {@link L64X256MixRandom} does use a mixing function).
    59  * using a Mixing function (and then the state of the LCG and the state of the
       
    60  * Xorshift generator are advanced).
    60  * <p>
    61  * <p>
    61  * The LCG subgenerator for {@link L64X256MixRandom} has an update step of the
    62  * The LCG subgenerator for {@link L64X256MixRandom} has an update step of the
    62  * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all
    63  * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all
    63  * of type {@code long}; {@code s} is the mutable state, the multiplier {@code m}
    64  * of type {@code long}; {@code s} is the mutable state, the multiplier {@code m}
    64  * is fixed (the same for all instances of {@link L64X256MixRandom}) and the addend
    65  * is fixed (the same for all instances of {@link L64X256MixRandom}) and the addend
    71  * version 1.0 (parameters 17, 45), without any final scrambler such as "+" or "**".
    72  * version 1.0 (parameters 17, 45), without any final scrambler such as "+" or "**".
    72  * Its state consists of four {@code long} fields {@code x0}, {@code x1}, {@code x2},
    73  * Its state consists of four {@code long} fields {@code x0}, {@code x1}, {@code x2},
    73  * and {@code x3}, which can take on any values provided that they are not all zero.
    74  * and {@code x3}, which can take on any values provided that they are not all zero.
    74  * The period of this subgenerator is 2<sup>256</sup>-1.
    75  * The period of this subgenerator is 2<sup>256</sup>-1.
    75  * <p>
    76  * <p>
    76  * The mixing function for {@link L64X256MixRandom} is the 64-bit MurmurHash3 finalizer.
    77  * The mixing function for {@link L64X256MixRandom} is {@link RandomSupport.mixLea64}
       
    78  * applied to the argument {@code (s + x0)}.
    77  * <p>
    79  * <p>
    78  * Because the periods 2<sup>64</sup> and 2<sup>256</sup>-1 of the two subgenerators
    80  * Because the periods 2<sup>64</sup> and 2<sup>256</sup>-1 of the two subgenerators
    79  * are relatively prime, the <em>period</em> of any single {@link L64X256MixRandom} object
    81  * are relatively prime, the <em>period</em> of any single {@link L64X256MixRandom} object
    80  * (the length of the series of generated 64-bit values before it repeats) is the product
    82  * (the length of the series of generated 64-bit values before it repeats) is the product
    81  * of the periods of the subgenerators, that is, 2<sup>64</sup>(2<sup>256</sup>-1),
    83  * of the periods of the subgenerators, that is, 2<sup>64</sup>(2<sup>256</sup>-1),
    96  * There are 2<sup>64</sup>(2<sup>256</sup>-1) such subsequences, and each subsequence,
    98  * There are 2<sup>64</sup>(2<sup>256</sup>-1) such subsequences, and each subsequence,
    97  * which consists of 4 64-bit values, can have one of 2<sup>256</sup> values. Of those
    99  * which consists of 4 64-bit values, can have one of 2<sup>256</sup> values. Of those
    98  * 2<sup>256</sup> subsequence values, nearly all of them (2<sup>256</sup>-2<sup>64</sup>)
   100  * 2<sup>256</sup> subsequence values, nearly all of them (2<sup>256</sup>-2<sup>64</sup>)
    99  * occur 2<sup>64</sup> times over the course of the entire cycle, and the other
   101  * occur 2<sup>64</sup> times over the course of the entire cycle, and the other
   100  * 2<sup>64</sup> subsequence values occur only 2<sup>64</sup>-1 times.  So the ratio
   102  * 2<sup>64</sup> subsequence values occur only 2<sup>64</sup>-1 times.  So the ratio
   101  * of the probability of getting one of the less common subsequence values and the
   103  * of the probability of getting any specific one of the less common subsequence values and the
   102  * probability of getting one of the more common subsequence values is 1-2<sup>-64</sup>.
   104  * probability of getting any specific one of the more common subsequence values is 1-2<sup>-64</sup>.
   103  * (Note that the set of 2<sup>64</sup> less-common subsequence values will differ from
   105  * (Note that the set of 2<sup>64</sup> less-common subsequence values will differ from
   104  * one instance of {@link L64X256MixRandom} to another, as a function of the additive
   106  * one instance of {@link L64X256MixRandom} to another, as a function of the additive
   105  * parameter of the LCG.)  The values produced by the {@code nextInt()}, {@code nextFloat()},
   107  * parameter of the LCG.)  The values produced by the {@code nextInt()}, {@code nextFloat()},
   106  * and {@code nextDouble()} methods are likewise 4-equidistributed.
   108  * and {@code nextDouble()} methods are likewise 4-equidistributed.
   107  * <p>
   109  * <p>
   134  * seed unless the {@linkplain System#getProperty system property}
   136  * seed unless the {@linkplain System#getProperty system property}
   135  * {@code java.util.secureRandomSeed} is set to {@code true}.
   137  * {@code java.util.secureRandomSeed} is set to {@code true}.
   136  *
   138  *
   137  * @since 14
   139  * @since 14
   138  */
   140  */
   139 public final class L64X256MixRandom extends AbstractSplittableGenerator {
   141 public final class L64X256MixRandom extends AbstractSplittableWithBrineGenerator {
   140 
   142 
   141     /*
   143     /*
   142      * Implementation Overview.
   144      * Implementation Overview.
   143      *
   145      *
   144      * The split operation uses the current generator to choose six new 64-bit
   146      * The split operation uses the current generator to choose six new 64-bit
   178      */
   180      */
   179     private static final BigInteger PERIOD =
   181     private static final BigInteger PERIOD =
   180         BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftLeft(64);
   182         BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftLeft(64);
   181 
   183 
   182     /*
   184     /*
   183      * Multiplier used in the LCG portion of the algorithm, taken from
   185      * Multiplier used in the LCG portion of the algorithm.
   184      * Pierre L'Ecuyer, Tables of linear congruential generators of
   186      * Chosen based on research by Sebastiano Vigna and Guy Steele (2019).
   185      * different sizes and good lattice structure, <em>Mathematics of
   187      * The spectral scores for dimensions 2 through 8 for the multiplier 0xd1342543de82ef95
   186      * Computation</em> 68, 225 (January 1999), pages 249-260,
   188      * are [0.958602, 0.937479, 0.870757, 0.822326, 0.820405, 0.813065, 0.760215].
   187      * Table 4 (first multiplier for size 2<sup>64</sup>).
   189      */
   188      */
   190 
   189 
   191     private static final long M = 0xd1342543de82ef95L;
   190     private static final long M = 2862933555777941757L;
       
   191 
   192 
   192     /* ---------------- instance fields ---------------- */
   193     /* ---------------- instance fields ---------------- */
   193 
   194 
   194     /**
   195     /**
   195      * The parameter that is used as an additive constant for the LCG.
   196      * The parameter that is used as an additive constant for the LCG.
   225         this.x1 = x1;
   226         this.x1 = x1;
   226         this.x2 = x2;
   227         this.x2 = x2;
   227         this.x3 = x3;
   228         this.x3 = x3;
   228         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
   229         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
   229         if ((x0 | x1 | x2 | x3) == 0) {
   230         if ((x0 | x1 | x2 | x3) == 0) {
       
   231 	    long v = s;
   230             // At least three of the four values generated here will be nonzero.
   232             // At least three of the four values generated here will be nonzero.
   231             this.x0 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
   233             this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
   232             this.x1 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
   234             this.x1 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
   233             this.x2 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
   235             this.x2 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
   234             this.x3 = RandomSupport.mixStafford13(s + RandomSupport.GOLDEN_RATIO_64);
   236             this.x3 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64);
   235         }
   237         }
   236     }
   238     }
   237 
   239 
   238     /**
   240     /**
   239      * Creates a new instance of {@link L64X256MixRandom} using the
   241      * Creates a new instance of {@link L64X256MixRandom} using the
   250         //
   252         //
   251         // The seed is hashed by mixMurmur64 to produce the `a` parameter.
   253         // The seed is hashed by mixMurmur64 to produce the `a` parameter.
   252         // The seed is hashed by mixStafford13 to produce the initial `x0`,
   254         // The seed is hashed by mixStafford13 to produce the initial `x0`,
   253         // which will then be used to produce the first generated value.
   255         // which will then be used to produce the first generated value.
   254         // The other x values are filled in as if by a SplitMix PRNG with
   256         // The other x values are filled in as if by a SplitMix PRNG with
   255         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
   257         // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer.
   256         this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
   258         this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
   257              1,
   259              1,
   258              RandomSupport.mixStafford13(seed),
   260              RandomSupport.mixStafford13(seed),
   259              RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
   261              RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
   260              RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
   262              RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
   293     }
   295     }
   294 
   296 
   295     /* ---------------- public methods ---------------- */
   297     /* ---------------- public methods ---------------- */
   296 
   298 
   297     /**
   299     /**
   298      * Constructs and returns a new instance of {@link L64X256MixRandom}
   300      * Given 63 bits of "brine", constructs and returns a new instance of
   299      * that shares no mutable state with this instance.
   301      * {@code L64X256MixRandom} that shares no mutable state with this instance.
   300      * However, with very high probability, the set of values collectively
   302      * However, with very high probability, the set of values collectively
   301      * generated by the two objects has the same statistical properties as if
   303      * generated by the two objects has the same statistical properties as if
   302      * same the quantity of values were generated by a single thread using
   304      * same the quantity of values were generated by a single thread using
   303      * a single {@link L64X256MixRandom} object.  Either or both of the two
   305      * a single {@code L64X256MixRandom} object.  Either or both of the two
   304      * objects may be further split using the {@code split} method,
   306      * objects may be further split using the {@code split} method,
   305      * and the same expected statistical properties apply to the
   307      * and the same expected statistical properties apply to the
   306      * entire set of generators constructed by such recursive splitting.
   308      * entire set of generators constructed by such recursive splitting.
   307      *
   309      *
   308      * @param source a {@link SplittableGenerator} instance to be used instead
   310      * @param source a {@code SplittableGenerator} instance to be used instead
   309      *               of this one as a source of pseudorandom bits used to
   311      *               of this one as a source of pseudorandom bits used to
   310      *               initialize the state of the new ones.
   312      *               initialize the state of the new ones.
   311      *
   313      * @param brine a long value, of which the low 63 bits are used to choose
   312      * @return a new instance of {@link L64X256MixRandom}
   314      *              the {@code a} parameter for the new instance.
   313      */
   315      * @return a new instance of {@code L64X256MixRandom}
   314     public L64X256MixRandom split(SplittableGenerator source) {
   316      */
   315         // Literally pick a new instance "at random".
   317     public SplittableGenerator split(SplittableGenerator source, long brine) {
   316         return new L64X256MixRandom(source.nextLong(), source.nextLong(),
   318 	// Pick a new instance "at random", but use the brine for `a`.
   317                                     source.nextLong(), source.nextLong(),
   319         return new L64X256MixRandom(brine << 1, source.nextLong(),
   318                                     source.nextLong(), source.nextLong());
   320 				    source.nextLong(), source.nextLong(),
       
   321 				    source.nextLong(), source.nextLong());
   319     }
   322     }
   320 
   323 
   321     /**
   324     /**
   322      * Returns a pseudorandom {@code long} value.
   325      * Returns a pseudorandom {@code long} value.
   323      *
   326      *
   324      * @return a pseudorandom {@code long} value
   327      * @return a pseudorandom {@code long} value
   325      */
   328      */
   326     public long nextLong() {
   329     public long nextLong() {
   327         final long z = s + x0;
   330 	// Compute the result based on current state information
   328         s = M * s + a;  // LCG
   331 	// (this allows the computation to be overlapped with state update).
       
   332         final long result = RandomSupport.mixLea64(s + x0);
       
   333 	// Update the LCG subgenerator
       
   334         s = M * s + a;
       
   335 	// Update the Xorshift subgenerator
   329         long q0 = x0, q1 = x1, q2 = x2, q3 = x3;
   336         long q0 = x0, q1 = x1, q2 = x2, q3 = x3;
   330         {   // xoshiro256 1.0
   337         {   // xoshiro256 1.0
   331             long t = q1 << 17;
   338             long t = q1 << 17;
   332             q2 ^= q0;
   339             q2 ^= q0;
   333             q3 ^= q1;
   340             q3 ^= q1;
   335             q0 ^= q3;
   342             q0 ^= q3;
   336             q2 ^= t;
   343             q2 ^= t;
   337             q3 = Long.rotateLeft(q3, 45);
   344             q3 = Long.rotateLeft(q3, 45);
   338         }
   345         }
   339         x0 = q0; x1 = q1; x2 = q2; x3 = q3;
   346         x0 = q0; x1 = q1; x2 = q2; x3 = q3;
   340         return RandomSupport.mixLea64(z);  // mixing function
   347         return result;
   341     }
   348     }
   342 
   349 
       
   350     /**
       
   351      * Returns the period of this random generator.
       
   352      *
       
   353      * @return a {@link BigInteger} whose value is the number of distinct possible states of this
       
   354      *         {@link RandomGenerator} object (2<sup>64</sup>(2<sup>256</sup>-1)).
       
   355      */
   343     public BigInteger period() {
   356     public BigInteger period() {
   344         return PERIOD;
   357         return PERIOD;
   345     }
   358     }
   346 }
   359 }