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