newrandom/Xoroshiro128Plus.java
branchbriangoetz-test-branch
changeset 57369 6d87e9f7a1ec
equal deleted inserted replaced
57366:c646b256fbcc 57369:6d87e9f7a1ec
       
     1 /*
       
     2  * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
       
     3  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
       
     4  *
       
     5  *
       
     6  *
       
     7  *
       
     8  *
       
     9  *
       
    10  *
       
    11  *
       
    12  *
       
    13  *
       
    14  *
       
    15  *
       
    16  *
       
    17  *
       
    18  *
       
    19  *
       
    20  *
       
    21  *
       
    22  *
       
    23  *
       
    24  */
       
    25 
       
    26 // package java.util;
       
    27 
       
    28 import java.math.BigInteger;
       
    29 import java.util.concurrent.atomic.AtomicLong;
       
    30 
       
    31 /**
       
    32  * A generator of uniform pseudorandom values applicable for use in
       
    33  * (among other contexts) isolated parallel computations that may
       
    34  * generate subtasks.  Class {@code Xoroshiro128Plus} implements
       
    35  * interfaces {@link java.util.Rng} and {@link java.util.LeapableRng},
       
    36  * and therefore supports methods for producing pseudorandomly chosen
       
    37  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
       
    38  * as well as creating new {@code Xoroshiro128Plus} objects
       
    39  * by "jumping" or "leaping".
       
    40  *
       
    41  * <p>Series of generated values pass the TestU01 BigCrush and PractRand test suites
       
    42  * that measure independence and uniformity properties of random number generators,
       
    43  * <em>except</em> that it does not pass the binary rank tests of PractRand,
       
    44  * which fail due to the lowest bit being an LFSR; all other bits pass all tests.
       
    45  * For this reason may be best for some purposes to use this generator to generate
       
    46  * pseudorandom {@code int}, {@code float}, and {@code double} values but not
       
    47  * {@code long} values.  For the same reason, it may be best not to use the
       
    48  * method {@code nextGaussian} or {@code nextExponential} with this generator.
       
    49  *
       
    50  * <p>The class {@code Xoroshiro128Plus} uses the {@code xoroshiro128} algorithm,
       
    51  * version 1.0 (parameters 24, 16, 37), with the "+" scrambler
       
    52  * (the returned value is the sum of the two state variables {@code x0} and {@code x1}).
       
    53  * Its state consists of two {@code long} fields {@code x0} and {@code x1},
       
    54  * which can take on any values provided that they are not both zero.
       
    55  * The period of this generator is 2<sup>128</sup>-1.
       
    56  *
       
    57  * <p>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>128</sup>-1,
       
    59  * each nonzero {@code long} value is generated 2<sup>64</sup> times,
       
    60  * but the value 0 is generated only 2<sup>64</sup>-1 times.
       
    61  * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()}
       
    62  * methods are likewise equidistributed.
       
    63  *
       
    64  * <p>Instances {@code Xoroshiro128Plus} are <em>not</em> thread-safe.
       
    65  * They are designed to be used so that each thread as its own instance.
       
    66  * The methods {@link #jump} and {@link #leap} and {@link #jumps} and {@link #leaps}
       
    67  * can be used to construct new instances of {@code Xoroshiro128Plus} that traverse
       
    68  * other parts of the state cycle.
       
    69  *
       
    70  * <p>Instances of {@code Xoroshiro128Plus} are not cryptographically
       
    71  * secure.  Consider instead using {@link java.security.SecureRandom}
       
    72  * in security-sensitive applications. Additionally,
       
    73  * default-constructed instances do not use a cryptographically random
       
    74  * seed unless the {@linkplain System#getProperty system property}
       
    75  * {@code java.util.secureRandomSeed} is set to {@code true}.
       
    76  *
       
    77  * @author  Guy Steele
       
    78  * @author  Doug Lea
       
    79  * @since   1.8
       
    80  */
       
    81 public final class Xoroshiro128Plus implements LeapableRng {
       
    82 
       
    83     /*
       
    84      * Implementation Overview.
       
    85      *
       
    86      * This is an implementation of the xoroshiro128+ algorithm written
       
    87      * in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org),
       
    88      * and updated with improved parameters in 2018.
       
    89      * See http://xoshiro.di.unimi.it and these two papers:
       
    90      *
       
    91      *    Sebastiano Vigna. 2016. An Experimental Exploration of Marsaglia's
       
    92      *    xorshift Generators, Scrambled. ACM Transactions on Mathematical
       
    93      *    Software 42, 4, Article 30 (June 2016), 23 pages.
       
    94      *    https://doi.org/10.1145/2845077
       
    95      *
       
    96      *    David Blackman and Sebastiano Vigna.  2018.  Scrambled Linear
       
    97      *    Pseudorandom Number Generators.  Computing Research Repository (CoRR).
       
    98      *    http://arxiv.org/abs/1805.01407
       
    99      *
       
   100      * The jump operation moves the current generator forward by 2*64
       
   101      * steps; this has the same effect as calling nextLong() 2**64
       
   102      * times, but is much faster.  Similarly, the leap operation moves
       
   103      * the current generator forward by 2*96 steps; this has the same
       
   104      * effect as calling nextLong() 2**96 times, but is much faster.
       
   105      * The copy method may be used to make a copy of the current
       
   106      * generator.  Thus one may repeatedly and cumulatively copy and
       
   107      * jump to produce a sequence of generators whose states are well
       
   108      * spaced apart along the overall state cycle (indeed, the jumps()
       
   109      * and leaps() methods each produce a stream of such generators).
       
   110      * The generators can then be parceled out to other threads.
       
   111      *
       
   112      * File organization: First the non-public methods that constitute the
       
   113      * main algorithm, then the public methods.  Note that many methods are
       
   114      * defined by classes {@code AbstractJumpableRng} and {@code AbstractRng}.
       
   115      */
       
   116 
       
   117     /* ---------------- static fields ---------------- */
       
   118 
       
   119     /**
       
   120      * The seed generator for default constructors.
       
   121      */
       
   122     private static final AtomicLong defaultGen = new AtomicLong(RngSupport.initialSeed());
       
   123 
       
   124     /*
       
   125      * The period of this generator, which is 2**128 - 1.
       
   126      */
       
   127     private static final BigInteger thePeriod =
       
   128 	BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE);
       
   129 
       
   130     /* ---------------- instance fields ---------------- */
       
   131 
       
   132     /**
       
   133      * The per-instance state.
       
   134      * At least one of the two fields x0 and x1 must be nonzero.
       
   135      */
       
   136     private long x0, x1;
       
   137 
       
   138     /* ---------------- constructors ---------------- */
       
   139 
       
   140     /**
       
   141      * Basic constructor that initializes all fields from parameters.
       
   142      * It then adjusts the field values if necessary to ensure that
       
   143      * all constraints on the values of fields are met.
       
   144      */
       
   145     public Xoroshiro128Plus(long x0, long x1) {
       
   146 	this.x0 = x0;
       
   147         this.x1 = x1;
       
   148 	// If x0 and x1 are both zero, we must choose nonzero values.
       
   149         if ((x0 | x1) == 0) {
       
   150 	    // At least one of the two values generated here will be nonzero.
       
   151 	    this.x0 = RngSupport.mixStafford13(x0 += RngSupport.GOLDEN_RATIO_64);
       
   152 	    this.x1 = (x0 += RngSupport.GOLDEN_RATIO_64);
       
   153 	}
       
   154     }
       
   155 
       
   156     /**
       
   157      * Creates a new instance of {@code Xoroshiro128Plus} using the
       
   158      * specified {@code long} value as the initial seed. Instances of
       
   159      * {@code Xoroshiro128Plus} created with the same seed in the same
       
   160      * program generate identical sequences of values.
       
   161      *
       
   162      * @param seed the initial seed
       
   163      */
       
   164     public Xoroshiro128Plus(long seed) {
       
   165 	// Using a value with irregularly spaced 1-bits to xor the seed
       
   166 	// argument tends to improve "pedestrian" seeds such as 0 or
       
   167 	// other small integers.  We may as well use SILVER_RATIO_64.
       
   168 	//
       
   169 	// The x values are then filled in as if by a SplitMix PRNG with
       
   170 	// GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
       
   171         this(RngSupport.mixStafford13(seed ^= RngSupport.SILVER_RATIO_64),
       
   172 	     RngSupport.mixStafford13(seed + RngSupport.GOLDEN_RATIO_64));
       
   173     }
       
   174 
       
   175     /**
       
   176      * Creates a new instance of {@code Xoroshiro128Plus} that is likely to
       
   177      * generate sequences of values that are statistically independent
       
   178      * of those of any other instances in the current program execution,
       
   179      * but may, and typically does, vary across program invocations.
       
   180      */
       
   181     public Xoroshiro128Plus() {
       
   182 	// Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
       
   183         this(defaultGen.getAndAdd(RngSupport.GOLDEN_RATIO_64));
       
   184     }
       
   185 
       
   186     /**
       
   187      * Creates a new instance of {@code Xoroshiro128Plus} using the specified array of
       
   188      * initial seed bytes. Instances of {@code Xoroshiro128Plus} created with the same
       
   189      * seed array in the same program execution generate identical sequences of values.
       
   190      *
       
   191      * @param seed the initial seed
       
   192      */
       
   193     public Xoroshiro128Plus(byte[] seed) {
       
   194 	// Convert the seed to 2 long values, which are not both zero.
       
   195 	long[] data = RngSupport.convertSeedBytesToLongs(seed, 2, 2);
       
   196 	long x0 = data[0], x1 = data[1];
       
   197         this.x0 = x0;
       
   198         this.x1 = x1;
       
   199     }
       
   200     
       
   201     /* ---------------- public methods ---------------- */
       
   202 
       
   203     public Xoroshiro128Plus copy() { return new Xoroshiro128Plus(x0, x1); }
       
   204 
       
   205 /*  
       
   206 
       
   207 To the extent possible under law, the author has dedicated all copyright
       
   208 and related and neighboring rights to this software to the public domain
       
   209 worldwide. This software is distributed without any warranty.
       
   210 
       
   211 See <http://creativecommons.org/publicdomain/zero/1.0/>. */
       
   212 
       
   213 /* This is the successor to xorshift128+. It is the fastest full-period
       
   214    generator passing BigCrush without systematic failures, but due to the
       
   215    relatively short period it is acceptable only for applications with a
       
   216    mild amount of parallelism; otherwise, use a xorshift1024* generator.
       
   217 
       
   218    Beside passing BigCrush, this generator passes the PractRand test suite
       
   219    up to (and included) 16TB, with the exception of binary rank tests,
       
   220    which fail due to the lowest bit being an LFSR; all other bits pass all
       
   221    tests. We suggest to use a sign test to extract a random Boolean value.
       
   222    
       
   223    Note that the generator uses a simulated rotate operation, which most C
       
   224    compilers will turn into a single instruction. In Java, you can use
       
   225    Long.rotateLeft(). In languages that do not make low-level rotation
       
   226    instructions accessible xorshift128+ could be faster.
       
   227 
       
   228    The state must be seeded so that it is not everywhere zero. If you have
       
   229    a 64-bit seed, we suggest to seed a splitmix64 generator and use its
       
   230    output to fill s. */
       
   231 
       
   232 
       
   233     /**
       
   234      * Returns a pseudorandom {@code long} value.
       
   235      *
       
   236      * @return a pseudorandom {@code long} value
       
   237      */
       
   238     public long nextLong() {
       
   239 	final long s0 = x0;
       
   240 	long s1 = x1;
       
   241 	final long z = s0 + s1;
       
   242 
       
   243 	s1 ^= s0;
       
   244 	x0 = Long.rotateLeft(s0, 24) ^ s1 ^ (s1 << 16); // a, b
       
   245 	x1 = Long.rotateLeft(s1, 37); // c
       
   246 
       
   247 	return z;
       
   248     }
       
   249 
       
   250     public BigInteger period() { return thePeriod; }
       
   251 
       
   252     public double defaultJumpDistance() { return 0x1.0p64; }
       
   253 
       
   254     public double defaultLeapDistance() { return 0x1.0p96; }
       
   255 
       
   256     private static final long[] JUMP_TABLE = { 0xdf900294d8f554a5L, 0x170865df4b3201fcL };
       
   257     
       
   258     private static final long[] LEAP_TABLE = { 0xd2a98b26625eee7bL, 0xdddf9b1090aa7ac1L };
       
   259    
       
   260 /* This is the jump function for the generator. It is equivalent
       
   261    to 2**64 calls to nextLong(); it can be used to generate 2**64
       
   262    non-overlapping subsequences for parallel computations. */
       
   263 
       
   264     public void jump() { jumpAlgorithm(JUMP_TABLE); }
       
   265     
       
   266 /* This is the long-jump function for the generator. It is equivalent to
       
   267    2**96 calls to next(); it can be used to generate 2**32 starting points,
       
   268    from each of which jump() will generate 2**32 non-overlapping
       
   269    subsequences for parallel distributed computations. */
       
   270 
       
   271     public void leap() { jumpAlgorithm(LEAP_TABLE); }
       
   272 
       
   273     private void jumpAlgorithm(long[] table) {
       
   274 	long s0 = 0, s1 = 0;
       
   275 	for (int i = 0; i < table.length; i++) {
       
   276 	    for (int b = 0; b < 64; b++) {
       
   277 		if ((table[i] & (1L << b)) != 0) {
       
   278 		    s0 ^= x0;
       
   279 		    s1 ^= x1;
       
   280 		}
       
   281 		nextLong();
       
   282 	    }
       
   283 	    x0 = s0;
       
   284 	    x1 = s1;
       
   285 	}
       
   286     }
       
   287 }