newrandom/LeapableRng.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 // package java.util;
       
    26 
       
    27 import java.math.BigInteger;
       
    28 import java.util.stream.Stream;
       
    29 
       
    30 /**
       
    31  * This interface is designed to provide a common protocol for objects
       
    32  * that generate sequences of pseudorandom numbers (or Boolean values)
       
    33  * and furthermore can easily not only jump but also <it>leap</it> to
       
    34  * a very distant point in the state cycle.
       
    35  *
       
    36  * Typically one will construct a series of {@code LeapableRng} objects
       
    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  */
       
    79 interface LeapableRng extends JumpableRng {
       
    80     /**
       
    81      * Returns a new generator whose internal state is an exact copy
       
    82      * of this generator (therefore their future behavior should be
       
    83      * identical if subjected to the same series of operations).
       
    84      *
       
    85      * @return a new object that is a copy of this generator
       
    86      */
       
    87     LeapableRng copy();
       
    88 
       
    89     /**
       
    90      * Alter the state of this pseudorandom number generator so as to
       
    91      * leap forward a large, fixed distance (typically 2<sup>96</sup>
       
    92      * or more) within its state cycle.
       
    93      */
       
    94     void leap();
       
    95     
       
    96     /**
       
    97      * Returns the distance by which the {@code leap()} method will leap
       
    98      * forward within the state cycle of this generator object.
       
    99      *
       
   100      * @return the default leap distance (as a {@code double} value)
       
   101      */
       
   102     double defaultLeapDistance();
       
   103 
       
   104     /**
       
   105      * Returns an effectively unlimited stream of new pseudorandom
       
   106      * number generators, each of which implements the {@code JumpableRng}
       
   107      * interface.
       
   108      *
       
   109      * @implNote It is permitted to implement this method in a manner
       
   110      * equivalent to {@code leaps(Long.MAX_VALUE)}.
       
   111      *
       
   112      * @implNote The default implementation produces a sequential stream
       
   113      * that  repeatedly calls {@code copy()} and {@code leap()} on this generator,
       
   114      * and the copies become the generators produced by the stream.
       
   115      *
       
   116      * @return a stream of objects that implement the {@code JumpableRng} interface
       
   117      */
       
   118     default Stream<JumpableRng> leaps() {
       
   119 	return Stream.generate(this::copyAndLeap).sequential();
       
   120     }
       
   121 
       
   122     /**
       
   123      * Returns a stream producing the given {@code streamSize} number of
       
   124      * new pseudorandom number generators, each of which implements the
       
   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      *
       
   131      * @param streamSize the number of generators to generate
       
   132      * @return a stream of objects that implement the {@code JumpableRng} interface
       
   133      * @throws IllegalArgumentException if {@code streamSize} is
       
   134      *         less than zero
       
   135      */
       
   136     default Stream<JumpableRng> leaps(long streamSize) {
       
   137         return leaps().limit(streamSize);
       
   138     }
       
   139         
       
   140     /**
       
   141      * Copy this generator, leap this generator forward, then return the copy.
       
   142      */
       
   143     default JumpableRng copyAndLeap() {
       
   144 	JumpableRng result = copy();
       
   145 	leap();
       
   146 	return result;
       
   147     }
       
   148 
       
   149 }