src/java.base/share/classes/java/util/random/Xoshiro256StarStar.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.LeapableGenerator;
    30 
    31 
    31 /**
    32 /**
    32  * A generator of uniform pseudorandom values applicable for use in
    33  * A generator of uniform pseudorandom values applicable for use in
    33  * (among other contexts) isolated parallel computations that may
    34  * (among other contexts) isolated parallel computations that may
    34  * generate subtasks.  Class {@link Xoshiro256StarStar} implements
    35  * generate subtasks.  Class {@link Xoshiro256StarStar} implements
    35  * interfaces {@link RandomNumberGenerator} and {@link LeapableRNG},
    36  * interfaces {@link RandomGenerator} and {@link LeapableGenerator},
    36  * and therefore supports methods for producing pseudorandomly chosen
    37  * and therefore supports methods for producing pseudorandomly chosen
    37  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
    38  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
    38  * as well as creating new {@link Xoshiro256StarStar} objects
    39  * as well as creating new {@link Xoshiro256StarStar} objects
    39  * by "jumping" or "leaping".
    40  * by "jumping" or "leaping".
    40  * <p>
    41  * <p>
    87  * seed unless the {@linkplain System#getProperty system property}
    88  * seed unless the {@linkplain System#getProperty system property}
    88  * {@code java.util.secureRandomSeed} is set to {@code true}.
    89  * {@code java.util.secureRandomSeed} is set to {@code true}.
    89  *
    90  *
    90  * @since 14
    91  * @since 14
    91  */
    92  */
    92 public final class Xoshiro256StarStar implements LeapableRNG {
    93 public final class Xoshiro256StarStar implements LeapableGenerator {
    93 
    94 
    94     /*
    95     /*
    95      * Implementation Overview.
    96      * Implementation Overview.
    96      *
    97      *
    97      * This is an implementation of the xoroshiro128** algorithm written
    98      * This is an implementation of the xoroshiro128** algorithm written
   126     /* ---------------- static fields ---------------- */
   127     /* ---------------- static fields ---------------- */
   127 
   128 
   128     /**
   129     /**
   129      * The seed generator for default constructors.
   130      * The seed generator for default constructors.
   130      */
   131      */
   131     private static final AtomicLong DEFAULT_GEN = new AtomicLong(RNGSupport.initialSeed());
   132     private static final AtomicLong DEFAULT_GEN = new AtomicLong(RandomSupport.initialSeed());
   132 
   133 
   133     /*
   134     /*
   134      * The period of this generator, which is 2**256 - 1.
   135      * The period of this generator, which is 2**256 - 1.
   135      */
   136      */
   136     private static final BigInteger PERIOD =
   137     private static final BigInteger PERIOD =
   162         this.x2 = x2;
   163         this.x2 = x2;
   163         this.x3 = x3;
   164         this.x3 = x3;
   164         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
   165         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
   165         if ((x0 | x1 | x2 | x3) == 0) {
   166         if ((x0 | x1 | x2 | x3) == 0) {
   166             // At least three of the four values generated here will be nonzero.
   167             // At least three of the four values generated here will be nonzero.
   167             this.x0 = RNGSupport.mixStafford13(x0 += RNGSupport.GOLDEN_RATIO_64);
   168             this.x0 = RandomSupport.mixStafford13(x0 += RandomSupport.GOLDEN_RATIO_64);
   168             this.x1 = (x0 += RNGSupport.GOLDEN_RATIO_64);
   169             this.x1 = (x0 += RandomSupport.GOLDEN_RATIO_64);
   169             this.x2 = (x0 += RNGSupport.GOLDEN_RATIO_64);
   170             this.x2 = (x0 += RandomSupport.GOLDEN_RATIO_64);
   170             this.x3 = (x0 += RNGSupport.GOLDEN_RATIO_64);
   171             this.x3 = (x0 += RandomSupport.GOLDEN_RATIO_64);
   171         }
   172         }
   172     }
   173     }
   173 
   174 
   174     /**
   175     /**
   175      * Creates a new instance of {@link Xoshiro256StarStar} using the
   176      * Creates a new instance of {@link Xoshiro256StarStar} using the
   184         // argument tends to improve "pedestrian" seeds such as 0 or
   185         // argument tends to improve "pedestrian" seeds such as 0 or
   185         // other small integers.  We may as well use SILVER_RATIO_64.
   186         // other small integers.  We may as well use SILVER_RATIO_64.
   186         //
   187         //
   187         // The x values are then filled in as if by a SplitMix PRNG with
   188         // The x values are then filled in as if by a SplitMix PRNG with
   188         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
   189         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
   189         this(RNGSupport.mixStafford13(seed ^= RNGSupport.SILVER_RATIO_64),
   190         this(RandomSupport.mixStafford13(seed ^= RandomSupport.SILVER_RATIO_64),
   190              RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
   191              RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
   191              RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
   192              RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
   192              RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
   193              RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
   193     }
   194     }
   194 
   195 
   195     /**
   196     /**
   196      * Creates a new instance of {@link Xoshiro256StarStar} that is likely to
   197      * Creates a new instance of {@link Xoshiro256StarStar} that is likely to
   197      * generate sequences of values that are statistically independent
   198      * generate sequences of values that are statistically independent
   198      * of those of any other instances in the current program execution,
   199      * of those of any other instances in the current program execution,
   199      * but may, and typically does, vary across program invocations.
   200      * but may, and typically does, vary across program invocations.
   200      */
   201      */
   201     public Xoshiro256StarStar() {
   202     public Xoshiro256StarStar() {
   202         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
   203         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
   203         this(DEFAULT_GEN.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
   204         this(DEFAULT_GEN.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
   204     }
   205     }
   205 
   206 
   206     /**
   207     /**
   207      * Creates a new instance of {@link Xoshiro256StarStar} using the specified array of
   208      * Creates a new instance of {@link Xoshiro256StarStar} using the specified array of
   208      * initial seed bytes. Instances of {@link Xoshiro256StarStar} created with the same
   209      * initial seed bytes. Instances of {@link Xoshiro256StarStar} created with the same
   210      *
   211      *
   211      * @param seed the initial seed
   212      * @param seed the initial seed
   212      */
   213      */
   213     public Xoshiro256StarStar(byte[] seed) {
   214     public Xoshiro256StarStar(byte[] seed) {
   214         // Convert the seed to 4 long values, which are not all zero.
   215         // Convert the seed to 4 long values, which are not all zero.
   215         long[] data = RNGSupport.convertSeedBytesToLongs(seed, 4, 4);
   216         long[] data = RandomSupport.convertSeedBytesToLongs(seed, 4, 4);
   216         long x0 = data[0], x1 = data[1], x2 = data[2], x3 = data[3];
   217         long x0 = data[0], x1 = data[1], x2 = data[2], x3 = data[3];
   217         this.x0 = x0;
   218         this.x0 = x0;
   218         this.x1 = x1;
   219         this.x1 = x1;
   219         this.x2 = x2;
   220         this.x2 = x2;
   220         this.x3 = x3;
   221         this.x3 = x3;