src/java.base/share/classes/java/util/random/L64X256Random.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 L64X256Random} implements
    36  * generate subtasks.  Class {@link L64X256Random} 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 L64X256Random} objects,
    40  * as well as creating new split-off {@link L64X256Random} 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 L64X256Random extends AbstractSplittableRNG {
   137 public final class L64X256Random extends AbstractSplittableGenerator {
   136 
   138 
   137     /*
   139     /*
   138      * Implementation Overview.
   140      * Implementation Overview.
   139      *
   141      *
   140      * The split() operation uses the current generator to choose six new 64-bit
   142      * The split() operation uses the current generator to choose six new 64-bit
   165     /* ---------------- static fields ---------------- */
   167     /* ---------------- static fields ---------------- */
   166 
   168 
   167     /**
   169     /**
   168      * The seed generator for default constructors.
   170      * The seed generator for default constructors.
   169      */
   171      */
   170     private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
   172     private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
   171 
   173 
   172     /*
   174     /*
   173      * The period of this generator, which is (2**256 - 1) * 2**64.
   175      * The period of this generator, which is (2**256 - 1) * 2**64.
   174      */
   176      */
   175     private static final BigInteger PERIOD =
   177     private static final BigInteger PERIOD =
   222         this.x2 = x2;
   224         this.x2 = x2;
   223         this.x3 = x3;
   225         this.x3 = x3;
   224         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
   226         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
   225         if ((x0 | x1 | x2 | x3) == 0) {
   227         if ((x0 | x1 | x2 | x3) == 0) {
   226             // At least three of the four values generated here will be nonzero.
   228             // At least three of the four values generated here will be nonzero.
   227             this.x0 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
   229             this.x0 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
   228             this.x1 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
   230             this.x1 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
   229             this.x2 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
   231             this.x2 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
   230             this.x3 = RNGSupport.mixStafford13(s + RNGSupport.GOLDEN_RATIO_64);
   232             this.x3 = RandomSupport.mixStafford13(s + RandomSupport.GOLDEN_RATIO_64);
   231         }
   233         }
   232     }
   234     }
   233 
   235 
   234     /**
   236     /**
   235      * Creates a new instance of {@link L64X256Random} using the
   237      * Creates a new instance of {@link L64X256Random} using the
   247         // The seed is hashed by mixMurmur64 to produce the `a` parameter.
   249         // The seed is hashed by mixMurmur64 to produce the `a` parameter.
   248         // The seed is hashed by mixStafford13 to produce the initial `x0`,
   250         // The seed is hashed by mixStafford13 to produce the initial `x0`,
   249         // which will then be used to produce the first generated value.
   251         // which will then be used to produce the first generated value.
   250         // The other x values are filled in as if by a SplitMix PRNG with
   252         // The other x values are filled in as if by a SplitMix PRNG with
   251         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
   253         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
   252         this(RNGSupport.mixMurmur64(seed ^= RNGSupport.SILVER_RATIO_64),
   254         this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
   253              1,
   255              1,
   254              RNGSupport.mixStafford13(seed),
   256              RandomSupport.mixStafford13(seed),
   255              RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
   257              RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
   256              RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
   258              RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
   257              RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
   259              RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
   258     }
   260     }
   259 
   261 
   260     /**
   262     /**
   261      * Creates a new instance of {@link L64X256Random} that is likely to
   263      * Creates a new instance of {@link L64X256Random} that is likely to
   262      * generate sequences of values that are statistically independent
   264      * generate sequences of values that are statistically independent
   263      * of those of any other instances in the current program execution,
   265      * of those of any other instances in the current program execution,
   264      * but may, and typically does, vary across program invocations.
   266      * but may, and typically does, vary across program invocations.
   265      */
   267      */
   266     public L64X256Random() {
   268     public L64X256Random() {
   267         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
   269         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
   268         this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
   270         this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
   269     }
   271     }
   270 
   272 
   271     /**
   273     /**
   272      * Creates a new instance of {@link L64X256Random} using the specified array of
   274      * Creates a new instance of {@link L64X256Random} using the specified array of
   273      * initial seed bytes. Instances of {@link L64X256Random} created with the same
   275      * initial seed bytes. Instances of {@link L64X256Random} created with the same
   275      *
   277      *
   276      * @param seed the initial seed
   278      * @param seed the initial seed
   277      */
   279      */
   278     public L64X256Random(byte[] seed) {
   280     public L64X256Random(byte[] seed) {
   279         // Convert the seed to 6 long values, of which the last 4 are not all zero.
   281         // Convert the seed to 6 long values, of which the last 4 are not all zero.
   280         long[] data = RNGSupport.convertSeedBytesToLongs(seed, 6, 4);
   282         long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 4);
   281         long a = data[0], s = data[1], x0 = data[2], x1 = data[3], x2 = data[4], x3 = data[5];
   283         long a = data[0], s = data[1], x0 = data[2], x1 = data[3], x2 = data[4], x3 = data[5];
   282         // Force a to be odd.
   284         // Force a to be odd.
   283         this.a = a | 1;
   285         this.a = a | 1;
   284         this.s = s;
   286         this.s = s;
   285         this.x0 = x0;
   287         this.x0 = x0;
   299      * a single {@link L64X256Random} object.  Either or both of the two
   301      * a single {@link L64X256Random} object.  Either or both of the two
   300      * objects may be further split using the {@code split} method,
   302      * objects may be further split using the {@code split} method,
   301      * and the same expected statistical properties apply to the
   303      * and the same expected statistical properties apply to the
   302      * entire set of generators constructed by such recursive splitting.
   304      * entire set of generators constructed by such recursive splitting.
   303      *
   305      *
   304      * @param source a {@link SplittableRNG} instance to be used instead
   306      * @param source a {@link SplittableGenerator} instance to be used instead
   305      *               of this one as a source of pseudorandom bits used to
   307      *               of this one as a source of pseudorandom bits used to
   306      *               initialize the state of the new ones.
   308      *               initialize the state of the new ones.
   307      *
   309      *
   308      * @return a new instance of {@link L64X256Random}
   310      * @return a new instance of {@link L64X256Random}
   309      */
   311      */
   310     public L64X256Random split(SplittableRNG source) {
   312     public L64X256Random split(SplittableGenerator source) {
   311         // Literally pick a new instance "at random".
   313         // Literally pick a new instance "at random".
   312         return new L64X256Random(source.nextLong(), source.nextLong(),
   314         return new L64X256Random(source.nextLong(), source.nextLong(),
   313                                  source.nextLong(), source.nextLong(),
   315                                  source.nextLong(), source.nextLong(),
   314                                  source.nextLong(), source.nextLong());
   316                                  source.nextLong(), source.nextLong());
   315     }
   317     }