newrandom/JumpableRng.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 pseudorandom sequences of numbers (or Boolean values)
       
    33  * and furthermore can easily <it>jump</it> forward (by a fixed amount)
       
    34  * to a distant point in the state cycle.
       
    35  *
       
    36  * <p>Ideally, all {@code JumpableRng} objects produced by iterative
       
    37  * jumping from a single original {@code JumpableRng} object are
       
    38  * statistically independent of one another and individually uniform.
       
    39  * In practice, one must settle for some approximation to independence
       
    40  * and uniformity.  In particular, a specific implementation may
       
    41  * assume that each generator in a stream produced by the {@code jumps}
       
    42  * method is used to produce a number of values no larger than either
       
    43  * 2<sup>64</sup> or the square root of its period.  Implementors are
       
    44  * advised to use algorithms whose period is at least 2<sup>127</sup>.
       
    45  *
       
    46  * <p>Methods are provided to perform a single jump operation and also
       
    47  * to produce a stream of generators produced from the original by
       
    48  * iterative copying and jumping of internal state.  A typical
       
    49  * strategy for a multithreaded application is to create a single
       
    50  * {@code JumpableRng} object, calls its {@code jumps} method exactly
       
    51  * once, and then parcel out generators from the resulting stream, one
       
    52  * to each thread.  It is generally not a good idea to call {@code jump}
       
    53  * on a generator that was itself produced by the {@code jumps} method,
       
    54  * because the result may be a generator identical to another
       
    55  * generator already produce by that call to the {@code jumps} method.
       
    56  * For this reason, the return type of the {@code jumps} method is
       
    57  * {@code Stream<Rng>} rather than {@code Stream<JumpableRng>}, even
       
    58  * though the actual generator objects in that stream likely do also
       
    59  * implement the {@code JumpableRng} interface.
       
    60  *
       
    61  * <p>An implementation of the {@code JumpableRng} interface must provide
       
    62  * concrete definitions for the methods {@code nextInt()}, {@code nextLong},
       
    63  * {@code period()}, {@code copy()}, {@code jump()}, and {@code defaultJumpDistance()}.
       
    64  * Default implementations are provided for all other methods.
       
    65  *
       
    66  * <p>Objects that implement {@code java.util.JumpableRng} are
       
    67  * typically not cryptographically secure.  Consider instead using
       
    68  * {@link java.security.SecureRandom} to get a cryptographically
       
    69  * secure pseudo-random number generator for use by
       
    70  * security-sensitive applications.
       
    71  *
       
    72  * @author  Guy Steele
       
    73  * @since   1.9
       
    74  */
       
    75 interface JumpableRng extends StreamableRng {
       
    76     /**
       
    77      * Returns a new generator whose internal state is an exact copy
       
    78      * of this generator (therefore their future behavior should be
       
    79      * identical if subjected to the same series of operations).
       
    80      *
       
    81      * @return a new object that is a copy of this generator
       
    82      */
       
    83     JumpableRng copy();
       
    84 
       
    85     /**
       
    86      * Alter the state of this pseudorandom number generator so as to
       
    87      * jump forward a large, fixed distance (typically 2<sup>64</sup>
       
    88      * or more) within its state cycle.
       
    89      */
       
    90     void jump();
       
    91  
       
    92     /**
       
    93      * Returns the distance by which the {@code jump()} method will jump
       
    94      * forward within the state cycle of this generator object.
       
    95      *
       
    96      * @return the default jump distance (as a {@code double} value)
       
    97      */
       
    98     double defaultJumpDistance();
       
    99 
       
   100     /**
       
   101      * Returns an effectively unlimited stream of new pseudorandom
       
   102      * number generators, each of which implements the {@code Rng}
       
   103      * interface.
       
   104      *
       
   105      * @implNote It is permitted to implement this method in a manner
       
   106      * equivalent to {@code jumps(Long.MAX_VALUE)}.
       
   107      *
       
   108      * @implNote The default implementation produces a sequential stream
       
   109      * that  repeatedly calls {@code copy()} and {@code jump()} on this generator,
       
   110      * and the copies become the generators produced by the stream.
       
   111      *
       
   112      * @return a stream of objects that implement the {@code Rng} interface
       
   113      */
       
   114     default Stream<Rng> jumps() {
       
   115 	return Stream.generate(this::copyAndJump).sequential();
       
   116     }
       
   117 
       
   118     /**
       
   119      * Returns a stream producing the given {@code streamSize} number of
       
   120      * new pseudorandom number generators, each of which implements the
       
   121      * {@code Rng} interface.
       
   122      *
       
   123      * @implNote The default implementation produces a sequential stream
       
   124      * that  repeatedly calls {@code copy()} and {@code jump()} on this generator,
       
   125      * and the copies become the generators produced by the stream.
       
   126      *
       
   127      * @param streamSize the number of generators to generate
       
   128      * @return a stream of objects that implement the {@code Rng} interface
       
   129      * @throws IllegalArgumentException if {@code streamSize} is
       
   130      *         less than zero
       
   131      */
       
   132     default Stream<Rng> jumps(long streamSize) {
       
   133         return jumps().limit(streamSize);
       
   134     }
       
   135     
       
   136     /**
       
   137      * Returns an effectively unlimited stream of new pseudorandom
       
   138      * number generators, each of which implements the {@code Rng}
       
   139      * interface.  Ideally the generators in the stream will appear
       
   140      * to be statistically independent.
       
   141      *
       
   142      * @implNote The default implementation calls {@code jumps()}.
       
   143      *
       
   144      * @return a stream of objects that implement the {@code Rng} interface
       
   145      */
       
   146     default Stream<Rng> rngs() {
       
   147 	return this.jumps();
       
   148     }
       
   149 
       
   150     /**
       
   151      * Returns a stream producing the given {@code streamSize} number of
       
   152      * new pseudorandom number generators, each of which implements the
       
   153      * {@code Rng} interface.  Ideally the generators in the stream will
       
   154      * appear to be statistically independent.
       
   155      *
       
   156      * @implNote The default implementation calls {@code jumps(streamSize)}.
       
   157      *
       
   158      * @param streamSize the number of generators to generate
       
   159      * @return a stream of objects that implement the {@code Rng} interface
       
   160      * @throws IllegalArgumentException if {@code streamSize} is
       
   161      *         less than zero
       
   162      */
       
   163     default Stream<Rng> rngs(long streamSize) {
       
   164 	return this.jumps(streamSize);
       
   165     }
       
   166 
       
   167     /**
       
   168      * Copy this generator, jump this generator forward, then return the copy.
       
   169      */
       
   170     default Rng copyAndJump() {
       
   171 	Rng result = copy();
       
   172 	jump();
       
   173 	return result;
       
   174     }
       
   175 
       
   176 }