src/java.base/share/classes/java/util/random/LeapableRNG.java
branchJDK-8193209-branch
changeset 57437 f02ffcb61dce
parent 57436 b0c958c0e6c6
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;
       
    26 
    25 
    27 import java.math.BigInteger;
    26 package java.util.random;
       
    27 
    28 import java.util.stream.Stream;
    28 import java.util.stream.Stream;
    29 
    29 
    30 /**
    30 /**
    31  * This interface is designed to provide a common protocol for objects
    31  * This interface is designed to provide a common protocol for objects that generate sequences of
    32  * that generate sequences of pseudorandom numbers (or Boolean values)
    32  * pseudorandom numbers (or Boolean values) and furthermore can easily not only jump but also
    33  * and furthermore can easily not only jump but also <i>leap</i> to
    33  * <i>leap</i> to a very distant point in the state cycle.
    34  * a very distant point in the state cycle.
    34  * <p>
       
    35  * Typically one will construct a series of {@link LeapableRNG} objects by iterative leaping from a
       
    36  * single original {@link LeapableRNG} object, and then for each such object produce a subseries of
       
    37  * objects by iterative jumping.  There is little conceptual difference between leaping and jumping,
       
    38  * but typically a leap will be a very long jump in the state cycle (perhaps distance
       
    39  * 2<sup>128</sup> or so).
       
    40  * <p>
       
    41  * Ideally, all {@link LeapableRNG} objects produced by iterative leaping and jumping from a single
       
    42  * original {@link LeapableRNG} object are statistically independent of one another and individually
       
    43  * uniform. In practice, one must settle for some approximation to independence and uniformity.  In
       
    44  * particular, a specific implementation may assume that each generator in a stream produced by the
       
    45  * {@code leaps} method is used to produce (by jumping) a number of objects no larger than
       
    46  * 2<sup>64</sup>.  Implementors are advised to use algorithms whose period is at least
       
    47  * 2<sup>191</sup>.
       
    48  * <p>
       
    49  * Methods are provided to perform a single leap operation and also to produce a stream of
       
    50  * generators produced from the original by iterative copying and leaping of internal state.  The
       
    51  * generators produced must implement the {@link JumpableRNG} interface but need not also implement
       
    52  * the {@link LeapableRNG} interface.  A typical strategy for a multithreaded application is to
       
    53  * create a single {@link LeapableRNG} object, calls its {@code leaps} method exactly once, and then
       
    54  * parcel out generators from the resulting stream, one to each thread.  Then the {@code jumps}
       
    55  * method of each such generator be called to produce a substream of generator objects.
       
    56  * <p>
       
    57  * An implementation of the {@link LeapableRNG} interface must provide concrete definitions for the
       
    58  * methods {@code nextInt()}, {@code nextLong}, {@code period()}, {@code copy()}, {@code jump()},
       
    59  * {@code defaultJumpDistance()}, {@code leap()}, and {@code defaultLeapDistance()}. Default
       
    60  * implementations are provided for all other methods.
       
    61  * <p>
       
    62  * Objects that implement {@link LeapableRNG} are typically not cryptographically secure.  Consider
       
    63  * instead using {@link java.security.SecureRandom} to get a cryptographically secure pseudo-random
       
    64  * number generator for use by security-sensitive applications.
    35  *
    65  *
    36  * Typically one will construct a series of {@code LeapableRng} objects
    66  * @since 14
    37  * by iterative leaping from a single original {@code LeapableRng}
       
    38  * object, and then for each such object produce a subseries of objects
       
    39  * by iterative jumping.  There is little conceptual difference between
       
    40  * leaping and jumping, but typically a leap will be a very long jump
       
    41  * in the state cycle (perhaps distance 2<sup>128</sup> or so).
       
    42  *
       
    43  * <p>Ideally, all {@code LeapableRng} objects produced by iterative
       
    44  * leaping and jumping from a single original {@code LeapableRng} object
       
    45  * are statistically independent of one another and individually uniform.
       
    46  * In practice, one must settle for some approximation to independence
       
    47  * and uniformity.  In particular, a specific implementation may
       
    48  * assume that each generator in a stream produced by the {@code leaps}
       
    49  * method is used to produce (by jumping) a number of objects no larger
       
    50  * than 2<sup>64</sup>.  Implementors are advised to use algorithms
       
    51  * whose period is at least 2<sup>191</sup>.
       
    52  *
       
    53  * <p>Methods are provided to perform a single leap operation and also
       
    54  * to produce a stream of generators produced from the original by
       
    55  * iterative copying and leaping of internal state.  The generators
       
    56  * produced must implement the {@code JumpableRng} interface but need
       
    57  * not also implement the {@code LeapableRng} interface.  A typical
       
    58  * strategy for a multithreaded application is to create a single
       
    59  * {@code LeapableRng} object, calls its {@code leaps} method exactly
       
    60  * once, and then parcel out generators from the resulting stream, one
       
    61  * to each thread.  Then the {@code jumps} method of each such generator
       
    62  * be called to produce a substream of generator objects.
       
    63  *
       
    64  * <p>An implementation of the {@code LeapableRng} interface must provide
       
    65  * concrete definitions for the methods {@code nextInt()}, {@code nextLong},
       
    66  * {@code period()}, {@code copy()}, {@code jump()}, {@code defaultJumpDistance()},
       
    67  * {@code leap()}, and {@code defaultLeapDistance()}.
       
    68  * Default implementations are provided for all other methods.
       
    69  *
       
    70  * <p>Objects that implement {@code java.util.LeapableRng} are
       
    71  * typically not cryptographically secure.  Consider instead using
       
    72  * {@link java.security.SecureRandom} to get a cryptographically
       
    73  * secure pseudo-random number generator for use by
       
    74  * security-sensitive applications.
       
    75  *
       
    76  * @author  Guy Steele
       
    77  * @since   1.9
       
    78  */
    67  */
    79 public interface LeapableRng extends JumpableRng {
    68 public interface LeapableRNG extends JumpableRNG {
    80     /**
    69     /**
    81      * Returns a new generator whose internal state is an exact copy
    70      * Returns a new generator whose internal state is an exact copy of this generator (therefore
    82      * of this generator (therefore their future behavior should be
    71      * their future behavior should be identical if subjected to the same series of operations).
    83      * identical if subjected to the same series of operations).
       
    84      *
    72      *
    85      * @return a new object that is a copy of this generator
    73      * @return a new object that is a copy of this generator
    86      */
    74      */
    87     LeapableRng copy();
    75     LeapableRNG copy();
    88 
    76 
    89     /**
    77     /**
    90      * Alter the state of this pseudorandom number generator so as to
    78      * Alter the state of this pseudorandom number generator so as to leap forward a large, fixed
    91      * leap forward a large, fixed distance (typically 2<sup>96</sup>
    79      * distance (typically 2<sup>96</sup> or more) within its state cycle.
    92      * or more) within its state cycle.
       
    93      */
    80      */
    94     void leap();
    81     void leap();
    95     
    82 
    96     /**
    83     /**
    97      * Returns the distance by which the {@code leap()} method will leap
    84      * Returns the distance by which the {@code leap()} method will leap forward within the state
    98      * forward within the state cycle of this generator object.
    85      * cycle of this generator object.
    99      *
    86      *
   100      * @return the default leap distance (as a {@code double} value)
    87      * @return the default leap distance (as a {@code double} value)
   101      */
    88      */
   102     double defaultLeapDistance();
    89     double defaultLeapDistance();
   103 
    90 
   104     /**
    91     /**
   105      * Returns an effectively unlimited stream of new pseudorandom
    92      * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
   106      * number generators, each of which implements the {@code JumpableRng}
    93      * implements the {@link JumpableRNG} interface.
   107      * interface.
       
   108      *
    94      *
   109      * @implNote It is permitted to implement this method in a manner
    95      * @return a stream of objects that implement the {@link JumpableRNG} interface
   110      * equivalent to {@code leaps(Long.MAX_VALUE)}.
       
   111      *
    96      *
   112      * @implNote The default implementation produces a sequential stream
    97      * @implNote It is permitted to implement this method in a manner equivalent to {@code
   113      * that  repeatedly calls {@code copy()} and {@code leap()} on this generator,
    98      *         leaps(Long.MAX_VALUE)}.
   114      * and the copies become the generators produced by the stream.
    99      * @implNote The default implementation produces a sequential stream that  repeatedly
   115      *
   100      *         calls {@code copy()} and {@code leap()} on this generator, and the copies become the
   116      * @return a stream of objects that implement the {@code JumpableRng} interface
   101      *         generators produced by the stream.
   117      */
   102      */
   118     default Stream<JumpableRng> leaps() {
   103     default Stream<JumpableRNG> leaps() {
   119 	return Stream.generate(this::copyAndLeap).sequential();
   104         return Stream.generate(this::copyAndLeap).sequential();
   120     }
   105     }
   121 
   106 
   122     /**
   107     /**
   123      * Returns a stream producing the given {@code streamSize} number of
   108      * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
   124      * new pseudorandom number generators, each of which implements the
   109      * generators, each of which implements the {@link JumpableRNG} interface.
   125      * {@code JumpableRng} interface.
       
   126      *
       
   127      * @implNote The default implementation produces a sequential stream
       
   128      * that  repeatedly calls {@code copy()} and {@code leap()} on this generator,
       
   129      * and the copies become the generators produced by the stream.
       
   130      *
   110      *
   131      * @param streamSize the number of generators to generate
   111      * @param streamSize the number of generators to generate
   132      * @return a stream of objects that implement the {@code JumpableRng} interface
   112      *
   133      * @throws IllegalArgumentException if {@code streamSize} is
   113      * @return a stream of objects that implement the {@link JumpableRNG} interface
   134      *         less than zero
   114      *
       
   115      * @throws IllegalArgumentException if {@code streamSize} is less than zero
       
   116      * @implNote The default implementation produces a sequential stream that  repeatedly
       
   117      *         calls {@code copy()} and {@code leap()} on this generator, and the copies become the
       
   118      *         generators produced by the stream.
   135      */
   119      */
   136     default Stream<JumpableRng> leaps(long streamSize) {
   120     default Stream<JumpableRNG> leaps(long streamSize) {
   137         return leaps().limit(streamSize);
   121         return leaps().limit(streamSize);
   138     }
   122     }
   139         
   123 
   140     /**
   124     /**
   141      * Copy this generator, leap this generator forward, then return the copy.
   125      * Copy this generator, leap this generator forward, then return the copy.
   142      *
   126      *
   143      * @return a copy of this generator object before the leap occurred
   127      * @return a copy of this generator object before the leap occurred
   144      */
   128      */
   145     default JumpableRng copyAndLeap() {
   129     default JumpableRNG copyAndLeap() {
   146 	JumpableRng result = copy();
   130         JumpableRNG result = copy();
   147 	leap();
   131         leap();
   148 	return result;
   132         return result;
   149     }
   133     }
   150 
   134 
   151 }
   135 }