newrandom/ArbitrarilyJumpableRng.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.util.stream.Stream;
       
    28 import java.util.stream.StreamSupport;
       
    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 <it>jump</it> to an arbitrarily specified
       
    34  * distant point in the state cycle.
       
    35  *
       
    36  * <p>Ideally, all {@code ArbitrarilyJumpableRng} objects produced by
       
    37  * iterative jumping from a single original {@code ArbtrarilyJumpableRng}
       
    38  * object are statistically independent of one another and
       
    39  * individually uniform, provided that they do not traverse
       
    40  * overlapping portions of the state cycle.  In practice, one must
       
    41  * settle for some approximation to independence and uniformity.  In
       
    42  * particular, a specific implementation may assume that each
       
    43  * generator in a stream produced by the {@code jumps} method is used
       
    44  * to produce a number of values no larger than the jump distance
       
    45  * specified.  Implementors are advised to use algorithms whose period
       
    46  * is at least 2<sup>127</sup>.
       
    47  *
       
    48  * <p>For many applications, it suffices to jump forward by a power of
       
    49  * two or some small multiple of a power of two, but this power of two
       
    50  * may not be representable as a {@code long} value.  To avoid the
       
    51  * use of {@code BigInteger} values as jump distances, {@code double}
       
    52  * values are used instead.
       
    53  *
       
    54  * <p>Methods are provided to perform a single jump operation and also
       
    55  * to produce a stream of generators produced from the original by
       
    56  * iterative copying and jumping of internal state.  A typical
       
    57  * strategy for a multithreaded application is to create a single
       
    58  * {@code ArbitrarilyJumpableRng} object, call its {@code jumps}
       
    59  * method exactly once, and then parcel out generators from the
       
    60  * resulting stream, one to each thread.  However, each generator
       
    61  * produced also has type {@code ArbitrarilyJumpableRng}; with care,
       
    62  * different jump distances can be used to traverse the entire
       
    63  * state cycle in various ways.
       
    64  *
       
    65  * <p>An implementation of the {@code ArbitrarilyJumpableRng} interface must
       
    66  * provide concrete definitions for the methods {@code nextInt()},
       
    67  * {@code nextLong}, {@code period()}, {@code copy()}, {@code jump(double)},
       
    68  * {@code defaultJumpDistance()}, and {@code defaultLeapDistance()}.
       
    69  * Default implementations are provided for all other methods.
       
    70  * Perhaps the most convenient
       
    71  * way to implement this interface is to extend the abstract class
       
    72  * {@link java.util.AbstractArbitrarilyJumpableRng}, which provides
       
    73  * spliterator-based implementations of the methods {@code ints}, {@code longs},
       
    74  * {@code doubles}, {@code rngs}, {@code jumps}, and {@code leaps}.
       
    75  *
       
    76  * <p>Objects that implement {@code java.util.ArbitrarilyJumpableRng}
       
    77  * are typically not cryptographically secure.  Consider instead using
       
    78  * {@link java.security.SecureRandom} to get a cryptographically
       
    79  * secure pseudo-random number generator for use by
       
    80  * security-sensitive applications.
       
    81  *
       
    82  * @author  Guy Steele
       
    83  * @since   1.9
       
    84  */
       
    85 interface ArbitrarilyJumpableRng extends LeapableRng {
       
    86     /**
       
    87      * Returns a new generator whose internal state is an exact copy
       
    88      * of this generator (therefore their future behavior should be
       
    89      * identical if subjected to the same series of operations).
       
    90      *
       
    91      * @return a new object that is a copy of this generator
       
    92      */
       
    93     ArbitrarilyJumpableRng copy();
       
    94 
       
    95     /**
       
    96      * Alter the state of this pseudorandom number generator so as to
       
    97      * jump forward a distance equal to 2<sup>{@code logDistance}</sup>
       
    98      * within its state cycle.
       
    99      *
       
   100      * @param logDistance the base-2 logarithm of the distance to jump
       
   101      *        forward within the state cycle
       
   102      * @throws IllegalArgumentException if {@code logDistance} is NaN
       
   103      *         or negative, or if 2<sup>{@code logDistance}</sup> is
       
   104      *         greater than the period of this generator
       
   105      */
       
   106     void jumpPowerOfTwo(int logDistance);
       
   107 
       
   108     /**
       
   109      * Alter the state of this pseudorandom number generator so as to
       
   110      * jump forward a specified distance within its state cycle.
       
   111      *
       
   112      * @param distance the distance to jump forward within the state cycle
       
   113      * @throws IllegalArgumentException if {@code distance} is Nan,
       
   114      *         negative, or greater than the period of this generator
       
   115      */
       
   116     void jump(double distance);
       
   117 
       
   118     /**
       
   119      * Alter the state of this pseudorandom number generator so as to
       
   120      * jump forward a large, fixed distance (typically 2<sup>64</sup>
       
   121      * or more) within its state cycle.  The distance used is that
       
   122      * returned by method {@code defaultJumpDistance()}.
       
   123      */
       
   124     default void jump() { jump(defaultJumpDistance()); }
       
   125     
       
   126     /**
       
   127      * Returns an effectively unlimited stream of new pseudorandom
       
   128      * number generators, each of which implements the {@code ArbitrarilyJumpableRng}
       
   129      * interface, produced by jumping copies of this generator
       
   130      * by different integer multiples of the specified jump distance.
       
   131      *
       
   132      * @implNote This method is implemented to be equivalent to
       
   133      * {@code jumps(Long.MAX_VALUE)}.
       
   134      *
       
   135      * @param distance a distance to jump forward within the state cycle
       
   136      * @return a stream of objects that implement the {@code Rng} interface
       
   137      */
       
   138     default Stream<ArbitrarilyJumpableRng> jumps(double distance) {
       
   139 	return Stream.generate(() -> copyAndJump(distance)).sequential();
       
   140     }
       
   141 
       
   142     /**
       
   143      * Returns a stream producing the given {@code streamSize} number of
       
   144      * new pseudorandom number generators, each of which implements the
       
   145      * {@code ArbitrarilyJumpableRng} interface, produced by jumping copies of this generator
       
   146      * by different integer multiples of the specified jump distance.
       
   147      *
       
   148      * @param streamSize the number of generators to generate
       
   149      * @param distance a distance to jump forward within the state cycle
       
   150      * @return a stream of objects that implement the {@code Rng} interface
       
   151      * @throws IllegalArgumentException if {@code streamSize} is
       
   152      *         less than zero
       
   153      */
       
   154     default Stream<ArbitrarilyJumpableRng> jumps(long streamSize, double distance) {
       
   155         return jumps(distance).limit(streamSize);
       
   156     }
       
   157 
       
   158     /**
       
   159      * Alter the state of this pseudorandom number generator so as to
       
   160      * jump forward a very large, fixed distance (typically 2<sup>128</sup>
       
   161      * or more) within its state cycle.  The distance used is that
       
   162      * returned by method {@code defaultJLeapDistance()}.
       
   163      */
       
   164     default void leap() { jump(defaultLeapDistance()); }
       
   165      
       
   166     /**
       
   167      * Copy this generator, jump this generator forward, then return the copy.
       
   168      */
       
   169     default ArbitrarilyJumpableRng copyAndJump(double distance) {
       
   170 	ArbitrarilyJumpableRng result = copy();
       
   171 	jump(distance);
       
   172 	return result;
       
   173     }
       
   174 
       
   175 }