src/java.base/share/classes/java/util/random/L64X128Random.java
branchJDK-8193209-branch
changeset 57547 56cbdc3ea079
parent 57437 f02ffcb61dce
child 57684 7cb325557832
equal deleted inserted replaced
57546:1ca1cfdcb451 57547:56cbdc3ea079
    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