src/java.base/share/classes/java/util/random/Xoshiro256StarStar.java
branchJDK-8193209-branch
changeset 57437 f02ffcb61dce
parent 57436 b0c958c0e6c6
child 57547 56cbdc3ea079
equal deleted inserted replaced
57436:b0c958c0e6c6 57437:f02ffcb61dce
    20  *
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    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
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 package java.util;
    25 
       
    26 package java.util.random;
    26 
    27 
    27 import java.math.BigInteger;
    28 import java.math.BigInteger;
    28 import java.util.concurrent.atomic.AtomicLong;
    29 import java.util.concurrent.atomic.AtomicLong;
    29 
    30 
    30 /**
    31 /**
    31  * A generator of uniform pseudorandom values applicable for use in
    32  * A generator of uniform pseudorandom values applicable for use in
    32  * (among other contexts) isolated parallel computations that may
    33  * (among other contexts) isolated parallel computations that may
    33  * generate subtasks.  Class {@code Xoshiro256StarStar} implements
    34  * generate subtasks.  Class {@link Xoshiro256StarStar} implements
    34  * interfaces {@link java.util.Rng} and {@link java.util.LeapableRng},
    35  * interfaces {@link RandomNumberGenerator} and {@link LeapableRNG},
    35  * and therefore supports methods for producing pseudorandomly chosen
    36  * and therefore supports methods for producing pseudorandomly chosen
    36  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
    37  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
    37  * as well as creating new {@code Xoshiro256StarStar} objects
    38  * as well as creating new {@link Xoshiro256StarStar} objects
    38  * by "jumping" or "leaping".
    39  * by "jumping" or "leaping".
    39  *
    40  * <p>
    40  * <p>Series of generated values pass the TestU01 BigCrush and PractRand test suites
    41  * Series of generated values pass the TestU01 BigCrush and PractRand test suites
    41  * that measure independence and uniformity properties of random number generators.
    42  * that measure independence and uniformity properties of random number generators.
    42  * (Most recently validated with
    43  * (Most recently validated with
    43  * <a href="http://simul.iro.umontreal.ca/testu01/tu01.html">version 1.2.3 of TestU01</a>
    44  * <a href="http://simul.iro.umontreal.ca/testu01/tu01.html">version 1.2.3 of TestU01</a>
    44  * and <a href="http://pracrand.sourceforge.net">version 0.90 of PractRand</a>.
    45  * and <a href="http://pracrand.sourceforge.net">version 0.90 of PractRand</a>.
    45  * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()}
    46  * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()}
    46  * method but also the result of bit-reversing each value produced by {@code nextLong()}.)
    47  * method but also the result of bit-reversing each value produced by {@code nextLong()}.)
    47  * These tests validate only the methods for certain
    48  * These tests validate only the methods for certain
    48  * types and ranges, but similar properties are expected to hold, at
    49  * types and ranges, but similar properties are expected to hold, at
    49  * least approximately, for others as well.
    50  * least approximately, for others as well.
    50  *
    51  * <p>
    51  * <p>The class {@code Xoshiro256StarStar} uses the {@code xoshiro256} algorithm,
    52  * The class {@link Xoshiro256StarStar} uses the {@code xoshiro256} algorithm,
    52  * version 1.0 (parameters 17, 45), with the "**" scrambler (a mixing function).
    53  * version 1.0 (parameters 17, 45), with the "**" scrambler (a mixing function).
    53  * Its state consists of four {@code long} fields {@code x0}, {@code x1}, {@code x2},
    54  * Its state consists of four {@code long} fields {@code x0}, {@code x1}, {@code x2},
    54  * and {@code x3}, which can take on any values provided that they are not all zero.
    55  * and {@code x3}, which can take on any values provided that they are not all zero.
    55  * The period of this generator is 2<sup>256</sup>-1.
    56  * The period of this generator is 2<sup>256</sup>-1.
    56  *
    57  * <p>
    57  * <p>The 64-bit values produced by the {@code nextLong()} method are equidistributed.
    58  * The 64-bit values produced by the {@code nextLong()} method are equidistributed.
    58  * To be precise, over the course of the cycle of length 2<sup>256</sup>-1,
    59  * To be precise, over the course of the cycle of length 2<sup>256</sup>-1,
    59  * each nonzero {@code long} value is generated 2<sup>192</sup> times,
    60  * each nonzero {@code long} value is generated 2<sup>192</sup> times,
    60  * but the value 0 is generated only 2<sup>192</sup>-1 times.
    61  * but the value 0 is generated only 2<sup>192</sup>-1 times.
    61  * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()}
    62  * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()}
    62  * methods are likewise equidistributed.
    63  * methods are likewise equidistributed.
    63  *
    64  * <p>
    64  * <p>In fact, the 64-bit values produced by the {@code nextLong()} method are 4-equidistributed.
    65  * In fact, the 64-bit values produced by the {@code nextLong()} method are 4-equidistributed.
    65  * To be precise: consider the (overlapping) length-4 subsequences of the cycle of 64-bit
    66  * To be precise: consider the (overlapping) length-4 subsequences of the cycle of 64-bit
    66  * values produced by {@code nextLong()} (assuming no other methods are called that would
    67  * values produced by {@code nextLong()} (assuming no other methods are called that would
    67  * affect the state).  There are 2<sup>256</sup>-1 such subsequences, and each subsequence,
    68  * affect the state).  There are 2<sup>256</sup>-1 such subsequences, and each subsequence,
    68  * which consists of 4 64-bit values, can have one of 2<sup>256</sup> values.  Of those
    69  * which consists of 4 64-bit values, can have one of 2<sup>256</sup> values.  Of those
    69  * 2<sup>256</sup> subsequence values, each one is generated exactly once over the course
    70  * 2<sup>256</sup> subsequence values, each one is generated exactly once over the course
    70  * of the entire cycle, except that the subsequence (0, 0, 0, 0) never appears.
    71  * of the entire cycle, except that the subsequence (0, 0, 0, 0) never appears.
    71  * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()}
    72  * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()}
    72  * methods are likewise 4-equidistributed, but note that that the subsequence (0, 0, 0, 0)
    73  * methods are likewise 4-equidistributed, but note that that the subsequence (0, 0, 0, 0)
    73  * can also appear (but occurring somewhat less frequently than all other subsequences),
    74  * can also appear (but occurring somewhat less frequently than all other subsequences),
    74  * because the values produced by those methods have fewer than 64 randomly chosen bits.
    75  * because the values produced by those methods have fewer than 64 randomly chosen bits.
    75  *
    76  * <p>
    76  * <p>Instances {@code Xoshiro256StarStar} are <em>not</em> thread-safe.
    77  * Instances {@link Xoshiro256StarStar} are <em>not</em> thread-safe.
    77  * They are designed to be used so that each thread as its own instance.
    78  * They are designed to be used so that each thread as its own instance.
    78  * The methods {@link #jump} and {@link #leap} and {@link #jumps} and {@link #leaps}
    79  * The methods {@link #jump} and {@link #leap} and {@link #jumps} and {@link #leaps}
    79  * can be used to construct new instances of {@code Xoshiro256StarStar} that traverse
    80  * can be used to construct new instances of {@link Xoshiro256StarStar} that traverse
    80  * other parts of the state cycle.
    81  * other parts of the state cycle.
    81  *
    82  * <p>
    82  * <p>Instances of {@code Xoshiro256StarStar} are not cryptographically
    83  * Instances of {@link Xoshiro256StarStar} are not cryptographically
    83  * secure.  Consider instead using {@link java.security.SecureRandom}
    84  * secure.  Consider instead using {@link java.security.SecureRandom}
    84  * in security-sensitive applications. Additionally,
    85  * in security-sensitive applications. Additionally,
    85  * default-constructed instances do not use a cryptographically random
    86  * default-constructed instances do not use a cryptographically random
    86  * seed unless the {@linkplain System#getProperty system property}
    87  * seed unless the {@linkplain System#getProperty system property}
    87  * {@code java.util.secureRandomSeed} is set to {@code true}.
    88  * {@code java.util.secureRandomSeed} is set to {@code true}.
    88  *
    89  *
    89  * @author  Guy Steele
    90  * @since 14
    90  * @since   1.9
       
    91  */
    91  */
    92 public final class Xoshiro256StarStar implements LeapableRng {
    92 public final class Xoshiro256StarStar implements LeapableRNG {
    93 
    93 
    94     /*
    94     /*
    95      * Implementation Overview.
    95      * Implementation Overview.
    96      *
    96      *
    97      * This is an implementation of the xoroshiro128** algorithm written
    97      * This is an implementation of the xoroshiro128** algorithm written
   126     /* ---------------- static fields ---------------- */
   126     /* ---------------- static fields ---------------- */
   127 
   127 
   128     /**
   128     /**
   129      * The seed generator for default constructors.
   129      * The seed generator for default constructors.
   130      */
   130      */
   131     private static final AtomicLong defaultGen = new AtomicLong(RngSupport.initialSeed());
   131     private static final AtomicLong DEFAULT_GEN = new AtomicLong(RNGSupport.initialSeed());
   132 
   132 
   133     /*
   133     /*
   134      * The period of this generator, which is 2**256 - 1.
   134      * The period of this generator, which is 2**256 - 1.
   135      */
   135      */
   136     private static final BigInteger thePeriod =
   136     private static final BigInteger PERIOD =
   137 	BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE);
   137         BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE);
   138 
   138 
   139     /* ---------------- instance fields ---------------- */
   139     /* ---------------- instance fields ---------------- */
   140 
   140 
   141     /**
   141     /**
   142      * The per-instance state.
   142      * The per-instance state.
   155      * @param x1 second word of the initial state
   155      * @param x1 second word of the initial state
   156      * @param x2 third word of the initial state
   156      * @param x2 third word of the initial state
   157      * @param x3 fourth word of the initial state
   157      * @param x3 fourth word of the initial state
   158      */
   158      */
   159     public Xoshiro256StarStar(long x0, long x1, long x2, long x3) {
   159     public Xoshiro256StarStar(long x0, long x1, long x2, long x3) {
   160 	this.x0 = x0;
       
   161         this.x1 = x1;
       
   162         this.x2 = x2;
       
   163         this.x3 = x3;
       
   164 	// If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
       
   165         if ((x0 | x1 | x2 | x3) == 0) {
       
   166 	    // At least three of the four values generated here will be nonzero.
       
   167 	    this.x0 = RngSupport.mixStafford13(x0 += RngSupport.GOLDEN_RATIO_64);
       
   168 	    this.x1 = (x0 += RngSupport.GOLDEN_RATIO_64);
       
   169 	    this.x2 = (x0 += RngSupport.GOLDEN_RATIO_64);
       
   170 	    this.x3 = (x0 += RngSupport.GOLDEN_RATIO_64);
       
   171 	}
       
   172     }
       
   173 
       
   174     /**
       
   175      * Creates a new instance of {@code Xoshiro256StarStar} using the
       
   176      * specified {@code long} value as the initial seed. Instances of
       
   177      * {@code Xoshiro256StarStar} created with the same seed in the same
       
   178      * program generate identical sequences of values.
       
   179      *
       
   180      * @param seed the initial seed
       
   181      */
       
   182     public Xoshiro256StarStar(long seed) {
       
   183 	// Using a value with irregularly spaced 1-bits to xor the seed
       
   184 	// argument tends to improve "pedestrian" seeds such as 0 or
       
   185 	// other small integers.  We may as well use SILVER_RATIO_64.
       
   186 	//
       
   187 	// 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         this(RngSupport.mixStafford13(seed ^= RngSupport.SILVER_RATIO_64),
       
   190 	     RngSupport.mixStafford13(seed += RngSupport.GOLDEN_RATIO_64),
       
   191 	     RngSupport.mixStafford13(seed += RngSupport.GOLDEN_RATIO_64),
       
   192 	     RngSupport.mixStafford13(seed + RngSupport.GOLDEN_RATIO_64));
       
   193     }
       
   194 
       
   195     /**
       
   196      * Creates a new instance of {@code Xoshiro256StarStar} that is likely to
       
   197      * generate sequences of values that are statistically independent
       
   198      * of those of any other instances in the current program execution,
       
   199      * but may, and typically does, vary across program invocations.
       
   200      */
       
   201     public Xoshiro256StarStar() {
       
   202 	// Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
       
   203         this(defaultGen.getAndAdd(RngSupport.GOLDEN_RATIO_64));
       
   204     }
       
   205 
       
   206     /**
       
   207      * Creates a new instance of {@code Xoshiro256StarStar} using the specified array of
       
   208      * initial seed bytes. Instances of {@code Xoshiro256StarStar} created with the same
       
   209      * seed array in the same program execution generate identical sequences of values.
       
   210      *
       
   211      * @param seed the initial seed
       
   212      */
       
   213     public Xoshiro256StarStar(byte[] seed) {
       
   214 	// Convert the seed to 4 long values, which are not all zero.
       
   215 	long[] data = RngSupport.convertSeedBytesToLongs(seed, 4, 4);
       
   216 	long x0 = data[0], x1 = data[1], x2 = data[2], x3 = data[3];
       
   217         this.x0 = x0;
   160         this.x0 = x0;
   218         this.x1 = x1;
   161         this.x1 = x1;
   219         this.x2 = x2;
   162         this.x2 = x2;
   220         this.x3 = x3;
   163         this.x3 = x3;
       
   164         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
       
   165         if ((x0 | x1 | x2 | x3) == 0) {
       
   166             // At least three of the four values generated here will be nonzero.
       
   167             this.x0 = RNGSupport.mixStafford13(x0 += RNGSupport.GOLDEN_RATIO_64);
       
   168             this.x1 = (x0 += RNGSupport.GOLDEN_RATIO_64);
       
   169             this.x2 = (x0 += RNGSupport.GOLDEN_RATIO_64);
       
   170             this.x3 = (x0 += RNGSupport.GOLDEN_RATIO_64);
       
   171         }
       
   172     }
       
   173 
       
   174     /**
       
   175      * Creates a new instance of {@link Xoshiro256StarStar} using the
       
   176      * specified {@code long} value as the initial seed. Instances of
       
   177      * {@link Xoshiro256StarStar} created with the same seed in the same
       
   178      * program generate identical sequences of values.
       
   179      *
       
   180      * @param seed the initial seed
       
   181      */
       
   182     public Xoshiro256StarStar(long seed) {
       
   183         // Using a value with irregularly spaced 1-bits to xor the seed
       
   184         // argument tends to improve "pedestrian" seeds such as 0 or
       
   185         // other small integers.  We may as well use SILVER_RATIO_64.
       
   186         //
       
   187         // 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         this(RNGSupport.mixStafford13(seed ^= RNGSupport.SILVER_RATIO_64),
       
   190              RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
       
   191              RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
       
   192              RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
       
   193     }
       
   194 
       
   195     /**
       
   196      * Creates a new instance of {@link Xoshiro256StarStar} that is likely to
       
   197      * generate sequences of values that are statistically independent
       
   198      * of those of any other instances in the current program execution,
       
   199      * but may, and typically does, vary across program invocations.
       
   200      */
       
   201     public Xoshiro256StarStar() {
       
   202         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
       
   203         this(DEFAULT_GEN.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
       
   204     }
       
   205 
       
   206     /**
       
   207      * 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      * seed array in the same program execution generate identical sequences of values.
       
   210      *
       
   211      * @param seed the initial seed
       
   212      */
       
   213     public Xoshiro256StarStar(byte[] seed) {
       
   214         // Convert the seed to 4 long values, which are not all zero.
       
   215         long[] data = RNGSupport.convertSeedBytesToLongs(seed, 4, 4);
       
   216         long x0 = data[0], x1 = data[1], x2 = data[2], x3 = data[3];
       
   217         this.x0 = x0;
       
   218         this.x1 = x1;
       
   219         this.x2 = x2;
       
   220         this.x3 = x3;
   221     }
   221     }
   222 
   222 
   223     /* ---------------- public methods ---------------- */
   223     /* ---------------- public methods ---------------- */
   224 
   224 
   225     public Xoshiro256StarStar copy() { return new Xoshiro256StarStar(x0, x1, x2, x3); }
   225     public Xoshiro256StarStar copy() {
       
   226         return new Xoshiro256StarStar(x0, x1, x2, x3);
       
   227     }
   226 
   228 
   227     /**
   229     /**
   228      * Returns a pseudorandom {@code long} value.
   230      * Returns a pseudorandom {@code long} value.
   229      *
   231      *
   230      * @return a pseudorandom {@code long} value
   232      * @return a pseudorandom {@code long} value
   231      */
   233      */
   232 
   234    public long nextLong() {
   233     public long nextLong() {
   235         final long z = x0;
   234 	final long z = x0;
   236         long q0 = x0, q1 = x1, q2 = x2, q3 = x3;
   235 	long q0 = x0, q1 = x1, q2 = x2, q3 = x3;	
   237         { long t = q1 << 17; q2 ^= q0; q3 ^= q1; q1 ^= q2; q0 ^= q3; q2 ^= t; q3 = Long.rotateLeft(q3, 45); }  // xoshiro256 1.0
   236 	{ long t = q1 << 17; q2 ^= q0; q3 ^= q1; q1 ^= q2; q0 ^= q3; q2 ^= t; q3 = Long.rotateLeft(q3, 45); }  // xoshiro256 1.0
   238         x0 = q0; x1 = q1; x2 = q2; x3 = q3;
   237 	x0 = q0; x1 = q1; x2 = q2; x3 = q3;
   239         return Long.rotateLeft(z * 5, 7) * 9;  // "starstar" mixing function
   238 	return Long.rotateLeft(z * 5, 7) * 9;  // "starstar" mixing function
   240     }
   239     }
   241 
   240 
   242     public BigInteger period() {
   241     public BigInteger period() { return thePeriod; }
   243         return PERIOD;
   242 
   244     }
   243     
   245 
   244     public double defaultJumpDistance() { return 0x1.0p64; }
   246     public double defaultJumpDistance() {
   245     public double defaultLeapDistance() { return 0x1.0p96; }
   247         return 0x1.0p64;
       
   248     }
       
   249 
       
   250     public double defaultLeapDistance() {
       
   251         return 0x1.0p96;
       
   252     }
   246 
   253 
   247     private static final long[] JUMP_TABLE = {
   254     private static final long[] JUMP_TABLE = {
   248 	0x180ec6d33cfd0abaL, 0xd5a61266f0c9392cL, 0xa9582618e03fc9aaL, 0x39abdc4529b1661cL };
   255         0x180ec6d33cfd0abaL, 0xd5a61266f0c9392cL, 0xa9582618e03fc9aaL, 0x39abdc4529b1661cL };
   249     
   256 
   250     private static final long[] LEAP_TABLE = {
   257     private static final long[] LEAP_TABLE = {
   251 	0x76e15d3efefdcbbfL, 0xc5004e441c522fb3L, 0x77710069854ee241L, 0x39109bb02acbe635L };
   258         0x76e15d3efefdcbbfL, 0xc5004e441c522fb3L, 0x77710069854ee241L, 0x39109bb02acbe635L };
   252    
   259 
   253 /* This is the jump function for the generator. It is equivalent
   260     /**
   254    to 2**128 calls to next(); it can be used to generate 2**128
   261      * This is the jump function for the generator. It is equivalent to 2**128 calls to next(); it
   255    non-overlapping subsequences for parallel computations. */
   262      * can be used to generate 2**128 non-overlapping subsequences for parallel computations.
   256 
   263      */
   257     public void jump() { jumpAlgorithm(JUMP_TABLE); }
   264     public void jump() {
   258     
   265         jumpAlgorithm(JUMP_TABLE);
   259 /* This is the long-jump function for the generator. It is equivalent to
   266     }
   260    2**192 calls to next(); it can be used to generate 2**64 starting points,
   267 
   261    from each of which jump() will generate 2**64 non-overlapping
   268     /**
   262    subsequences for parallel distributed computations. */
   269      * This is the long-jump function for the generator. It is equivalent to 2**192 calls to next();
   263 
   270      * it can be used to generate 2**64 starting points, from each of which jump() will generate
   264     public void leap() { jumpAlgorithm(LEAP_TABLE); }
   271      * 2**64 non-overlapping subsequences for parallel distributed computations.
       
   272      */
       
   273     public void leap() {
       
   274         jumpAlgorithm(LEAP_TABLE);
       
   275     }
   265 
   276 
   266     private void jumpAlgorithm(long[] table) {
   277     private void jumpAlgorithm(long[] table) {
   267 	long s0 = 0, s1 = 0, s2 = 0, s3 = 0;
   278         long s0 = 0, s1 = 0, s2 = 0, s3 = 0;
   268 	for (int i = 0; i < table.length; i++) {
   279         for (int i = 0; i < table.length; i++) {
   269 	    for (int b = 0; b < 64; b++) {
   280             for (int b = 0; b < 64; b++) {
   270 		if ((table[i] & (1L << b)) != 0) {
   281                 if ((table[i] & (1L << b)) != 0) {
   271 		    s0 ^= x0;
   282                     s0 ^= x0;
   272 		    s1 ^= x1;
   283                     s1 ^= x1;
   273 		    s2 ^= x2;
   284                     s2 ^= x2;
   274 		    s3 ^= x3;
   285                     s3 ^= x3;
   275 		}
   286                 }
   276 		nextLong();
   287                 nextLong();
   277 	    }
   288             }
   278 	    x0 = s0;
   289             x0 = s0;
   279 	    x1 = s1;
   290             x1 = s1;
   280 	    x2 = s2;
   291             x2 = s2;
   281 	    x3 = s3;
   292             x3 = s3;
   282 	}
   293         }
   283     }
   294     }
   284 
   295 
   285 }
   296 }