src/java.base/share/classes/java/util/random/LeapableRNG.java
branchJDK-8193209-branch
changeset 57547 56cbdc3ea079
parent 57546 1ca1cfdcb451
child 57671 6a4be8bf8990
equal deleted inserted replaced
57546:1ca1cfdcb451 57547:56cbdc3ea079
     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 
       
    26 package java.util.random;
       
    27 
       
    28 import java.util.stream.Stream;
       
    29 
       
    30 /**
       
    31  * This interface is designed to provide a common protocol for objects that generate sequences of
       
    32  * pseudorandom numbers (or Boolean values) and furthermore can easily not only jump but also
       
    33  * <i>leap</i> to 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.
       
    65  *
       
    66  * @since 14
       
    67  */
       
    68 public interface LeapableRNG extends JumpableRNG {
       
    69     /**
       
    70      * Returns a new generator whose internal state is an exact copy of this generator (therefore
       
    71      * their future behavior should be identical if subjected to the same series of operations).
       
    72      *
       
    73      * @return a new object that is a copy of this generator
       
    74      */
       
    75     LeapableRNG copy();
       
    76 
       
    77     /**
       
    78      * Alter the state of this pseudorandom number generator so as to leap forward a large, fixed
       
    79      * distance (typically 2<sup>96</sup> or more) within its state cycle.
       
    80      */
       
    81     void leap();
       
    82 
       
    83     /**
       
    84      * Returns the distance by which the {@code leap()} method will leap forward within the state
       
    85      * cycle of this generator object.
       
    86      *
       
    87      * @return the default leap distance (as a {@code double} value)
       
    88      */
       
    89     double defaultLeapDistance();
       
    90 
       
    91     /**
       
    92      * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
       
    93      * implements the {@link JumpableRNG} interface.
       
    94      *
       
    95      * @return a stream of objects that implement the {@link JumpableRNG} interface
       
    96      *
       
    97      * @implNote It is permitted to implement this method in a manner equivalent to {@code
       
    98      *         leaps(Long.MAX_VALUE)}.
       
    99      * @implNote The default implementation produces a sequential stream that  repeatedly
       
   100      *         calls {@code copy()} and {@code leap()} on this generator, and the copies become the
       
   101      *         generators produced by the stream.
       
   102      */
       
   103     default Stream<JumpableRNG> leaps() {
       
   104         return Stream.generate(this::copyAndLeap).sequential();
       
   105     }
       
   106 
       
   107     /**
       
   108      * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
       
   109      * generators, each of which implements the {@link JumpableRNG} interface.
       
   110      *
       
   111      * @param streamSize the number of generators to generate
       
   112      *
       
   113      * @return a stream of objects that implement the {@link JumpableRNG} interface
       
   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.
       
   119      */
       
   120     default Stream<JumpableRNG> leaps(long streamSize) {
       
   121         return leaps().limit(streamSize);
       
   122     }
       
   123 
       
   124     /**
       
   125      * Copy this generator, leap this generator forward, then return the copy.
       
   126      *
       
   127      * @return a copy of this generator object before the leap occurred
       
   128      */
       
   129     default JumpableRNG copyAndLeap() {
       
   130         JumpableRNG result = copy();
       
   131         leap();
       
   132         return result;
       
   133     }
       
   134 
       
   135 }