newrandom/AbstractArbitrarilyJumpableRng.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 
       
    26 // package java.util;
       
    27 
       
    28 import java.util.Spliterator;
       
    29 import java.util.function.Consumer;
       
    30 import java.util.function.IntConsumer;
       
    31 import java.util.function.LongConsumer;
       
    32 import java.util.function.DoubleConsumer;
       
    33 import java.util.stream.StreamSupport;
       
    34 import java.util.stream.Stream;
       
    35 
       
    36 /**
       
    37  * This class provides much of the implementation of the
       
    38  * {@code ArbitrarilyJumpableRng} interface, to minimize the effort
       
    39  * required to implement that interface.
       
    40  *
       
    41  * To implement a pseudorandom number generator, the programmer needs
       
    42  * only to extend this class and provide implementations for the
       
    43  * methods {@code nextInt()}, {@code nextLong()}, {@code copy()},
       
    44  * {@code jump(distance)}, {@code jumpPowerOfTwo(distance)},
       
    45  * {@code defaultJumpDistance()}, and {@code defaultLeapDistance()}.
       
    46  *
       
    47  * (If the pseudorandom number generator also has the ability to split,
       
    48  * then the programmer may wish to consider instead extending
       
    49  * {@code AbstractSplittableArbitrarilyJumpableRng}.)
       
    50  *
       
    51  * The programmer should generally provide at least three constructors:
       
    52  * one that takes no arguments, one that accepts a {@code long}
       
    53  * seed value, and one that accepts an array of seed {@code byte} values.
       
    54  * This class provides a public {@code initialSeed()} method that may
       
    55  * be useful in initializing some static state from which to derive
       
    56  * defaults seeds for use by the no-argument constructor.
       
    57  *
       
    58  * For the stream methods (such as {@code ints()} and {@code splits()}),
       
    59  * this class provides {@code Spliterator}-based implementations that
       
    60  * allow parallel execution when appropriate.  In this respect
       
    61  * {@code ArbitrarilyJumpableRng} differs from {@code JumpableRng},
       
    62  * which provides very simple implementations that produce
       
    63  * sequential streams only.
       
    64  *
       
    65  * <p>An implementation of the {@code AbstractArbitrarilyJumpableRng} class
       
    66  * must 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  *
       
    71  * The documentation for each non-abstract method in this class
       
    72  * describes its implementation in detail. Each of these methods may
       
    73  * be overridden if the pseudorandom number generator being
       
    74  * implemented admits a more efficient implementation.
       
    75  *
       
    76  * @author  Guy Steele
       
    77  * @since   1.9
       
    78  */
       
    79 public abstract class AbstractArbitrarilyJumpableRng
       
    80     extends AbstractSpliteratorRng implements ArbitrarilyJumpableRng {
       
    81 
       
    82     /*
       
    83      * Implementation Overview.
       
    84      *
       
    85      * This class provides most of the "user API" methods needed to satisfy
       
    86      * the interface java.util.ArbitrarilyJumpableRng.  Most of these methods
       
    87      * are in turn inherited from AbstractRng and the non-public class
       
    88      * AbstractSpliteratorRng; this file implements four versions of the
       
    89      * jumps method and defines the spliterators necessary to support them.
       
    90      *
       
    91      * File organization: First the non-public methods needed by the class
       
    92      * AbstractSpliteratorRng, then the main public methods, followed by some
       
    93      * custom spliterator classes needed for stream methods.
       
    94      */
       
    95 
       
    96     // IllegalArgumentException messages
       
    97     static final String BadLogDistance  = "logDistance must be non-negative";
       
    98 
       
    99     // Methods required by class AbstractSpliteratorRng
       
   100     Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) {
       
   101 	return new RandomIntsSpliterator(this, index, fence, origin, bound);
       
   102     }
       
   103     Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound) {
       
   104 	return new RandomLongsSpliterator(this, index, fence, origin, bound);
       
   105     }
       
   106     Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound) {
       
   107 	return new RandomDoublesSpliterator(this, index, fence, origin, bound);
       
   108     }
       
   109 
       
   110     // Similar methods used by this class
       
   111     Spliterator<Rng> makeJumpsSpliterator(long index, long fence, double distance) {
       
   112 	return new RandomJumpsSpliterator(this, index, fence, distance);
       
   113     }
       
   114     Spliterator<JumpableRng> makeLeapsSpliterator(long index, long fence, double distance) {
       
   115 	return new RandomLeapsSpliterator(this, index, fence, distance);
       
   116     }
       
   117     Spliterator<ArbitrarilyJumpableRng> makeArbitraryJumpsSpliterator(long index, long fence, double distance) {
       
   118 	return new RandomArbitraryJumpsSpliterator(this, index, fence, distance);
       
   119     }
       
   120 
       
   121     /* ---------------- public methods ---------------- */
       
   122 
       
   123     /**
       
   124      * Returns a new generator whose internal state is an exact copy
       
   125      * of this generator (therefore their future behavior should be
       
   126      * identical if subjected to the same series of operations).
       
   127      *
       
   128      * @return a new object that is a copy of this generator
       
   129      */
       
   130     public abstract AbstractArbitrarilyJumpableRng copy();
       
   131 
       
   132     // Stream methods for jumping
       
   133 
       
   134     /**
       
   135      * Returns an effectively unlimited stream of new pseudorandom
       
   136      * number generators, each of which implements the {@code Rng}
       
   137      * interface, produced by jumping copies of this generator
       
   138      * by different integer multiples of the default jump distance.
       
   139      *
       
   140      * @implNote This method is implemented to be equivalent to
       
   141      * {@code jumps(Long.MAX_VALUE)}.
       
   142      *
       
   143      * @return a stream of objects that implement the {@code Rng} interface
       
   144      */
       
   145     public Stream<Rng> jumps() {
       
   146         return StreamSupport.stream
       
   147             (makeJumpsSpliterator(0L, Long.MAX_VALUE, defaultJumpDistance()),
       
   148              false);
       
   149     }
       
   150 
       
   151     /**
       
   152      * Returns a stream producing the given {@code streamSize} number of
       
   153      * new pseudorandom number generators, each of which implements the
       
   154      * {@code Rng} interface, produced by jumping copies of this generator
       
   155      * by different integer multiples of the default jump distance.
       
   156      *
       
   157      * @param streamSize the number of generators to generate
       
   158      * @return a stream of objects that implement the {@code Rng} interface
       
   159      * @throws IllegalArgumentException if {@code streamSize} is
       
   160      *         less than zero
       
   161      */
       
   162     public Stream<Rng> jumps(long streamSize) {
       
   163         return StreamSupport.stream
       
   164             (makeJumpsSpliterator(0L, streamSize, defaultJumpDistance()),
       
   165              false);
       
   166     }
       
   167 
       
   168     /**
       
   169      * Returns an effectively unlimited stream of new pseudorandom
       
   170      * number generators, each of which implements the {@code Rng}
       
   171      * interface, produced by jumping copies of this generator
       
   172      * by different integer multiples of the specified jump distance.
       
   173      *
       
   174      * @implNote This method is implemented to be equivalent to
       
   175      * {@code jumps(Long.MAX_VALUE)}.
       
   176      *
       
   177      * @param distance a distance to jump forward within the state cycle
       
   178      * @return a stream of objects that implement the {@code Rng} interface
       
   179      */
       
   180     public Stream<ArbitrarilyJumpableRng> jumps(double distance) {
       
   181         return StreamSupport.stream
       
   182             (makeArbitraryJumpsSpliterator(0L, Long.MAX_VALUE, distance),
       
   183              false);
       
   184     }
       
   185 
       
   186     /**
       
   187      * Returns a stream producing the given {@code streamSize} number of
       
   188      * new pseudorandom number generators, each of which implements the
       
   189      * {@code Rng} interface, produced by jumping copies of this generator
       
   190      * by different integer multiples of the specified jump distance.
       
   191      *
       
   192      * @param streamSize the number of generators to generate
       
   193      * @param distance a distance to jump forward within the state cycle
       
   194      * @return a stream of objects that implement the {@code Rng} interface
       
   195      * @throws IllegalArgumentException if {@code streamSize} is
       
   196      *         less than zero
       
   197      */
       
   198     public Stream<ArbitrarilyJumpableRng> jumps(long streamSize, double distance) {
       
   199 	RngSupport.checkStreamSize(streamSize);
       
   200         return StreamSupport.stream
       
   201             (makeArbitraryJumpsSpliterator(0L, streamSize, distance),
       
   202              false);
       
   203     }
       
   204 
       
   205     /**
       
   206      * Alter the state of this pseudorandom number generator so as to
       
   207      * jump forward a very large, fixed distance (typically 2<sup>128</sup>
       
   208      * or more) within its state cycle.  The distance used is that
       
   209      * returned by method {@code defaultLeapDistance()}.
       
   210      */
       
   211     public void leap() { jump(defaultLeapDistance()); }
       
   212 
       
   213     // Stream methods for leaping
       
   214 
       
   215     /**
       
   216      * Returns an effectively unlimited stream of new pseudorandom
       
   217      * number generators, each of which implements the {@code Rng}
       
   218      * interface, produced by jumping copies of this generator
       
   219      * by different integer multiples of the default leap distance.
       
   220      *
       
   221      * @implNote This method is implemented to be equivalent to
       
   222      * {@code leaps(Long.MAX_VALUE)}.
       
   223      *
       
   224      * @return a stream of objects that implement the {@code Rng} interface
       
   225      */
       
   226     public Stream<JumpableRng> leaps() {
       
   227         return StreamSupport.stream
       
   228             (makeLeapsSpliterator(0L, Long.MAX_VALUE, defaultLeapDistance()),
       
   229              false);
       
   230     }
       
   231 
       
   232     /**
       
   233      * Returns a stream producing the given {@code streamSize} number of
       
   234      * new pseudorandom number generators, each of which implements the
       
   235      * {@code Rng} interface, produced by jumping copies of this generator
       
   236      * by different integer multiples of the default leap distance.
       
   237      *
       
   238      * @param streamSize the number of generators to generate
       
   239      * @return a stream of objects that implement the {@code Rng} interface
       
   240      * @throws IllegalArgumentException if {@code streamSize} is
       
   241      *         less than zero
       
   242      */
       
   243     public Stream<JumpableRng> leaps(long streamSize) {
       
   244         return StreamSupport.stream
       
   245             (makeLeapsSpliterator(0L, streamSize, defaultLeapDistance()),
       
   246              false);
       
   247     }
       
   248 
       
   249     
       
   250     /**
       
   251      * Spliterator for int streams.  We multiplex the four int
       
   252      * versions into one class by treating a bound less than origin as
       
   253      * unbounded, and also by treating "infinite" as equivalent to
       
   254      * Long.MAX_VALUE. For splits, we choose to override the method
       
   255      * {@code trySplit()} to try to optimize execution speed: instead of
       
   256      * dividing a range in half, it breaks off the largest possible chunk
       
   257      * whose size is a power of two such that the remaining chunk is not
       
   258      * empty.  In this way, the necessary jump distances will tend to be
       
   259      * powers of two.  The long and double versions of this class are
       
   260      * identical except for types.
       
   261      */
       
   262     static class RandomIntsSpliterator extends RngSupport.RandomSpliterator implements Spliterator.OfInt {
       
   263 	final ArbitrarilyJumpableRng generatingRng;
       
   264         final int origin;
       
   265         final int bound;
       
   266 
       
   267         RandomIntsSpliterator(ArbitrarilyJumpableRng generatingRng, long index, long fence, int origin, int bound) {
       
   268 	    super(index, fence);
       
   269 	    this.origin = origin; this.bound = bound;
       
   270 	    this.generatingRng = generatingRng;
       
   271         }
       
   272 	
       
   273         public Spliterator.OfInt trySplit() {
       
   274             long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
       
   275 	    if (m <= i) return null;
       
   276 	    index = m;
       
   277 	    ArbitrarilyJumpableRng r = (ArbitrarilyJumpableRng) generatingRng;
       
   278 	    return new RandomIntsSpliterator(r.copyAndJump((double)delta), i, m, origin, bound);
       
   279         }
       
   280 	
       
   281         public boolean tryAdvance(IntConsumer consumer) {
       
   282             if (consumer == null) throw new NullPointerException();
       
   283             long i = index, f = fence;
       
   284             if (i < f) {
       
   285                 consumer.accept(RngSupport.boundedNextInt(generatingRng, origin, bound));
       
   286                 index = i + 1;
       
   287                 return true;
       
   288             }
       
   289             else return false;
       
   290         }
       
   291 
       
   292         public void forEachRemaining(IntConsumer consumer) {
       
   293             if (consumer == null) throw new NullPointerException();
       
   294             long i = index, f = fence;
       
   295             if (i < f) {
       
   296                 index = f;
       
   297                 ArbitrarilyJumpableRng r = generatingRng;
       
   298                 int o = origin, b = bound;
       
   299                 do {
       
   300                     consumer.accept(RngSupport.boundedNextInt(r, o, b));
       
   301                 } while (++i < f);
       
   302             }
       
   303         }
       
   304     }
       
   305 
       
   306     /**
       
   307      * Spliterator for long streams.  
       
   308      */
       
   309     static class RandomLongsSpliterator extends RngSupport.RandomSpliterator implements Spliterator.OfLong {
       
   310 	final ArbitrarilyJumpableRng generatingRng;
       
   311         final long origin;
       
   312         final long bound;
       
   313 
       
   314         RandomLongsSpliterator(ArbitrarilyJumpableRng generatingRng, long index, long fence, long origin, long bound) {
       
   315 	    super(index, fence);
       
   316 	    this.generatingRng = generatingRng;
       
   317 	    this.origin = origin; this.bound = bound;
       
   318         }
       
   319 	
       
   320         public Spliterator.OfLong trySplit() {
       
   321             long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
       
   322 	    if (m <= i) return null;
       
   323 	    index = m;
       
   324 	    ArbitrarilyJumpableRng r = (ArbitrarilyJumpableRng) generatingRng;
       
   325 	    return new RandomLongsSpliterator(r.copyAndJump((double)delta), i, m, origin, bound);
       
   326         }
       
   327 	
       
   328         public boolean tryAdvance(LongConsumer consumer) {
       
   329             if (consumer == null) throw new NullPointerException();
       
   330             long i = index, f = fence;
       
   331             if (i < f) {
       
   332                 consumer.accept(RngSupport.boundedNextLong(generatingRng, origin, bound));
       
   333                 index = i + 1;
       
   334                 return true;
       
   335             }
       
   336             else return false;
       
   337         }
       
   338 
       
   339         public void forEachRemaining(LongConsumer consumer) {
       
   340             if (consumer == null) throw new NullPointerException();
       
   341             long i = index, f = fence;
       
   342             if (i < f) {
       
   343                 index = f;
       
   344                 ArbitrarilyJumpableRng r = generatingRng;
       
   345                 long o = origin, b = bound;
       
   346                 do {
       
   347                     consumer.accept(RngSupport.boundedNextLong(r, o, b));
       
   348                 } while (++i < f);
       
   349             }
       
   350         }
       
   351     }
       
   352 
       
   353     /**
       
   354      * Spliterator for double streams.  
       
   355      */
       
   356     static class RandomDoublesSpliterator extends RngSupport.RandomSpliterator implements Spliterator.OfDouble {
       
   357 	final ArbitrarilyJumpableRng generatingRng;
       
   358         final double origin;
       
   359         final double bound;
       
   360 
       
   361         RandomDoublesSpliterator(ArbitrarilyJumpableRng generatingRng, long index, long fence, double origin, double bound) {
       
   362 	    super(index, fence);
       
   363 	    this.generatingRng = generatingRng;
       
   364 	    this.origin = origin; this.bound = bound;
       
   365         }
       
   366 	
       
   367         public Spliterator.OfDouble trySplit() {
       
   368 
       
   369             long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
       
   370 	    if (m <= i) return null;
       
   371 	    index = m;
       
   372 	    ArbitrarilyJumpableRng r = (ArbitrarilyJumpableRng) generatingRng;
       
   373 	    return new RandomDoublesSpliterator(r.copyAndJump((double)delta), i, m, origin, bound);
       
   374         }
       
   375 	
       
   376         public boolean tryAdvance(DoubleConsumer consumer) {
       
   377             if (consumer == null) throw new NullPointerException();
       
   378             long i = index, f = fence;
       
   379             if (i < f) {
       
   380                 consumer.accept(RngSupport.boundedNextDouble(generatingRng, origin, bound));
       
   381                 index = i + 1;
       
   382                 return true;
       
   383             }
       
   384             else return false;
       
   385         }
       
   386 
       
   387         public void forEachRemaining(DoubleConsumer consumer) {
       
   388             if (consumer == null) throw new NullPointerException();
       
   389             long i = index, f = fence;
       
   390             if (i < f) {
       
   391                 index = f;
       
   392                 ArbitrarilyJumpableRng r = generatingRng;
       
   393                 double o = origin, b = bound;
       
   394                 do {
       
   395                     consumer.accept(RngSupport.boundedNextDouble(r, o, b));
       
   396                 } while (++i < f);
       
   397             }
       
   398         }
       
   399     }
       
   400     
       
   401     // Spliterators for producing new generators by jumping or leaping.  The
       
   402     // complete implementation of each of these spliterators is right here.
       
   403     // In the same manner as for the preceding spliterators, the method trySplit() is
       
   404     // coded to optimize execution speed: instead of dividing a range
       
   405     // in half, it breaks off the largest possible chunk whose
       
   406     // size is a power of two such that the remaining chunk is not
       
   407     // empty.  In this way, the necessary jump distances will tend to be
       
   408     // powers of two.
       
   409 
       
   410     /**
       
   411      * Spliterator for stream of generators of type Rng produced by jumps.
       
   412      */
       
   413     static class RandomJumpsSpliterator extends RngSupport.RandomSpliterator implements Spliterator<Rng> {
       
   414 	ArbitrarilyJumpableRng generatingRng;
       
   415 	final double distance;
       
   416 
       
   417         RandomJumpsSpliterator(ArbitrarilyJumpableRng generatingRng, long index, long fence, double distance) {
       
   418             super(index, fence);
       
   419             this.generatingRng = generatingRng; this.distance = distance;
       
   420         }
       
   421 
       
   422         public Spliterator<Rng> trySplit() {
       
   423 	    long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
       
   424 	    if (m <= i) return null;
       
   425 	    index = m;
       
   426 	    ArbitrarilyJumpableRng r = (ArbitrarilyJumpableRng) generatingRng;
       
   427 	    // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
       
   428 	    return new RandomJumpsSpliterator(r.copyAndJump(distance * (double)delta), i, m, distance);
       
   429         }
       
   430 
       
   431         public boolean tryAdvance(Consumer<? super Rng> consumer) {
       
   432             if (consumer == null) throw new NullPointerException();
       
   433             long i = index, f = fence;
       
   434             if (i < f) {
       
   435 		consumer.accept(generatingRng.copyAndJump(distance));
       
   436                 index = i + 1;
       
   437                 return true;
       
   438             }
       
   439             return false;
       
   440         }
       
   441 
       
   442         public void forEachRemaining(Consumer<? super Rng> consumer) {
       
   443             if (consumer == null) throw new NullPointerException();
       
   444             long i = index, f = fence;
       
   445             if (i < f) {
       
   446                 index = f;
       
   447 		ArbitrarilyJumpableRng r = generatingRng;
       
   448                 do {
       
   449                     consumer.accept(r.copyAndJump(distance));
       
   450                 } while (++i < f);
       
   451             }
       
   452         }
       
   453     }
       
   454     
       
   455     /**
       
   456      * Spliterator for stream of generators of type Rng produced by leaps.
       
   457      */
       
   458     static class RandomLeapsSpliterator extends RngSupport.RandomSpliterator implements Spliterator<JumpableRng> {
       
   459 	ArbitrarilyJumpableRng generatingRng;
       
   460 	final double distance;
       
   461 
       
   462         RandomLeapsSpliterator(ArbitrarilyJumpableRng generatingRng, long index, long fence, double distance) {
       
   463             super(index, fence);
       
   464             this.generatingRng = generatingRng; this.distance = distance;
       
   465         }
       
   466 
       
   467         public Spliterator<JumpableRng> trySplit() {
       
   468 	    long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
       
   469 	    if (m <= i) return null;
       
   470 	    index = m;
       
   471 	    // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
       
   472 	    return new RandomLeapsSpliterator(generatingRng.copyAndJump(distance * (double)delta), i, m, distance);
       
   473         }
       
   474 
       
   475         public boolean tryAdvance(Consumer<? super JumpableRng> consumer) {
       
   476             if (consumer == null) throw new NullPointerException();
       
   477             long i = index, f = fence;
       
   478             if (i < f) {
       
   479 		consumer.accept(generatingRng.copyAndJump(distance));
       
   480                 index = i + 1;
       
   481                 return true;
       
   482             }
       
   483             return false;
       
   484         }
       
   485 
       
   486         public void forEachRemaining(Consumer<? super JumpableRng> consumer) {
       
   487             if (consumer == null) throw new NullPointerException();
       
   488             long i = index, f = fence;
       
   489             if (i < f) {
       
   490                 index = f;
       
   491                 ArbitrarilyJumpableRng r = generatingRng;
       
   492                 do {
       
   493                     consumer.accept(r.copyAndJump(distance));
       
   494                 } while (++i < f);
       
   495             }
       
   496         }
       
   497     }
       
   498 
       
   499     /**
       
   500      * Spliterator for stream of generators of type Rng produced by arbitrary jumps.
       
   501      */
       
   502     static class RandomArbitraryJumpsSpliterator extends RngSupport.RandomSpliterator implements Spliterator<ArbitrarilyJumpableRng> {
       
   503 	ArbitrarilyJumpableRng generatingRng;
       
   504 	final double distance;
       
   505 
       
   506         RandomArbitraryJumpsSpliterator(ArbitrarilyJumpableRng generatingRng, long index, long fence, double distance) {
       
   507             super(index, fence);
       
   508             this.generatingRng = generatingRng; this.distance = distance;
       
   509         }
       
   510 
       
   511         public Spliterator<ArbitrarilyJumpableRng> trySplit() {
       
   512 	    long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
       
   513 	    if (m <= i) return null;
       
   514 	    index = m;
       
   515 	    // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
       
   516 	    return new RandomArbitraryJumpsSpliterator(generatingRng.copyAndJump(distance * (double)delta), i, m, distance);
       
   517         }
       
   518 
       
   519         public boolean tryAdvance(Consumer<? super ArbitrarilyJumpableRng> consumer) {
       
   520             if (consumer == null) throw new NullPointerException();
       
   521             long i = index, f = fence;
       
   522             if (i < f) {
       
   523 		consumer.accept(generatingRng.copyAndJump(distance));
       
   524                 index = i + 1;
       
   525                 return true;
       
   526             }
       
   527             return false;
       
   528         }
       
   529 
       
   530         public void forEachRemaining(Consumer<? super ArbitrarilyJumpableRng> consumer) {
       
   531             if (consumer == null) throw new NullPointerException();
       
   532             long i = index, f = fence;
       
   533             if (i < f) {
       
   534                 index = f;
       
   535 		ArbitrarilyJumpableRng r = generatingRng;
       
   536                 do {
       
   537                     consumer.accept(r.copyAndJump(distance));
       
   538                 } while (++i < f);
       
   539             }
       
   540         }
       
   541     }
       
   542 
       
   543 }