src/java.base/share/classes/java/util/random/RandomSupport.java
author jlaskey
Thu, 14 Nov 2019 12:50:08 -0400
branchJDK-8193209-branch
changeset 59088 da026c172c1e
permissions -rw-r--r--
add missing files
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
59088
da026c172c1e add missing files
jlaskey
parents:
diff changeset
     1
/*
da026c172c1e add missing files
jlaskey
parents:
diff changeset
     2
 * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
     4
 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
da026c172c1e add missing files
jlaskey
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
da026c172c1e add missing files
jlaskey
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
da026c172c1e add missing files
jlaskey
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
da026c172c1e add missing files
jlaskey
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    10
 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    15
 * accompanied this code).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    16
 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    20
 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    23
 * questions.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    24
 */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    25
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    26
package java.util.random;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    27
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    28
import java.util.function.Consumer;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    29
import java.util.function.DoubleConsumer;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    30
import java.util.function.IntConsumer;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    31
import java.util.function.LongConsumer;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    32
import java.util.random.RandomGenerator.SplittableGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    33
import java.util.Spliterator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    34
import java.util.stream.DoubleStream;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    35
import java.util.stream.IntStream;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    36
import java.util.stream.LongStream;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    37
import java.util.stream.Stream;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    38
import java.util.stream.StreamSupport;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    39
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    40
/**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    41
 * Low-level utility methods helpful for implementing pseudorandom number generators.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    42
 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    43
 * This class is mostly for library writers creating specific implementations of the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    44
 * interface {@link RandomGenerator}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    45
 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    46
 * @since 14
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    47
 */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    48
public class RandomSupport {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    49
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    50
    /*
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    51
     * Implementation Overview.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    52
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    53
     * This class provides utility methods and constants frequently
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    54
     * useful in the implementation of pseudorandom number generators
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    55
     * that satisfy the interface {@link RandomGenerator}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    56
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    57
     * File organization: First some message strings, then the main
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    58
     * public methods, followed by a non-public base spliterator class.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    59
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    60
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    61
    // IllegalArgumentException messages
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    62
    static final String BAD_SIZE = "size must be non-negative";
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    63
    static final String BAD_DISTANCE = "jump distance must be finite, positive, and an exact integer";
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    64
    static final String BAD_BOUND = "bound must be positive";
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    65
    static final String BAD_FLOATING_BOUND = "bound must be finite and positive";
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    66
    static final String BAD_RANGE = "bound must be greater than origin";
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    67
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    68
    /* ---------------- public methods ---------------- */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    69
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    70
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    71
     * Check a {@code long} proposed stream size for validity.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    72
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    73
     * @param streamSize the proposed stream size
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    74
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    75
     * @throws IllegalArgumentException if {@code streamSize} is negative
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    76
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    77
    public static void checkStreamSize(long streamSize) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    78
        if (streamSize < 0L)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    79
            throw new IllegalArgumentException(BAD_SIZE);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    80
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    81
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    82
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    83
     * Check a {@code double} proposed jump distance for validity.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    84
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    85
     * @param distance the proposed jump distance
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    86
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    87
     * @throws IllegalArgumentException if {@code size} fails to be positive, finite, and an exact integer
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    88
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    89
    public static void checkJumpDistance(double distance) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    90
        if (!(distance > 0.0 && distance < Float.POSITIVE_INFINITY
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    91
                             && distance == Math.floor(distance))) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    92
            throw new IllegalArgumentException(BAD_DISTANCE);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    93
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    94
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    95
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    96
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    97
     * Checks a {@code float} upper bound value for validity.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    98
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
    99
     * @param bound the upper bound (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   100
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   101
     * @throws IllegalArgumentException if {@code bound} fails to be positive and finite
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   102
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   103
    public static void checkBound(float bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   104
        if (!(bound > 0.0 && bound < Float.POSITIVE_INFINITY)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   105
            throw new IllegalArgumentException(BAD_FLOATING_BOUND);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   106
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   107
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   108
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   109
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   110
     * Checks a {@code double} upper bound value for validity.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   111
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   112
     * @param bound the upper bound (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   113
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   114
     * @throws IllegalArgumentException if {@code bound} fails to be positive and finite
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   115
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   116
    public static void checkBound(double bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   117
        if (!(bound > 0.0 && bound < Double.POSITIVE_INFINITY)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   118
            throw new IllegalArgumentException(BAD_FLOATING_BOUND);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   119
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   120
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   121
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   122
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   123
     * Checks an {@code int} upper bound value for validity.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   124
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   125
     * @param bound the upper bound (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   126
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   127
     * @throws IllegalArgumentException if {@code bound} is not positive
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   128
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   129
    public static void checkBound(int bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   130
        if (bound <= 0) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   131
            throw new IllegalArgumentException(BAD_BOUND);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   132
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   133
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   134
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   135
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   136
     * Checks a {@code long} upper bound value for validity.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   137
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   138
     * @param bound the upper bound (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   139
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   140
     * @throws IllegalArgumentException if {@code bound} is not positive
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   141
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   142
    public static void checkBound(long bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   143
        if (bound <= 0) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   144
            throw new IllegalArgumentException(BAD_BOUND);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   145
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   146
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   147
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   148
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   149
     * Checks a {@code float} range for validity.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   150
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   151
     * @param origin the least value (inclusive) in the range
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   152
     * @param bound  the upper bound (exclusive) of the range
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   153
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   154
     * @throws IllegalArgumentException if {@code origin} is not finite, {@code bound} is not finite,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   155
     *                                  or {@code bound - origin} is not finite
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   156
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   157
    public static void checkRange(float origin, float bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   158
        if (!(origin < bound && (bound - origin) < Float.POSITIVE_INFINITY)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   159
            throw new IllegalArgumentException(BAD_RANGE);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   160
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   161
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   162
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   163
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   164
     * Checks a {@code double} range for validity.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   165
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   166
     * @param origin the least value (inclusive) in the range
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   167
     * @param bound  the upper bound (exclusive) of the range
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   168
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   169
     * @throws IllegalArgumentException if {@code origin} is not finite, {@code bound} is not finite,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   170
     *                                  or {@code bound - origin} is not finite
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   171
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   172
    public static void checkRange(double origin, double bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   173
        if (!(origin < bound && (bound - origin) < Double.POSITIVE_INFINITY)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   174
            throw new IllegalArgumentException(BAD_RANGE);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   175
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   176
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   177
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   178
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   179
     * Checks an {@code int} range for validity.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   180
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   181
     * @param origin the least value that can be returned
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   182
     * @param bound  the upper bound (exclusive) for the returned value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   183
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   184
     * @throws IllegalArgumentException if {@code origin} is greater than or equal to {@code bound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   185
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   186
    public static void checkRange(int origin, int bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   187
        if (origin >= bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   188
            throw new IllegalArgumentException(BAD_RANGE);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   189
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   190
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   191
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   192
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   193
     * Checks a {@code long} range for validity.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   194
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   195
     * @param origin the least value that can be returned
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   196
     * @param bound  the upper bound (exclusive) for the returned value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   197
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   198
     * @throws IllegalArgumentException if {@code origin} is greater than or equal to {@code bound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   199
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   200
    public static void checkRange(long origin, long bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   201
        if (origin >= bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   202
            throw new IllegalArgumentException(BAD_RANGE);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   203
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   204
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   205
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   206
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   207
     * Given an array of seed bytes of any length, construct an array
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   208
     * of {@code long} seed values of length {@code n}, such that the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   209
     * last {@code z} values are not all zero.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   210
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   211
     * @param seed an array of {@code byte} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   212
     * @param n the length of the result array (should be nonnegative)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   213
     * @param z the number of trailing result elements that are required
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   214
     *        to be not all zero (should be nonnegative but not larger
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   215
     *        than {@code n})
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   216
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   217
     * @return an array of length {@code n} containing {@code long} seed values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   218
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   219
    public static long[] convertSeedBytesToLongs(byte[] seed, int n, int z) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   220
        final long[] result = new long[n];
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   221
        final int m = Math.min(seed.length, n << 3);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   222
        // Distribute seed bytes into the words to be formed.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   223
        for (int j = 0; j < m; j++) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   224
            result[j>>3] = (result[j>>3] << 8) | seed[j];
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   225
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   226
        // If there aren't enough seed bytes for all the words we need,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   227
        // use a SplitMix-style PRNG to fill in the rest.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   228
        long v = result[0];
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   229
        for (int j = (m + 7) >> 3; j < n; j++) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   230
            result[j] = mixMurmur64(v += SILVER_RATIO_64);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   231
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   232
        // Finally, we need to make sure the last z words are not all zero.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   233
        search: {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   234
            for (int j = n - z; j < n; j++) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   235
                if (result[j] != 0) break search;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   236
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   237
            // If they are, fill in using a SplitMix-style PRNG.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   238
            // Using "& ~1L" in the next line defends against the case z==1
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   239
            // by guaranteeing that the first generated value will be nonzero.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   240
            long w = result[0] & ~1L;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   241
            for (int j = n - z; j < n; j++) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   242
                result[j] = mixMurmur64(w += SILVER_RATIO_64);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   243
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   244
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   245
        return result;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   246
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   247
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   248
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   249
     * Given an array of seed bytes of any length, construct an array
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   250
     * of {@code int} seed values of length {@code n}, such that the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   251
     * last {@code z} values are not all zero.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   252
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   253
     * @param seed an array of {@code byte} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   254
     * @param n the length of the result array (should be nonnegative)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   255
     * @param z the number of trailing result elements that are required
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   256
     *        to be not all zero (should be nonnegative but not larger
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   257
     *        than {@code n})
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   258
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   259
     * @return an array of length {@code n} containing {@code int} seed values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   260
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   261
    public static int[] convertSeedBytesToInts(byte[] seed, int n, int z) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   262
        final int[] result = new int[n];
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   263
        final int m = Math.min(seed.length, n << 2);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   264
        // Distribute seed bytes into the words to be formed.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   265
        for (int j = 0; j < m; j++) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   266
            result[j>>2] = (result[j>>2] << 8) | seed[j];
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   267
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   268
        // If there aren't enough seed bytes for all the words we need,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   269
        // use a SplitMix-style PRNG to fill in the rest.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   270
        int v = result[0];
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   271
        for (int j = (m + 3) >> 2; j < n; j++) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   272
            result[j] = mixMurmur32(v += SILVER_RATIO_32);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   273
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   274
        // Finally, we need to make sure the last z words are not all zero.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   275
        search: {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   276
            for (int j = n - z; j < n; j++) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   277
                if (result[j] != 0) break search;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   278
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   279
            // If they are, fill in using a SplitMix-style PRNG.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   280
            // Using "& ~1" in the next line defends against the case z==1
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   281
            // by guaranteeing that the first generated value will be nonzero.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   282
            int w = result[0] & ~1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   283
            for (int j = n - z; j < n; j++) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   284
                result[j] = mixMurmur32(w += SILVER_RATIO_32);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   285
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   286
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   287
        return result;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   288
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   289
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   290
    /*
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   291
     * Bounded versions of nextX methods used by streams, as well as
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   292
     * the public nextX(origin, bound) methods.  These exist mainly to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   293
     * avoid the need for multiple versions of stream spliterators
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   294
     * across the different exported forms of streams.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   295
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   296
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   297
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   298
     * This is the form of {@code nextLong} used by a {@link LongStream}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   299
     * {@link Spliterator} and by the public method
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   300
     * {@code nextLong(origin, bound)}.  If {@code origin} is greater
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   301
     * than {@code bound}, then this method simply calls the unbounded
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   302
     * version of {@code nextLong()}, choosing pseudorandomly from
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   303
     * among all 2<sup>64</sup> possible {@code long} values}, and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   304
     * otherwise uses one or more calls to {@code nextLong()} to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   305
     * choose a value pseudorandomly from the possible values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   306
     * between {@code origin} (inclusive) and {@code bound} (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   307
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   308
     * @implNote This method first calls {@code nextLong()} to obtain
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   309
     * a {@code long} value that is assumed to be pseudorandomly
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   310
     * chosen uniformly and independently from the 2<sup>64</sup>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   311
     * possible {@code long} values (that is, each of the 2<sup>64</sup>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   312
     * possible long values is equally likely to be chosen).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   313
     * Under some circumstances (when the specified range is not
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   314
     * a power of 2), {@code nextLong()} may be called additional times
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   315
     * to ensure that that the values in the specified range are
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   316
     * equally likely to be chosen (provided the assumption holds).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   317
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   318
     * The implementation considers four cases:
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   319
     * <ol>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   320
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   321
     * <li> If the {@code} bound} is less than or equal to the {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   322
     *      (indicated an unbounded form), the 64-bit {@code long} value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   323
     *      obtained from {@code nextLong()} is returned directly.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   324
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   325
     * <li> Otherwise, if the length <i>n</i> of the specified range is an
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   326
     *      exact power of two 2<sup><i>m</i></sup> for some integer
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   327
     *      <i>m</i>, then return the sum of {@code origin} and the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   328
     *      <i>m</i> lowest-order bits of the value from {@code nextLong()}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   329
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   330
     * <li> Otherwise, if the length <i>n</i> of the specified range
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   331
     *      is less than 2<sup>63</sup>, then the basic idea is to use the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   332
     *      remainder modulo <i>n</i> of the value from {@code nextLong()},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   333
     *      but with this approach some values will be over-represented.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   334
     *      Therefore a loop is used to avoid potential bias by rejecting
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   335
     *      candidates that are too large.  Assuming that the results from
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   336
     *      {@code nextLong()} are truly chosen uniformly and independently,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   337
     *      the expected number of iterations will be somewhere between
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   338
     *      1 and 2, depending on the precise value of <i>n</i>.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   339
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   340
     * <li> Otherwise, the length <i>n</i> of the specified range
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   341
     *      cannot be represented as a positive {@code long} value.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   342
     *      A loop repeatedly calls {@code nextlong()} until obtaining
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   343
     *      a suitable candidate,  Again, the expected number of iterations
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   344
     *      is less than 2.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   345
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   346
     * </ol>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   347
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   348
     * @param rng a random number generator to be used as a
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   349
     *        source of pseudorandom {@code long} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   350
     * @param origin the least value that can be produced,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   351
     *        unless greater than or equal to {@code bound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   352
     * @param bound the upper bound (exclusive), unless {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   353
     *        is greater than or equal to {@code bound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   354
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   355
     * @return a pseudorandomly chosen {@code long} value,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   356
     *         which will be between {@code origin} (inclusive) and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   357
     *         {@code bound} exclusive unless {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   358
     *         is greater than or equal to {@code bound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   359
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   360
    public static long boundedNextLong(RandomGenerator rng, long origin, long bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   361
        long r = rng.nextLong();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   362
        if (origin < bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   363
            // It's not case (1).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   364
            final long n = bound - origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   365
            final long m = n - 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   366
            if ((n & m) == 0L) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   367
                // It is case (2): length of range is a power of 2.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   368
                r = (r & m) + origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   369
            } else if (n > 0L) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   370
                // It is case (3): need to reject over-represented candidates.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   371
                /* This loop takes an unlovable form (but it works):
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   372
                   because the first candidate is already available,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   373
                   we need a break-in-the-middle construction,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   374
                   which is concisely but cryptically performed
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   375
                   within the while-condition of a body-less for loop. */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   376
                for (long u = r >>> 1;            // ensure nonnegative
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   377
                     u + m - (r = u % n) < 0L;    // rejection check
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   378
                     u = rng.nextLong() >>> 1) // retry
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   379
                    ;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   380
                r += origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   381
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   382
            else {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   383
                // It is case (4): length of range not representable as long.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   384
                while (r < origin || r >= bound)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   385
                    r = rng.nextLong();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   386
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   387
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   388
        return r;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   389
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   390
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   391
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   392
     * This is the form of {@code nextLong} used by the public method
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   393
     * {@code nextLong(bound)}.  This is essentially a version of
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   394
     * {@code boundedNextLong(origin, bound)} that has been
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   395
     * specialized for the case where the {@code origin} is zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   396
     * and the {@code bound} is greater than zero.  The value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   397
     * returned is chosen pseudorandomly from nonnegative integer
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   398
     * values less than {@code bound}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   399
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   400
     * @implNote This method first calls {@code nextLong()} to obtain
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   401
     * a {@code long} value that is assumed to be pseudorandomly
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   402
     * chosen uniformly and independently from the 2<sup>64</sup>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   403
     * possible {@code long} values (that is, each of the 2<sup>64</sup>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   404
     * possible long values is equally likely to be chosen).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   405
     * Under some circumstances (when the specified range is not
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   406
     * a power of 2), {@code nextLong()} may be called additional times
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   407
     * to ensure that that the values in the specified range are
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   408
     * equally likely to be chosen (provided the assumption holds).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   409
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   410
     * The implementation considers two cases:
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   411
     * <ol>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   412
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   413
     * <li> If {@code bound} is an exact power of two 2<sup><i>m</i></sup>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   414
     *      for some integer <i>m</i>, then return the sum of {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   415
     *      and the <i>m</i> lowest-order bits of the value from
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   416
     *      {@code nextLong()}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   417
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   418
     * <li> Otherwise, the basic idea is to use the remainder modulo
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   419
     *      <i>bound</i> of the value from {@code nextLong()},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   420
     *      but with this approach some values will be over-represented.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   421
     *      Therefore a loop is used to avoid potential bias by rejecting
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   422
     *      candidates that vare too large.  Assuming that the results from
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   423
     *      {@code nextLong()} are truly chosen uniformly and independently,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   424
     *      the expected number of iterations will be somewhere between
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   425
     *      1 and 2, depending on the precise value of <i>bound</i>.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   426
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   427
     * </ol>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   428
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   429
     * @param rng a random number generator to be used as a
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   430
     *        source of pseudorandom {@code long} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   431
     * @param bound the upper bound (exclusive); must be greater than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   432
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   433
     * @return a pseudorandomly chosen {@code long} value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   434
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   435
    public static long boundedNextLong(RandomGenerator rng, long bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   436
        // Specialize boundedNextLong for origin == 0, bound > 0
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   437
        final long m = bound - 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   438
        long r = rng.nextLong();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   439
        if ((bound & m) == 0L) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   440
            // The bound is a power of 2.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   441
            r &= m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   442
        } else {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   443
            // Must reject over-represented candidates
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   444
            /* This loop takes an unlovable form (but it works):
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   445
               because the first candidate is already available,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   446
               we need a break-in-the-middle construction,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   447
               which is concisely but cryptically performed
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   448
               within the while-condition of a body-less for loop. */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   449
            for (long u = r >>> 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   450
                 u + m - (r = u % bound) < 0L;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   451
                 u = rng.nextLong() >>> 1)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   452
                ;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   453
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   454
        return r;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   455
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   456
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   457
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   458
     * This is the form of {@code nextInt} used by an {@link IntStream}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   459
     * {@link Spliterator} and by the public method
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   460
     * {@code nextInt(origin, bound)}.  If {@code origin} is greater
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   461
     * than {@code bound}, then this method simply calls the unbounded
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   462
     * version of {@code nextInt()}, choosing pseudorandomly from
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   463
     * among all 2<sup>64</sup> possible {@code int} values}, and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   464
     * otherwise uses one or more calls to {@code nextInt()} to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   465
     * choose a value pseudorandomly from the possible values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   466
     * between {@code origin} (inclusive) and {@code bound} (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   467
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   468
     * @param rng a random number generator to be used as a
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   469
     *        source of pseudorandom {@code int} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   470
     * @param origin the least value that can be produced,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   471
     *        unless greater than or equal to {@code bound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   472
     * @param bound the upper bound (exclusive), unless {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   473
     *        is greater than or equal to {@code bound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   474
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   475
     * @return a pseudorandomly chosen {@code int} value,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   476
     *         which will be between {@code origin} (inclusive) and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   477
     *         {@code bound} exclusive unless {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   478
     *         is greater than or equal to {@code bound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   479
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   480
     * @implNote The implementation of this method is identical to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   481
     *           the implementation of {@code nextLong(origin, bound)}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   482
     *           except that {@code int} values and the {@code nextInt()}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   483
     *           method are used rather than {@code long} values and the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   484
     *           {@code nextLong()} method.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   485
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   486
    public static int boundedNextInt(RandomGenerator rng, int origin, int bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   487
        int r = rng.nextInt();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   488
        if (origin < bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   489
            // It's not case (1).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   490
            final int n = bound - origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   491
            final int m = n - 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   492
            if ((n & m) == 0) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   493
                // It is case (2): length of range is a power of 2.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   494
                r = (r & m) + origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   495
            } else if (n > 0) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   496
                // It is case (3): need to reject over-represented candidates.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   497
                for (int u = r >>> 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   498
                     u + m - (r = u % n) < 0;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   499
                     u = rng.nextInt() >>> 1)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   500
                    ;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   501
                r += origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   502
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   503
            else {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   504
                // It is case (4): length of range not representable as long.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   505
                while (r < origin || r >= bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   506
                    r = rng.nextInt();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   507
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   508
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   509
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   510
        return r;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   511
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   512
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   513
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   514
     * This is the form of {@code nextInt} used by the public method
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   515
     * {@code nextInt(bound)}.  This is essentially a version of
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   516
     * {@code boundedNextInt(origin, bound)} that has been
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   517
     * specialized for the case where the {@code origin} is zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   518
     * and the {@code bound} is greater than zero.  The value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   519
     * returned is chosen pseudorandomly from nonnegative integer
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   520
     * values less than {@code bound}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   521
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   522
     * @param rng a random number generator to be used as a
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   523
     *        source of pseudorandom {@code long} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   524
     * @param bound the upper bound (exclusive); must be greater than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   525
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   526
     * @return a pseudorandomly chosen {@code long} value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   527
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   528
     * @implNote The implementation of this method is identical to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   529
     *           the implementation of {@code nextLong(bound)}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   530
     *           except that {@code int} values and the {@code nextInt()}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   531
     *           method are used rather than {@code long} values and the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   532
     *           {@code nextLong()} method.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   533
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   534
    public static int boundedNextInt(RandomGenerator rng, int bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   535
        // Specialize boundedNextInt for origin == 0, bound > 0
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   536
        final int m = bound - 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   537
        int r = rng.nextInt();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   538
        if ((bound & m) == 0) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   539
            // The bound is a power of 2.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   540
            r &= m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   541
        } else {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   542
            // Must reject over-represented candidates
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   543
            for (int u = r >>> 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   544
                 u + m - (r = u % bound) < 0;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   545
                 u = rng.nextInt() >>> 1)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   546
                ;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   547
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   548
        return r;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   549
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   550
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   551
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   552
     * This is the form of {@code nextDouble} used by a {@link DoubleStream}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   553
     * {@link Spliterator} and by the public method
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   554
     * {@code nextDouble(origin, bound)}.  If {@code origin} is greater
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   555
     * than {@code bound}, then this method simply calls the unbounded
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   556
     * version of {@code nextDouble()}, and otherwise scales and translates
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   557
     * the result of a call to {@code nextDouble()} so that it lies
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   558
     * between {@code origin} (inclusive) and {@code bound} (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   559
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   560
     * @implNote The implementation considers two cases:
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   561
     * <ol>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   562
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   563
     * <li> If the {@code bound} is less than or equal to the {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   564
     *      (indicated an unbounded form), the 64-bit {@code double} value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   565
     *      obtained from {@code nextDouble()} is returned directly.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   566
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   567
     * <li> Otherwise, the result of a call to {@code nextDouble} is
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   568
     *      multiplied by {@code (bound - origin)}, then {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   569
     *      is added, and then if this this result is not less than
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   570
     *      {@code bound} (which can sometimes occur because of rounding),
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   571
     *      it is replaced with the largest {@code double} value that
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   572
     *      is less than {@code bound}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   573
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   574
     * </ol>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   575
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   576
     * @param rng a random number generator to be used as a
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   577
     *        source of pseudorandom {@code double} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   578
     * @param origin the least value that can be produced,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   579
     *        unless greater than or equal to {@code bound}; must be finite
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   580
     * @param bound the upper bound (exclusive), unless {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   581
     *        is greater than or equal to {@code bound}; must be finite
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   582
     * @return a pseudorandomly chosen {@code double} value,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   583
     *         which will be between {@code origin} (inclusive) and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   584
     *         {@code bound} exclusive unless {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   585
     *         is greater than or equal to {@code bound},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   586
     *         in which case it will be between 0.0 (inclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   587
     *         and 1.0 (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   588
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   589
    public static double boundedNextDouble(RandomGenerator rng, double origin, double bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   590
        double r = rng.nextDouble();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   591
        if (origin < bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   592
            r = r * (bound - origin) + origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   593
            if (r >= bound)  // may need to correct a rounding problem
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   594
                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   595
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   596
        return r;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   597
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   598
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   599
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   600
     * This is the form of {@code nextDouble} used by the public method
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   601
     * {@code nextDouble(bound)}.  This is essentially a version of
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   602
     * {@code boundedNextDouble(origin, bound)} that has been
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   603
     * specialized for the case where the {@code origin} is zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   604
     * and the {@code bound} is greater than zero.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   605
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   606
     * @implNote The result of a call to {@code nextDouble} is
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   607
     *      multiplied by {@code bound}, and then if this result is
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   608
     *      not less than {@code bound} (which can sometimes occur
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   609
     *      because of rounding), it is replaced with the largest
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   610
     *      {@code double} value that is less than {@code bound}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   611
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   612
     * @param rng a random number generator to be used as a
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   613
     *        source of pseudorandom {@code double} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   614
     * @param bound the upper bound (exclusive); must be finite and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   615
     *        greater than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   616
     * @return a pseudorandomly chosen {@code double} value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   617
     *         between zero (inclusive) and {@code bound} (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   618
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   619
    public static double boundedNextDouble(RandomGenerator rng, double bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   620
        // Specialize boundedNextDouble for origin == 0, bound > 0
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   621
        double r = rng.nextDouble();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   622
        r = r * bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   623
        if (r >= bound)  // may need to correct a rounding problem
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   624
            r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   625
        return r;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   626
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   627
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   628
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   629
     * This is the form of {@code nextFloat} used by a {@code Stream<Float>}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   630
     * {@link Spliterator} (if there were any) and by the public method
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   631
     * {@code nextFloat(origin, bound)}.  If {@code origin} is greater
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   632
     * than {@code bound}, then this method simply calls the unbounded
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   633
     * version of {@code nextFloat()}, and otherwise scales and translates
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   634
     * the result of a call to {@code nextFloat()} so that it lies
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   635
     * between {@code origin} (inclusive) and {@code bound} (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   636
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   637
     * @implNote The implementation of this method is identical to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   638
     *     the implementation of {@code nextDouble(origin, bound)}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   639
     *     except that {@code float} values and the {@code nextFloat()}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   640
     *     method are used rather than {@code double} values and the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   641
     *     {@code nextDouble()} method.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   642
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   643
     * @param rng a random number generator to be used as a
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   644
     *        source of pseudorandom {@code float} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   645
     * @param origin the least value that can be produced,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   646
     *        unless greater than or equal to {@code bound}; must be finite
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   647
     * @param bound the upper bound (exclusive), unless {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   648
     *        is greater than or equal to {@code bound}; must be finite
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   649
     * @return a pseudorandomly chosen {@code float} value,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   650
     *         which will be between {@code origin} (inclusive) and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   651
     *         {@code bound} exclusive unless {@code origin}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   652
     *         is greater than or equal to {@code bound},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   653
     *         in which case it will be between 0.0 (inclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   654
     *         and 1.0 (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   655
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   656
    public static float boundedNextFloat(RandomGenerator rng, float origin, float bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   657
        float r = rng.nextFloat();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   658
        if (origin < bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   659
            r = r * (bound - origin) + origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   660
            if (r >= bound) // may need to correct a rounding problem
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   661
                r = Float.intBitsToFloat(Float.floatToIntBits(bound) - 1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   662
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   663
        return r;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   664
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   665
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   666
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   667
     * This is the form of {@code nextFloat} used by the public method
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   668
     * {@code nextFloat(bound)}.  This is essentially a version of
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   669
     * {@code boundedNextFloat(origin, bound)} that has been
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   670
     * specialized for the case where the {@code origin} is zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   671
     * and the {@code bound} is greater than zero.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   672
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   673
     * @implNote The implementation of this method is identical to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   674
     *     the implementation of {@code nextDouble(bound)}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   675
     *     except that {@code float} values and the {@code nextFloat()}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   676
     *     method are used rather than {@code double} values and the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   677
     *     {@code nextDouble()} method.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   678
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   679
     * @param rng a random number generator to be used as a
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   680
     *        source of pseudorandom {@code float} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   681
     * @param bound the upper bound (exclusive); must be finite and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   682
     *        greater than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   683
     * @return a pseudorandomly chosen {@code float} value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   684
     *         between zero (inclusive) and {@code bound} (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   685
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   686
    public static float boundedNextFloat(RandomGenerator rng, float bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   687
        // Specialize boundedNextFloat for origin == 0, bound > 0
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   688
        float r = rng.nextFloat();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   689
        r = r * bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   690
        if (r >= bound) // may need to correct a rounding problem
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   691
            r = Float.intBitsToFloat(Float.floatToIntBits(bound) - 1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   692
        return r;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   693
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   694
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   695
    // The following decides which of two strategies initialSeed() will use.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   696
    private static boolean secureRandomSeedRequested() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   697
        String pp = java.security.AccessController.doPrivileged(
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   698
                new sun.security.action.GetPropertyAction(
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   699
                        "java.util.secureRandomSeed"));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   700
        return (pp != null && pp.equalsIgnoreCase("true"));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   701
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   702
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   703
    private static final boolean useSecureRandomSeed = secureRandomSeedRequested();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   704
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   705
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   706
     * Returns a {@code long} value (chosen from some
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   707
     * machine-dependent entropy source) that may be useful for
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   708
     * initializing a source of seed values for instances of {@link RandomGenerator}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   709
     * created by zero-argument constructors.  (This method should
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   710
     * <i>not</i> be called repeatedly, once per constructed
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   711
     * object; at most it should be called once per class.)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   712
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   713
     * @return a {@code long} value, randomly chosen using
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   714
     *         appropriate environmental entropy
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   715
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   716
    public static long initialSeed() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   717
        if (useSecureRandomSeed) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   718
            byte[] seedBytes = java.security.SecureRandom.getSeed(8);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   719
            long s = (long)(seedBytes[0]) & 0xffL;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   720
            for (int i = 1; i < 8; ++i)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   721
                s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   722
            return s;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   723
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   724
        return (mixStafford13(System.currentTimeMillis()) ^
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   725
                mixStafford13(System.nanoTime()));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   726
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   727
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   728
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   729
     * The first 32 bits of the golden ratio (1+sqrt(5))/2, forced to be odd.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   730
     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   731
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   732
    public static final int  GOLDEN_RATIO_32 = 0x9e3779b9;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   733
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   734
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   735
     * The first 64 bits of the golden ratio (1+sqrt(5))/2, forced to be odd.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   736
     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   737
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   738
    public static final long GOLDEN_RATIO_64 = 0x9e3779b97f4a7c15L;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   739
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   740
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   741
     * The first 32 bits of the silver ratio 1+sqrt(2), forced to be odd.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   742
     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   743
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   744
    public static final int  SILVER_RATIO_32 = 0x6A09E667;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   745
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   746
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   747
     * The first 64 bits of the silver ratio 1+sqrt(2), forced to be odd.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   748
     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   749
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   750
    public static final long SILVER_RATIO_64 = 0x6A09E667F3BCC909L;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   751
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   752
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   753
     * Computes the 64-bit mixing function for MurmurHash3.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   754
     * This is a 64-bit hashing function with excellent avalanche statistics.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   755
     * https://github.com/aappleby/smhasher/wiki/MurmurHash3
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   756
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   757
     * Note that if the argument {@code z} is 0, the result is 0.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   758
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   759
     * @param z any long value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   760
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   761
     * @return the result of hashing z
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   762
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   763
    public static long mixMurmur64(long z) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   764
        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   765
        z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   766
        return z ^ (z >>> 33);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   767
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   768
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   769
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   770
     * Computes Stafford variant 13 of the 64-bit mixing function for MurmurHash3.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   771
     * This is a 64-bit hashing function with excellent avalanche statistics.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   772
     * http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   773
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   774
     * Note that if the argument {@code z} is 0, the result is 0.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   775
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   776
     * @param z any long value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   777
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   778
     * @return the result of hashing z
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   779
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   780
    public static long mixStafford13(long z) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   781
        z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   782
        z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   783
        return z ^ (z >>> 31);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   784
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   785
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   786
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   787
     * Computes Doug Lea's 64-bit mixing function.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   788
     * This is a 64-bit hashing function with excellent avalanche statistics.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   789
     * It has the advantages of using the same multiplicative constant twice
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   790
     * and of using only 32-bit shifts.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   791
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   792
     * Note that if the argument {@code z} is 0, the result is 0.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   793
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   794
     * @param z any long value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   795
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   796
     * @return the result of hashing z
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   797
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   798
    public static long mixLea64(long z) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   799
        z = (z ^ (z >>> 32)) * 0xdaba0b6eb09322e3L;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   800
        z = (z ^ (z >>> 32)) * 0xdaba0b6eb09322e3L;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   801
        return z ^ (z >>> 32);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   802
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   803
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   804
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   805
     * Computes the 32-bit mixing function for MurmurHash3.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   806
     * This is a 32-bit hashing function with excellent avalanche statistics.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   807
     * https://github.com/aappleby/smhasher/wiki/MurmurHash3
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   808
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   809
     * Note that if the argument {@code z} is 0, the result is 0.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   810
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   811
     * @param z any long value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   812
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   813
     * @return the result of hashing z
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   814
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   815
    public static int mixMurmur32(int z) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   816
        z = (z ^ (z >>> 16)) * 0x85ebca6b;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   817
        z = (z ^ (z >>> 13)) * 0xc2b2ae35;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   818
        return z ^ (z >>> 16);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   819
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   820
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   821
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   822
     * Computes Doug Lea's 32-bit mixing function.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   823
     * This is a 32-bit hashing function with excellent avalanche statistics.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   824
     * It has the advantages of using the same multiplicative constant twice
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   825
     * and of using only 16-bit shifts.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   826
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   827
     * Note that if the argument {@code z} is 0, the result is 0.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   828
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   829
     * @param z any long value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   830
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   831
     * @return the result of hashing z
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   832
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   833
    public static int mixLea32(int z) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   834
        z = (z ^ (z >>> 16)) * 0xd36d884b;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   835
        z = (z ^ (z >>> 16)) * 0xd36d884b;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   836
        return z ^ (z >>> 16);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   837
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   838
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   839
    // Non-public (package only) support for spliterators needed by AbstractSplittableGenerator
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   840
    // and AbstractArbitrarilyJumpableGenerator and AbstractSharedGenerator
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   841
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   842
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   843
     * Base class for making Spliterator classes for streams of randomly chosen values.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   844
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   845
    public abstract static class RandomSpliterator {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   846
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   847
        /** low range value */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   848
        public long index;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   849
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   850
        /** high range value */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   851
        public final long fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   852
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   853
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   854
         * Constructor
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   855
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   856
         * @param index  low range value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   857
         * @param fence  high range value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   858
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   859
        public RandomSpliterator(long index, long fence) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   860
            this.index = index; this.fence = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   861
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   862
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   863
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   864
         * Returns estimated size.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   865
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   866
         * @return estimated size
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   867
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   868
        public long estimateSize() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   869
            return fence - index;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   870
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   871
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   872
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   873
         * Returns characteristics.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   874
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   875
         * @return characteristics
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   876
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   877
        public int characteristics() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   878
            return (Spliterator.SIZED | Spliterator.SUBSIZED |
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   879
                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   880
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   881
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   882
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   883
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   884
    /*
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   885
     * Implementation support for nextExponential() and nextGaussian() methods of RandomGenerator.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   886
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   887
     * Each is implemented using McFarland's fast modified ziggurat algorithm (largely
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   888
     * table-driven, with rare cases handled by computation and rejection sampling).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   889
     * Walker's alias method for sampling a discrete distribution also plays a role.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   890
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   891
     * The tables themselves, as well as a number of associated parameters, are defined
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   892
     * in class java.util.DoubleZigguratTables, which is automatically generated by the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   893
     * program create_ziggurat_tables.c (which takes only a few seconds to run).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   894
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   895
     * For more information about the algorithms, see these articles:
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   896
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   897
     * Christopher D. McFarland.  2016 (published online 24 Jun 2015).  A modified ziggurat
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   898
     * algorithm for generating exponentially and normally distributed pseudorandom numbers.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   899
     * Journal of Statistical Computation and Simulation 86 (7), pages 1281-1294.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   900
     * https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   901
     * Also at https://arxiv.org/abs/1403.6870 (26 March 2014).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   902
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   903
     * Alastair J. Walker.  1977.  An efficient method for generating discrete random
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   904
     * variables with general distributions. ACM Trans. Math. Software 3, 3
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   905
     * (September 1977), 253-256. DOI: https://doi.org/10.1145/355744.355749
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   906
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   907
     * Certain details of these algorithms depend critically on the quality of the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   908
     * low-order bits delivered by NextLong().  These algorithms should not be used
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   909
     * with RNG algorithms (such as a simple Linear Congruential Generator) whose
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   910
     * low-order output bits do not have good statistical quality.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   911
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   912
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   913
    // Implementation support for nextExponential()
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   914
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   915
    static double computeNextExponential(RandomGenerator rng) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   916
        long U1 = rng.nextLong();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   917
        // Experimentation on a variety of machines indicates that it is overall much faster
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   918
        // to do the following & and < operations on longs rather than first cast U1 to int
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   919
        // (but then we need to cast to int before doing the array indexing operation).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   920
        long i = U1 & DoubleZigguratTables.exponentialLayerMask;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   921
        if (i < DoubleZigguratTables.exponentialNumberOfLayers) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   922
            // This is the fast path (occurring more than 98% of the time).  Make an early exit.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   923
            return DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   924
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   925
        // We didn't use the upper part of U1 after all.  We'll be able to use it later.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   926
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   927
        for (double extra = 0.0; ; ) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   928
            // Use Walker's alias method to sample an (unsigned) integer j from a discrete
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   929
            // probability distribution that includes the tail and all the ziggurat overhangs;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   930
            // j will be less than DoubleZigguratTables.exponentialNumberOfLayers + 1.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   931
            long UA = rng.nextLong();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   932
            int j = (int)UA & DoubleZigguratTables.exponentialAliasMask;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   933
            if (UA >= DoubleZigguratTables.exponentialAliasThreshold[j]) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   934
                j = DoubleZigguratTables.exponentialAliasMap[j] &
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   935
                    DoubleZigguratTables.exponentialSignCorrectionMask;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   936
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   937
            if (j > 0) {   // Sample overhang j
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   938
                // For the exponential distribution, every overhang is convex.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   939
                final double[] X = DoubleZigguratTables.exponentialX;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   940
                final double[] Y = DoubleZigguratTables.exponentialY;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   941
                for (;; U1 = (rng.nextLong() >>> 1)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   942
                    long U2 = (rng.nextLong() >>> 1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   943
                    // Compute the actual x-coordinate of the randomly chosen point.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   944
                    double x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   945
                    // Does the point lie below the curve?
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   946
                    long Udiff = U2 - U1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   947
                    if (Udiff < 0) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   948
                        // We picked a point in the upper-right triangle.  None of those can be
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   949
                        // accepted.  So remap the point into the lower-left triangle and try that.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   950
                        // In effect, we swap U1 and U2, and invert the sign of Udiff.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   951
                        Udiff = -Udiff;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   952
                        U2 = U1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   953
                        U1 -= Udiff;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   954
                    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   955
                    if (Udiff >= DoubleZigguratTables.exponentialConvexMargin) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   956
                        return x + extra;   // The chosen point is way below the curve; accept it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   957
                    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   958
                    // Compute the actual y-coordinate of the randomly chosen point.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   959
                    double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   960
                    // Now see how that y-coordinate compares to the curve
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   961
                    if (y <= Math.exp(-x)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   962
                        return x + extra;   // The chosen point is below the curve; accept it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   963
                    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   964
                    // Otherwise, we reject this sample and have to try again.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   965
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   966
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   967
            // We are now committed to sampling from the tail.  We could do a recursive call
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   968
            // and then add X[0] but we save some time and stack space by using an iterative loop.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   969
            extra += DoubleZigguratTables.exponentialX0;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   970
            // This is like the first five lines of this method, but if it returns, it first adds "extra".
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   971
            U1 = rng.nextLong();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   972
            i = U1 & DoubleZigguratTables.exponentialLayerMask;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   973
            if (i < DoubleZigguratTables.exponentialNumberOfLayers) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   974
                return DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1) + extra;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   975
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   976
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   977
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   978
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   979
    // Implementation support for nextGaussian()
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   980
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   981
    static double computeNextGaussian(RandomGenerator rng) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   982
        long U1 = rng.nextLong();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   983
        // Experimentation on a variety of machines indicates that it is overall much faster
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   984
        // to do the following & and < operations on longs rather than first cast U1 to int
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   985
        // (but then we need to cast to int before doing the array indexing operation).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   986
        long i = U1 & DoubleZigguratTables.normalLayerMask;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   987
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   988
        if (i < DoubleZigguratTables.normalNumberOfLayers) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   989
            // This is the fast path (occurring more than 98% of the time).  Make an early exit.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   990
            return DoubleZigguratTables.normalX[(int)i] * U1;   // Note that the sign bit of U1 is used here.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   991
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   992
        // We didn't use the upper part of U1 after all.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   993
        // Pull U1 apart into a sign bit and a 63-bit value for later use.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   994
        double signBit = (U1 >= 0) ? 1.0 : -1.0;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   995
        U1 = (U1 << 1) >>> 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   996
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   997
        // Use Walker's alias method to sample an (unsigned) integer j from a discrete
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   998
        // probability distribution that includes the tail and all the ziggurat overhangs;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
   999
        // j will be less than DoubleZigguratTables.normalNumberOfLayers + 1.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1000
        long UA = rng.nextLong();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1001
        int j = (int)UA & DoubleZigguratTables.normalAliasMask;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1002
        if (UA >= DoubleZigguratTables.normalAliasThreshold[j]) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1003
            j = DoubleZigguratTables.normalAliasMap[j] & DoubleZigguratTables.normalSignCorrectionMask;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1004
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1005
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1006
        double x;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1007
        // Now the goal is to choose the result, which will be multiplied by signBit just before return.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1008
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1009
        // There are four kinds of overhangs:
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1010
        //
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1011
        //  j == 0                          :  Sample from tail
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1012
        //  0 < j < normalInflectionIndex   :  Overhang is convex; can reject upper-right triangle
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1013
        //  j == normalInflectionIndex      :  Overhang includes the inflection point
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1014
        //  j > normalInflectionIndex       :  Overhang is concave; can accept point in lower-left triangle
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1015
        //
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1016
        // Choose one of four loops to compute x, each specialized for a specific kind of overhang.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1017
        // Conditional statements are arranged such that the more likely outcomes are first.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1018
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1019
        // In the three cases other than the tail case:
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1020
        // U1 represents a fraction (scaled by 2**63) of the width of rectangle measured from the left.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1021
        // U2 represents a fraction (scaled by 2**63) of the height of rectangle measured from the top.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1022
        // Together they indicate a randomly chosen point within the rectangle.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1023
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1024
        final double[] X = DoubleZigguratTables.normalX;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1025
        final double[] Y = DoubleZigguratTables.normalY;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1026
        if (j > DoubleZigguratTables.normalInflectionIndex) {   // Concave overhang
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1027
            for (;; U1 = (rng.nextLong() >>> 1)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1028
                long U2 = (rng.nextLong() >>> 1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1029
                // Compute the actual x-coordinate of the randomly chosen point.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1030
                x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1031
                // Does the point lie below the curve?
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1032
                long Udiff = U2 - U1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1033
                if (Udiff >= 0) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1034
                    break;   // The chosen point is in the lower-left triangle; accept it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1035
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1036
                if (Udiff <= -DoubleZigguratTables.normalConcaveMargin) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1037
                    continue;   // The chosen point is way above the curve; reject it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1038
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1039
                // Compute the actual y-coordinate of the randomly chosen point.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1040
                double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1041
                // Now see how that y-coordinate compares to the curve
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1042
                if (y <= Math.exp(-0.5*x*x)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1043
                    break;   // The chosen point is below the curve; accept it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1044
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1045
                // Otherwise, we reject this sample and have to try again.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1046
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1047
        } else if (j == 0) {   // Tail
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1048
            // Tail-sampling method of Marsaglia and Tsang.  See any one of:
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1049
            // Marsaglia and Tsang. 1984. A fast, easily implemented method for sampling from decreasing
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1050
            //    or symmetric unimodal density functions. SIAM J. Sci. Stat. Comput. 5, 349-359.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1051
            // Marsaglia and Tsang. 1998. The Monty Python method for generating random variables.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1052
            //    ACM Trans. Math. Softw. 24, 3 (September 1998), 341-350.  See page 342, step (4).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1053
            //    http://doi.org/10.1145/292395.292453
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1054
            // Thomas, Luk, Leong, and Villasenor. 2007. Gaussian random number generators.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1055
            //    ACM Comput. Surv. 39, 4, Article 11 (November 2007).  See Algorithm 16.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1056
            //    http://doi.org/10.1145/1287620.1287622
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1057
            // Compute two separate random exponential samples and then compare them in certain way.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1058
            do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1059
                x = (1.0 / DoubleZigguratTables.normalX0) * computeNextExponential(rng);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1060
            } while (computeNextExponential(rng) < 0.5*x*x);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1061
            x += DoubleZigguratTables.normalX0;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1062
        } else if (j < DoubleZigguratTables.normalInflectionIndex) {   // Convex overhang
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1063
            for (;; U1 = (rng.nextLong() >>> 1)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1064
                long U2 = (rng.nextLong() >>> 1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1065
                // Compute the actual x-coordinate of the randomly chosen point.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1066
                x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1067
                // Does the point lie below the curve?
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1068
                long Udiff = U2 - U1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1069
                if (Udiff < 0) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1070
                    // We picked a point in the upper-right triangle.  None of those can be accepted.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1071
                    // So remap the point into the lower-left triangle and try that.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1072
                    // In effect, we swap U1 and U2, and invert the sign of Udiff.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1073
                    Udiff = -Udiff;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1074
                    U2 = U1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1075
                    U1 -= Udiff;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1076
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1077
                if (Udiff >= DoubleZigguratTables.normalConvexMargin) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1078
                    break;   // The chosen point is way below the curve; accept it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1079
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1080
                // Compute the actual y-coordinate of the randomly chosen point.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1081
                double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1082
                // Now see how that y-coordinate compares to the curve
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1083
                if (y <= Math.exp(-0.5*x*x)) break; // The chosen point is below the curve; accept it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1084
                // Otherwise, we reject this sample and have to try again.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1085
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1086
        } else {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1087
            // The overhang includes the inflection point, so the curve is both convex and concave
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1088
            for (;; U1 = (rng.nextLong() >>> 1)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1089
                long U2 = (rng.nextLong() >>> 1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1090
                // Compute the actual x-coordinate of the randomly chosen point.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1091
                x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1092
                // Does the point lie below the curve?
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1093
                long Udiff = U2 - U1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1094
                if (Udiff >= DoubleZigguratTables.normalConvexMargin) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1095
                    break;   // The chosen point is way below the curve; accept it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1096
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1097
                if (Udiff <= -DoubleZigguratTables.normalConcaveMargin) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1098
                    continue;   // The chosen point is way above the curve; reject it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1099
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1100
                // Compute the actual y-coordinate of the randomly chosen point.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1101
                double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1102
                // Now see how that y-coordinate compares to the curve
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1103
                if (y <= Math.exp(-0.5*x*x)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1104
                    break;   // The chosen point is below the curve; accept it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1105
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1106
                // Otherwise, we reject this sample and have to try again.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1107
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1108
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1109
        return signBit*x;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1110
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1111
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1112
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1113
     * This class overrides the stream-producing methods (such as {@code ints()})
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1114
     * in class {@link AbstractGenerator} to provide {@link Spliterator}-based
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1115
     * implmentations that support potentially parallel execution.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1116
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1117
     * To implement a pseudorandom number generator, the programmer needs
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1118
     * only to extend this class and provide implementations for the methods
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1119
     * {@code nextInt()}, {@code nextLong()}, {@code makeIntsSpliterator},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1120
     * {@code makeLongsSpliterator}, and {@code makeDoublesSpliterator}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1121
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1122
     * This class is not public; it provides shared code to the public
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1123
     * classes {@link AbstractSplittableGenerator}, {@link AbstractSharedGenerator},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1124
     * and {@link AbstractArbitrarilyJumpableGenerator}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1125
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1126
     * @since 14
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1127
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1128
    public abstract static class AbstractSpliteratorGenerator implements RandomGenerator {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1129
        /*
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1130
         * Implementation Overview.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1131
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1132
         * This class provides most of the "user API" methods needed to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1133
         * satisfy the interface RandomGenerator.  An implementation of this
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1134
         * interface need only extend this class and provide implementations
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1135
         * of six methods: nextInt, nextLong, and nextDouble (the versions
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1136
         * that take no arguments) and makeIntsSpliterator,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1137
         * makeLongsSpliterator, and makeDoublesSpliterator.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1138
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1139
         * File organization: First the non-public abstract methods needed
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1140
         * to create spliterators, then the main public methods.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1141
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1142
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1143
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1144
         * Create an instance of {@link Spliterator.OfInt} that for each traversal position
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1145
	 * between the specified index (inclusive) and the specified fence (exclusive) generates
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1146
	 * a pseudorandomly chosen {@code int} value between the specified origin (inclusive) and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1147
	 * the specified bound (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1148
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1149
         * @param index the (inclusive) lower bound on traversal positions
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1150
         * @param fence the (exclusive) upper bound on traversal positions
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1151
         * @param origin the (inclusive) lower bound on the pseudorandom values to be generated
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1152
         * @param bound the (exclusive) upper bound on the pseudorandom values to be generated
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1153
         * @return an instance of {@link Spliterator.OfInt}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1154
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1155
        public abstract Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1156
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1157
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1158
         * Create an instance of {@link Spliterator.OfLong} that for each traversal position
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1159
	 * between the specified index (inclusive) and the specified fence (exclusive) generates
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1160
	 * a pseudorandomly chosen {@code long} value between the specified origin (inclusive) and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1161
	 * the specified bound (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1162
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1163
         * @param index the (inclusive) lower bound on traversal positions
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1164
         * @param fence the (exclusive) upper bound on traversal positions
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1165
         * @param origin the (inclusive) lower bound on the pseudorandom values to be generated
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1166
         * @param bound the (exclusive) upper bound on the pseudorandom values to be generated
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1167
         * @return an instance of {@link Spliterator.OfLong}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1168
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1169
        public abstract Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1170
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1171
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1172
         * Create an instance of {@link Spliterator.OfDouble} that for each traversal position
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1173
	 * between the specified index (inclusive) and the specified fence (exclusive) generates
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1174
	 * a pseudorandomly chosen {@code double} value between the specified origin (inclusive) and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1175
	 * the specified bound (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1176
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1177
         * @param index the (inclusive) lower bound on traversal positions
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1178
         * @param fence the (exclusive) upper bound on traversal positions
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1179
         * @param origin the (inclusive) lower bound on the pseudorandom values to be generated
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1180
         * @param bound the (exclusive) upper bound on the pseudorandom values to be generated
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1181
         * @return an instance of {@link Spliterator.OfDouble}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1182
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1183
        public abstract Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1184
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1185
        /* ---------------- public methods ---------------- */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1186
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1187
        // stream methods, coded in a way intended to better isolate for
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1188
        // maintenance purposes the small differences across forms.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1189
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1190
        private static IntStream intStream(Spliterator.OfInt srng) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1191
            return StreamSupport.intStream(srng, false);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1192
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1193
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1194
        private static LongStream longStream(Spliterator.OfLong srng) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1195
            return StreamSupport.longStream(srng, false);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1196
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1197
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1198
        private static DoubleStream doubleStream(Spliterator.OfDouble srng) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1199
            return StreamSupport.doubleStream(srng, false);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1200
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1201
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1202
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1203
         * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code int}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1204
         * values from this generator and/or one split from it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1205
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1206
         * @param streamSize the number of values to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1207
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1208
         * @return a stream of pseudorandom {@code int} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1209
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1210
         * @throws IllegalArgumentException if {@code streamSize} is less than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1211
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1212
        public IntStream ints(long streamSize) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1213
            RandomSupport.checkStreamSize(streamSize);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1214
            return intStream(makeIntsSpliterator(0L, streamSize, Integer.MAX_VALUE, 0));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1215
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1216
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1217
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1218
         * Returns an effectively unlimited stream of pseudorandomly chosen
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1219
         * {@code int} values.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1220
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1221
         * @implNote The implementation of this method is effectively
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1222
         * equivalent to {@code ints(Long.MAX_VALUE)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1223
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1224
         * @return a stream of pseudorandomly chosen {@code int} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1225
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1226
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1227
        public IntStream ints() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1228
            return intStream(makeIntsSpliterator(0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1229
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1230
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1231
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1232
         * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code int}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1233
         * values from this generator and/or one split from it; each value conforms to the given origin
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1234
         * (inclusive) and bound (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1235
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1236
         * @param streamSize         the number of values to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1237
         * @param randomNumberOrigin the origin (inclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1238
         * @param randomNumberBound  the bound (exclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1239
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1240
         * @return a stream of pseudorandom {@code int} values, each with the given origin (inclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1241
         *         and bound (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1242
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1243
         * @throws IllegalArgumentException if {@code streamSize} is less than zero, or {@code
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1244
         *                                  randomNumberOrigin} is greater than or equal to {@code
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1245
         *                                  randomNumberBound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1246
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1247
        public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1248
            RandomSupport.checkStreamSize(streamSize);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1249
            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1250
            return intStream(makeIntsSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1251
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1252
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1253
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1254
         * Returns an effectively unlimited stream of pseudorandom {@code int} values from this
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1255
         * generator and/or one split from it; each value conforms to the given origin (inclusive) and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1256
         * bound (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1257
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1258
         * @param randomNumberOrigin the origin (inclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1259
         * @param randomNumberBound  the bound (exclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1260
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1261
         * @return a stream of pseudorandom {@code int} values, each with the given origin (inclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1262
         *         and bound (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1263
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1264
         * @throws IllegalArgumentException if {@code randomNumberOrigin} is greater than or equal to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1265
         *                                  {@code randomNumberBound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1266
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1267
         * @implNote This method is implemented to be equivalent to {@code ints(Long.MAX_VALUE,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1268
         *         randomNumberOrigin, randomNumberBound)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1269
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1270
        public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1271
            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1272
            return intStream(makeIntsSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1273
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1274
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1275
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1276
         * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code long}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1277
         * values from this generator and/or one split from it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1278
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1279
         * @param streamSize the number of values to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1280
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1281
         * @return a stream of pseudorandom {@code long} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1282
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1283
         * @throws IllegalArgumentException if {@code streamSize} is less than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1284
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1285
        public LongStream longs(long streamSize) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1286
            RandomSupport.checkStreamSize(streamSize);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1287
            return longStream(makeLongsSpliterator(0L, streamSize, Long.MAX_VALUE, 0L));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1288
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1289
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1290
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1291
         * Returns an effectively unlimited stream of pseudorandom {@code long} values from this
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1292
         * generator and/or one split from it.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1293
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1294
         * @return a stream of pseudorandom {@code long} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1295
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1296
         * @implNote This method is implemented to be equivalent to {@code
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1297
         *         longs(Long.MAX_VALUE)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1298
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1299
        public LongStream longs() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1300
            return longStream(makeLongsSpliterator(0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1301
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1302
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1303
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1304
         * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code long}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1305
         * values from this generator and/or one split from it; each value conforms to the given origin
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1306
         * (inclusive) and bound (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1307
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1308
         * @param streamSize         the number of values to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1309
         * @param randomNumberOrigin the origin (inclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1310
         * @param randomNumberBound  the bound (exclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1311
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1312
         * @return a stream of pseudorandom {@code long} values, each with the given origin (inclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1313
         *         and bound (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1314
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1315
         * @throws IllegalArgumentException if {@code streamSize} is less than zero, or {@code
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1316
         *                                  randomNumberOrigin} is greater than or equal to {@code
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1317
         *                                  randomNumberBound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1318
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1319
        public LongStream longs(long streamSize, long randomNumberOrigin,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1320
                                 long randomNumberBound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1321
            RandomSupport.checkStreamSize(streamSize);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1322
            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1323
            return longStream(makeLongsSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1324
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1325
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1326
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1327
         * Returns an effectively unlimited stream of pseudorandom {@code long} values from this
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1328
         * generator and/or one split from it; each value conforms to the given origin (inclusive) and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1329
         * bound (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1330
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1331
         * @param randomNumberOrigin the origin (inclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1332
         * @param randomNumberBound  the bound (exclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1333
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1334
         * @return a stream of pseudorandom {@code long} values, each with the given origin (inclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1335
         *         and bound (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1336
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1337
         * @throws IllegalArgumentException if {@code randomNumberOrigin} is greater than or equal to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1338
         *                                  {@code randomNumberBound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1339
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1340
         * @implNote This method is implemented to be equivalent to {@code longs(Long.MAX_VALUE,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1341
         *         randomNumberOrigin, randomNumberBound)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1342
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1343
        public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1344
            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1345
            return StreamSupport.longStream
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1346
                (makeLongsSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1347
                 false);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1348
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1349
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1350
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1351
         * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code double}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1352
         * values from this generator and/or one split from it; each value is between zero (inclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1353
         * and one (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1354
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1355
         * @param streamSize the number of values to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1356
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1357
         * @return a stream of {@code double} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1358
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1359
         * @throws IllegalArgumentException if {@code streamSize} is less than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1360
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1361
        public DoubleStream doubles(long streamSize) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1362
            RandomSupport.checkStreamSize(streamSize);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1363
            return doubleStream(makeDoublesSpliterator(0L, streamSize, Double.MAX_VALUE, 0.0));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1364
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1365
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1366
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1367
         * Returns an effectively unlimited stream of pseudorandom {@code double} values from this
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1368
         * generator and/or one split from it; each value is between zero (inclusive) and one
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1369
         * (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1370
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1371
         * @return a stream of pseudorandom {@code double} values
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1372
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1373
         * @implNote This method is implemented to be equivalent to {@code
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1374
         *         doubles(Long.MAX_VALUE)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1375
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1376
        public DoubleStream doubles() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1377
            return doubleStream(makeDoublesSpliterator(0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1378
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1379
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1380
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1381
         * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code double}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1382
         * values from this generator and/or one split from it; each value conforms to the given origin
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1383
         * (inclusive) and bound (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1384
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1385
         * @param streamSize         the number of values to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1386
         * @param randomNumberOrigin the origin (inclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1387
         * @param randomNumberBound  the bound (exclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1388
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1389
         * @return a stream of pseudorandom {@code double} values, each with the given origin
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1390
         *         (inclusive) and bound (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1391
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1392
         * @throws IllegalArgumentException if {@code streamSize} is less than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1393
         * @throws IllegalArgumentException if {@code randomNumberOrigin} is greater than or equal to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1394
         *                                  {@code randomNumberBound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1395
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1396
        public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1397
            RandomSupport.checkStreamSize(streamSize);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1398
            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1399
            return doubleStream(makeDoublesSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1400
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1401
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1402
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1403
         * Returns an effectively unlimited stream of pseudorandom {@code double} values from this
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1404
         * generator and/or one split from it; each value conforms to the given origin (inclusive) and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1405
         * bound (exclusive).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1406
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1407
         * @param randomNumberOrigin the origin (inclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1408
         * @param randomNumberBound  the bound (exclusive) of each random value
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1409
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1410
         * @return a stream of pseudorandom {@code double} values, each with the given origin
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1411
         *         (inclusive) and bound (exclusive)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1412
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1413
         * @throws IllegalArgumentException if {@code randomNumberOrigin} is greater than or equal to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1414
         *                                  {@code randomNumberBound}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1415
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1416
         * @implNote This method is implemented to be equivalent to {@code
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1417
         *         doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1418
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1419
        public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1420
            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1421
            return doubleStream(makeDoublesSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1422
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1423
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1424
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1425
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1426
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1427
     * This class provides much of the implementation of the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1428
     * {@link ArbitrarilyJumpableGenerator} interface, to minimize the effort
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1429
     * required to implement that interface.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1430
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1431
     * To implement a pseudorandom number generator, the programmer needs
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1432
     * only to extend this class and provide implementations for the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1433
     * methods {@link #nextInt()}, {@link #nextLong()}, {@link #copy()},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1434
     * {@link #jump(double)}, {@link #jumpPowerOfTwo(int)},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1435
     * {@link #defaultJumpDistance()}, and {@link #defaultLeapDistance()}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1436
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1437
     * (If the pseudorandom number generator also has the ability to split,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1438
     * then the programmer may wish to consider instead extending
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1439
     * {@link AbstractSplittableGenerator}.)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1440
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1441
     * The programmer should generally provide at least three constructors:
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1442
     * one that takes no arguments, one that accepts a {@code long}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1443
     * seed value, and one that accepts an array of seed {@code byte} values.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1444
     * This class provides a public {@code initialSeed()} method that may
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1445
     * be useful in initializing some static state from which to derive
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1446
     * defaults seeds for use by the no-argument constructor.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1447
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1448
     * For the stream methods (such as {@code ints()} and {@code splits()}),
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1449
     * this class provides {@link Spliterator}-based implementations that
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1450
     * allow parallel execution when appropriate.  In this respect
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1451
     * {@link ArbitrarilyJumpableGenerator} differs from {@link JumpableGenerator},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1452
     * which provides very simple implementations that produce
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1453
     * sequential streams only.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1454
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1455
     * <p>An implementation of the {@link AbstractArbitrarilyJumpableGenerator} class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1456
     * must provide concrete definitions for the methods {@code nextInt()},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1457
     * {@code nextLong}, {@code period()}, {@code copy()}, {@code jump(double)},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1458
     * {@code defaultJumpDistance()}, and {@code defaultLeapDistance()}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1459
     * Default implementations are provided for all other methods.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1460
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1461
     * The documentation for each non-abstract method in this class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1462
     * describes its implementation in detail. Each of these methods may
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1463
     * be overridden if the pseudorandom number generator being
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1464
     * implemented admits a more efficient implementation.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1465
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1466
     * @since 14
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1467
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1468
    public abstract static class AbstractArbitrarilyJumpableGenerator
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1469
        extends AbstractSpliteratorGenerator implements RandomGenerator.ArbitrarilyJumpableGenerator {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1470
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1471
        /*
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1472
         * Implementation Overview.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1473
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1474
         * This class provides most of the "user API" methods needed to satisfy
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1475
         * the interface ArbitrarilyJumpableGenerator.  Most of these methods
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1476
         * are in turn inherited from AbstractGenerator and the non-public class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1477
         * AbstractSpliteratorGenerator; this file implements four versions of the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1478
         * jumps method and defines the spliterators necessary to support them.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1479
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1480
         * File organization: First the non-public methods needed by the class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1481
         * AbstractSpliteratorGenerator, then the main public methods, followed by some
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1482
         * custom spliterator classes needed for stream methods.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1483
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1484
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1485
        // IllegalArgumentException messages
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1486
        static final String BadLogDistance  = "logDistance must be non-negative";
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1487
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1488
        // Methods required by class AbstractSpliteratorGenerator
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1489
        public Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1490
            return new RandomIntsSpliterator(this, index, fence, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1491
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1492
        public Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1493
            return new RandomLongsSpliterator(this, index, fence, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1494
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1495
        public Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1496
            return new RandomDoublesSpliterator(this, index, fence, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1497
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1498
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1499
        // Similar methods used by this class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1500
        Spliterator<RandomGenerator> makeJumpsSpliterator(long index, long fence, double distance) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1501
            return new RandomJumpsSpliterator(this, index, fence, distance);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1502
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1503
        Spliterator<JumpableGenerator> makeLeapsSpliterator(long index, long fence, double distance) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1504
            return new RandomLeapsSpliterator(this, index, fence, distance);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1505
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1506
        Spliterator<ArbitrarilyJumpableGenerator> makeArbitraryJumpsSpliterator(long index, long fence, double distance) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1507
            return new RandomArbitraryJumpsSpliterator(this, index, fence, distance);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1508
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1509
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1510
        /* ---------------- public methods ---------------- */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1511
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1512
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1513
         * Returns a new generator whose internal state is an exact copy
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1514
         * of this generator (therefore their future behavior should be
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1515
         * identical if subjected to the same series of operations).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1516
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1517
         * @return a new object that is a copy of this generator
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1518
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1519
        public abstract AbstractArbitrarilyJumpableGenerator copy();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1520
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1521
        // Stream methods for jumping
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1522
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1523
        private static <T> Stream<T> stream(Spliterator<T> srng) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1524
            return StreamSupport.stream(srng, false);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1525
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1526
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1527
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1528
         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1529
         * implements the {@link RandomGenerator} interface, produced by jumping copies of this
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1530
         * generator by different integer multiples of the default jump distance.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1531
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1532
         * @return a stream of objects that implement the {@link RandomGenerator} interface
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1533
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1534
         * @implNote This method is implemented to be equivalent to {@code
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1535
         *         jumps(Long.MAX_VALUE)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1536
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1537
        public Stream<RandomGenerator> jumps() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1538
            return stream(makeJumpsSpliterator(0L, Long.MAX_VALUE, defaultJumpDistance()));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1539
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1540
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1541
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1542
         * Returns a stream producing the given {@code streamSize} number of
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1543
         * new pseudorandom number generators, each of which implements the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1544
         * {@link RandomGenerator} interface, produced by jumping copies of this generator
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1545
         * by different integer multiples of the default jump distance.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1546
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1547
         * @param streamSize the number of generators to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1548
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1549
         * @return a stream of objects that implement the {@link RandomGenerator} interface
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1550
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1551
         * @throws IllegalArgumentException if {@code streamSize} is less than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1552
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1553
        public Stream<RandomGenerator> jumps(long streamSize) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1554
            RandomSupport.checkStreamSize(streamSize);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1555
            return stream(makeJumpsSpliterator(0L, streamSize, defaultJumpDistance()));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1556
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1557
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1558
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1559
         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1560
         * implements the {@link RandomGenerator} interface, produced by jumping copies of this
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1561
         * generator by different integer multiples of the specified jump distance.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1562
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1563
         * @param distance a distance to jump forward within the state cycle
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1564
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1565
         * @return a stream of objects that implement the {@link RandomGenerator} interface
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1566
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1567
         * @implNote This method is implemented to be equivalent to {@code
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1568
         *         jumps(Long.MAX_VALUE)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1569
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1570
        public Stream<ArbitrarilyJumpableGenerator> jumps(double distance) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1571
            return stream(makeArbitraryJumpsSpliterator(0L, Long.MAX_VALUE, distance));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1572
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1573
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1574
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1575
         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1576
         * generators, each of which implements the {@link RandomGenerator} interface, produced by
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1577
         * jumping copies of this generator by different integer multiples of the specified jump
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1578
         * distance.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1579
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1580
         * @param streamSize the number of generators to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1581
         * @param distance   a distance to jump forward within the state cycle
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1582
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1583
         * @return a stream of objects that implement the {@link RandomGenerator} interface
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1584
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1585
         * @throws IllegalArgumentException if {@code streamSize} is less than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1586
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1587
        public Stream<ArbitrarilyJumpableGenerator> jumps(long streamSize, double distance) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1588
            RandomSupport.checkStreamSize(streamSize);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1589
            return stream(makeArbitraryJumpsSpliterator(0L, streamSize, distance));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1590
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1591
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1592
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1593
         * Alter the state of this pseudorandom number generator so as to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1594
         * jump forward a very large, fixed distance (typically 2<sup>128</sup>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1595
         * or more) within its state cycle.  The distance used is that
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1596
         * returned by method {@code defaultLeapDistance()}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1597
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1598
        public void leap() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1599
            jump(defaultLeapDistance());
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1600
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1601
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1602
        // Stream methods for leaping
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1603
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1604
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1605
         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1606
         * implements the {@link RandomGenerator} interface, produced by jumping copies of this
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1607
         * generator by different integer multiples of the default leap distance.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1608
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1609
         * @implNote This method is implemented to be equivalent to {@code leaps(Long.MAX_VALUE)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1610
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1611
         * @return a stream of objects that implement the {@link RandomGenerator} interface
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1612
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1613
        public Stream<JumpableGenerator> leaps() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1614
            return stream(makeLeapsSpliterator(0L, Long.MAX_VALUE, defaultLeapDistance()));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1615
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1616
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1617
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1618
         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1619
         * generators, each of which implements the {@link RandomGenerator} interface, produced by
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1620
         * jumping copies of this generator by different integer multiples of the default leap
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1621
         * distance.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1622
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1623
         * @param streamSize the number of generators to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1624
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1625
         * @return a stream of objects that implement the {@link RandomGenerator} interface
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1626
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1627
         * @throws IllegalArgumentException if {@code streamSize} is less than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1628
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1629
        public Stream<JumpableGenerator> leaps(long streamSize) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1630
            return stream(makeLeapsSpliterator(0L, streamSize, defaultLeapDistance()));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1631
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1632
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1633
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1634
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1635
         * Spliterator for int streams.  We multiplex the four int versions into one class by treating a
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1636
         * bound less than origin as unbounded, and also by treating "infinite" as equivalent to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1637
         * {@code Long.MAX_VALUE}. For splits, we choose to override the method {@code trySplit()} to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1638
         * try to optimize execution speed: instead of dividing a range in half, it breaks off the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1639
         * largest possible chunk whose size is a power of two such that the remaining chunk is not
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1640
         * empty. In this way, the necessary jump distances will tend to be powers of two.  The long
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1641
         * and double versions of this class are identical except for types.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1642
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1643
        static class RandomIntsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfInt {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1644
            final ArbitrarilyJumpableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1645
            final int origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1646
            final int bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1647
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1648
            RandomIntsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, int origin, int bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1649
                super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1650
                this.origin = origin; this.bound = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1651
                this.generatingGenerator = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1652
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1653
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1654
            public Spliterator.OfInt trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1655
                long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1656
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1657
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1658
                ArbitrarilyJumpableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1659
                return new RandomIntsSpliterator(r.copyAndJump((double)delta), i, m, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1660
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1661
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1662
            public boolean tryAdvance(IntConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1663
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1664
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1665
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1666
                    consumer.accept(RandomSupport.boundedNextInt(generatingGenerator, origin, bound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1667
                    index = i + 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1668
                    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1669
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1670
                else return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1671
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1672
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1673
            public void forEachRemaining(IntConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1674
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1675
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1676
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1677
                    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1678
                    ArbitrarilyJumpableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1679
                    int o = origin, b = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1680
                    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1681
                        consumer.accept(RandomSupport.boundedNextInt(r, o, b));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1682
                    } while (++i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1683
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1684
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1685
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1686
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1687
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1688
         * Spliterator for long streams.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1689
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1690
        static class RandomLongsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfLong {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1691
            final ArbitrarilyJumpableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1692
            final long origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1693
            final long bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1694
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1695
            RandomLongsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, long origin, long bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1696
                super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1697
                this.generatingGenerator = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1698
                this.origin = origin; this.bound = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1699
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1700
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1701
            public Spliterator.OfLong trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1702
                long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1703
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1704
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1705
                ArbitrarilyJumpableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1706
                return new RandomLongsSpliterator(r.copyAndJump((double)delta), i, m, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1707
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1708
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1709
            public boolean tryAdvance(LongConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1710
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1711
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1712
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1713
                    consumer.accept(RandomSupport.boundedNextLong(generatingGenerator, origin, bound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1714
                    index = i + 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1715
                    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1716
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1717
                else return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1718
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1719
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1720
            public void forEachRemaining(LongConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1721
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1722
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1723
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1724
                    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1725
                    ArbitrarilyJumpableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1726
                    long o = origin, b = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1727
                    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1728
                        consumer.accept(RandomSupport.boundedNextLong(r, o, b));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1729
                    } while (++i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1730
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1731
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1732
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1733
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1734
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1735
         * Spliterator for double streams.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1736
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1737
        static class RandomDoublesSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfDouble {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1738
            final ArbitrarilyJumpableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1739
            final double origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1740
            final double bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1741
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1742
            RandomDoublesSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double origin, double bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1743
                super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1744
                this.generatingGenerator = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1745
                this.origin = origin; this.bound = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1746
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1747
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1748
            public Spliterator.OfDouble trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1749
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1750
                long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1751
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1752
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1753
                ArbitrarilyJumpableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1754
                return new RandomDoublesSpliterator(r.copyAndJump((double)delta), i, m, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1755
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1756
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1757
            public boolean tryAdvance(DoubleConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1758
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1759
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1760
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1761
                    consumer.accept(RandomSupport.boundedNextDouble(generatingGenerator, origin, bound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1762
                    index = i + 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1763
                    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1764
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1765
                else return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1766
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1767
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1768
            public void forEachRemaining(DoubleConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1769
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1770
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1771
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1772
                    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1773
                    ArbitrarilyJumpableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1774
                    double o = origin, b = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1775
                    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1776
                        consumer.accept(RandomSupport.boundedNextDouble(r, o, b));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1777
                    } while (++i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1778
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1779
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1780
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1781
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1782
        // Spliterators for producing new generators by jumping or leaping.  The
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1783
        // complete implementation of each of these spliterators is right here.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1784
        // In the same manner as for the preceding spliterators, the method trySplit() is
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1785
        // coded to optimize execution speed: instead of dividing a range
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1786
        // in half, it breaks off the largest possible chunk whose
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1787
        // size is a power of two such that the remaining chunk is not
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1788
        // empty.  In this way, the necessary jump distances will tend to be
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1789
        // powers of two.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1790
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1791
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1792
         * Spliterator for stream of generators of type RandomGenerator produced by jumps.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1793
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1794
        static class RandomJumpsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator<RandomGenerator> {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1795
            ArbitrarilyJumpableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1796
            final double distance;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1797
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1798
            RandomJumpsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double distance) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1799
                super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1800
                this.generatingGenerator = generatingGenerator; this.distance = distance;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1801
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1802
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1803
            public Spliterator<RandomGenerator> trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1804
                long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1805
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1806
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1807
                ArbitrarilyJumpableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1808
                // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1809
                return new RandomJumpsSpliterator(r.copyAndJump(distance * (double)delta), i, m, distance);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1810
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1811
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1812
            public boolean tryAdvance(Consumer<? super RandomGenerator> consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1813
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1814
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1815
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1816
                    consumer.accept(generatingGenerator.copyAndJump(distance));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1817
                    index = i + 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1818
                    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1819
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1820
                return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1821
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1822
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1823
            public void forEachRemaining(Consumer<? super RandomGenerator> consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1824
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1825
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1826
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1827
                    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1828
                    ArbitrarilyJumpableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1829
                    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1830
                        consumer.accept(r.copyAndJump(distance));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1831
                    } while (++i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1832
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1833
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1834
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1835
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1836
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1837
         * Spliterator for stream of generators of type RandomGenerator produced by leaps.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1838
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1839
        static class RandomLeapsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator<JumpableGenerator> {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1840
            ArbitrarilyJumpableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1841
            final double distance;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1842
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1843
            RandomLeapsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double distance) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1844
                super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1845
                this.generatingGenerator = generatingGenerator; this.distance = distance;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1846
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1847
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1848
            public Spliterator<JumpableGenerator> trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1849
                long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1850
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1851
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1852
                // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1853
                return new RandomLeapsSpliterator(generatingGenerator.copyAndJump(distance * (double)delta), i, m, distance);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1854
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1855
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1856
            public boolean tryAdvance(Consumer<? super JumpableGenerator> consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1857
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1858
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1859
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1860
                    consumer.accept(generatingGenerator.copyAndJump(distance));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1861
                    index = i + 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1862
                    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1863
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1864
                return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1865
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1866
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1867
            public void forEachRemaining(Consumer<? super JumpableGenerator> consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1868
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1869
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1870
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1871
                    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1872
                    ArbitrarilyJumpableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1873
                    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1874
                        consumer.accept(r.copyAndJump(distance));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1875
                    } while (++i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1876
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1877
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1878
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1879
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1880
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1881
         * Spliterator for stream of generators of type RandomGenerator produced by arbitrary jumps.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1882
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1883
        static class RandomArbitraryJumpsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator<ArbitrarilyJumpableGenerator> {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1884
            ArbitrarilyJumpableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1885
            final double distance;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1886
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1887
            RandomArbitraryJumpsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double distance) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1888
                super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1889
                this.generatingGenerator = generatingGenerator; this.distance = distance;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1890
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1891
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1892
            public Spliterator<ArbitrarilyJumpableGenerator> trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1893
                long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1894
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1895
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1896
                // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1897
                return new RandomArbitraryJumpsSpliterator(generatingGenerator.copyAndJump(distance * (double)delta), i, m, distance);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1898
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1899
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1900
            public boolean tryAdvance(Consumer<? super ArbitrarilyJumpableGenerator> consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1901
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1902
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1903
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1904
                    consumer.accept(generatingGenerator.copyAndJump(distance));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1905
                    index = i + 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1906
                    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1907
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1908
                return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1909
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1910
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1911
            public void forEachRemaining(Consumer<? super ArbitrarilyJumpableGenerator> consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1912
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1913
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1914
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1915
                    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1916
                    ArbitrarilyJumpableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1917
                    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1918
                        consumer.accept(r.copyAndJump(distance));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1919
                    } while (++i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1920
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1921
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1922
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1923
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1924
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1925
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1926
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1927
     * This class provides much of the implementation of the {@link SplittableGenerator} interface, to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1928
     * minimize the effort required to implement this interface.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1929
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1930
     * To implement a pseudorandom number generator, the programmer needs only to extend this class and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1931
     * provide implementations for the methods {@code nextInt()}, {@code nextLong()}, {@code period()},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1932
     * and {@code split(SplittableGenerator)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1933
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1934
     * (If the pseudorandom number generator also has the ability to jump an arbitrary
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1935
     * specified distance, then the programmer may wish to consider instead extending the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1936
     * class {@link AbstractArbitrarilyJumpableGenerator}.  See also the class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1937
     * {@link AbstractSplittableWithBrineGenerator}.)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1938
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1939
     * The programmer should generally provide at least three constructors: one that takes no arguments,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1940
     * one that accepts a {@code long} seed value, and one that accepts an array of seed {@code byte}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1941
     * values. This class provides a public {@code initialSeed()} method that may be useful in
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1942
     * initializing some static state from which to derive defaults seeds for use by the no-argument
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1943
     * constructor.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1944
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1945
     * For the stream methods (such as {@code ints()} and {@code splits()}), this class provides
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1946
     * {@link Spliterator}-based implementations that allow parallel execution when appropriate.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1947
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1948
     * The documentation for each non-abstract method in this class describes its implementation in
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1949
     * detail. Each of these methods may be overridden if the pseudorandom number generator being
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1950
     * implemented admits a more efficient implementation.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1951
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1952
     * @since 14
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1953
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1954
    public abstract static class AbstractSplittableGenerator extends AbstractSpliteratorGenerator implements SplittableGenerator {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1955
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1956
        /*
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1957
         * Implementation Overview.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1958
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1959
         * This class provides most of the "user API" methods needed to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1960
         * satisfy the interface SplittableGenerator.  Most of these methods
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1961
         * are in turn inherited from AbstractGenerator and the non-public class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1962
         * AbstractSpliteratorGenerator; this class provides two versions of the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1963
         * splits method and defines the spliterators necessary to support
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1964
         * them.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1965
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1966
         * File organization: First the non-public methods needed by the class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1967
         * AbstractSpliteratorGenerator, then the main public methods, followed by some
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1968
         * custom spliterator classes.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1969
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1970
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1971
        public Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1972
            return new RandomIntsSpliterator(this, index, fence, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1973
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1974
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1975
        public Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1976
            return new RandomLongsSpliterator(this, index, fence, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1977
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1978
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1979
        public Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1980
            return new RandomDoublesSpliterator(this, index, fence, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1981
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1982
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1983
        Spliterator<SplittableGenerator> makeSplitsSpliterator(long index, long fence, SplittableGenerator source) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1984
            return new RandomSplitsSpliterator(source, index, fence, this);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1985
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1986
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1987
        /* ---------------- public methods ---------------- */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1988
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1989
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1990
         * Implements the @code{split()} method as {@code this.split(this)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1991
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1992
         * @return the new {@link SplittableGenerator} instance
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1993
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1994
        public SplittableGenerator split() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1995
            return this.split(this);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1996
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1997
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1998
        // Stream methods for splittings
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  1999
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2000
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2001
         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2002
         * implements the {@link SplittableGenerator} interface.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2003
         * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2004
         * This pseudorandom number generator provides the entropy used to seed the new ones.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2005
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2006
         * @return a stream of {@link SplittableGenerator} objects
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2007
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2008
         * @implNote This method is implemented to be equivalent to {@code splits(Long.MAX_VALUE)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2009
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2010
        public Stream<SplittableGenerator> splits() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2011
            return this.splits(Long.MAX_VALUE, this);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2012
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2013
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2014
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2015
         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2016
         * generators, each of which implements the {@link SplittableGenerator} interface.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2017
         * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2018
         * This pseudorandom number generator provides the entropy used to seed the new ones.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2019
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2020
         * @param streamSize the number of values to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2021
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2022
         * @return a stream of {@link SplittableGenerator} objects
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2023
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2024
         * @throws IllegalArgumentException if {@code streamSize} is less than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2025
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2026
        public Stream<SplittableGenerator> splits(long streamSize) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2027
            return this.splits(streamSize, this);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2028
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2029
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2030
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2031
         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2032
         * implements the {@link SplittableGenerator} interface.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2033
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2034
         * @param source a {@link SplittableGenerator} instance to be used instead of this one as a source of
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2035
         *               pseudorandom bits used to initialize the state of the new ones.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2036
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2037
         * @return a stream of {@link SplittableGenerator} objects
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2038
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2039
         * @implNote This method is implemented to be equivalent to {@code splits(Long.MAX_VALUE)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2040
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2041
        public Stream<SplittableGenerator> splits(SplittableGenerator source) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2042
            return this.splits(Long.MAX_VALUE, source);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2043
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2044
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2045
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2046
         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2047
         * generators, each of which implements the {@link SplittableGenerator} interface.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2048
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2049
         * @param streamSize the number of values to generate
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2050
         * @param source     a {@link SplittableGenerator} instance to be used instead of this one as a source
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2051
         *                   of pseudorandom bits used to initialize the state of the new ones.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2052
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2053
         * @return a stream of {@link SplittableGenerator} objects
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2054
         *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2055
         * @throws IllegalArgumentException if {@code streamSize} is less than zero
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2056
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2057
        public Stream<SplittableGenerator> splits(long streamSize, SplittableGenerator source) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2058
            RandomSupport.checkStreamSize(streamSize);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2059
            return StreamSupport.stream(makeSplitsSpliterator(0L, streamSize, source), false);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2060
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2061
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2062
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2063
         * Spliterator for int streams.  We multiplex the four int versions into one class by treating a
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2064
         * bound less than origin as unbounded, and also by treating "infinite" as equivalent to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2065
         * {@code Long.MAX_VALUE}. For splits, it uses the standard divide-by-two approach. The long and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2066
         * double versions of this class are identical except for types.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2067
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2068
        static class RandomIntsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfInt {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2069
            final SplittableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2070
            final int origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2071
            final int bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2072
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2073
            RandomIntsSpliterator(SplittableGenerator generatingGenerator, long index, long fence, int origin, int bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2074
                super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2075
                this.generatingGenerator = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2076
                this.origin = origin; this.bound = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2077
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2078
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2079
            public Spliterator.OfInt trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2080
                long i = index, m = (i + fence) >>> 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2081
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2082
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2083
                return new RandomIntsSpliterator(generatingGenerator.split(), i, m, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2084
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2085
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2086
            public boolean tryAdvance(IntConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2087
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2088
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2089
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2090
                    consumer.accept(RandomSupport.boundedNextInt(generatingGenerator, origin, bound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2091
                    index = i + 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2092
                    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2093
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2094
                else return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2095
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2096
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2097
            public void forEachRemaining(IntConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2098
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2099
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2100
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2101
                    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2102
                    RandomGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2103
                    int o = origin, b = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2104
                    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2105
                        consumer.accept(RandomSupport.boundedNextInt(r, o, b));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2106
                    } while (++i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2107
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2108
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2109
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2110
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2111
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2112
         * Spliterator for long streams.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2113
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2114
        static class RandomLongsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfLong {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2115
            final SplittableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2116
            final long origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2117
            final long bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2118
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2119
            RandomLongsSpliterator(SplittableGenerator generatingGenerator, long index, long fence, long origin, long bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2120
                super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2121
                this.generatingGenerator = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2122
                this.origin = origin; this.bound = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2123
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2124
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2125
            public Spliterator.OfLong trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2126
                long i = index, m = (i + fence) >>> 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2127
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2128
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2129
                return new RandomLongsSpliterator(generatingGenerator.split(), i, m, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2130
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2131
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2132
            public boolean tryAdvance(LongConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2133
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2134
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2135
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2136
                    consumer.accept(RandomSupport.boundedNextLong(generatingGenerator, origin, bound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2137
                    index = i + 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2138
                    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2139
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2140
                else return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2141
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2142
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2143
            public void forEachRemaining(LongConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2144
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2145
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2146
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2147
                    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2148
                    RandomGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2149
                    long o = origin, b = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2150
                    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2151
                        consumer.accept(RandomSupport.boundedNextLong(r, o, b));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2152
                    } while (++i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2153
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2154
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2155
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2156
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2157
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2158
         * Spliterator for double streams.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2159
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2160
        static class RandomDoublesSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfDouble {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2161
            final SplittableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2162
            final double origin;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2163
            final double bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2164
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2165
            RandomDoublesSpliterator(SplittableGenerator generatingGenerator, long index, long fence, double origin, double bound) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2166
                super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2167
                this.generatingGenerator = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2168
                this.origin = origin; this.bound = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2169
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2170
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2171
            public Spliterator.OfDouble trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2172
                long i = index, m = (i + fence) >>> 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2173
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2174
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2175
                return new RandomDoublesSpliterator(generatingGenerator.split(), i, m, origin, bound);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2176
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2177
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2178
            public boolean tryAdvance(DoubleConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2179
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2180
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2181
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2182
                    consumer.accept(RandomSupport.boundedNextDouble(generatingGenerator, origin, bound));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2183
                    index = i + 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2184
                    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2185
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2186
                else return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2187
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2188
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2189
            public void forEachRemaining(DoubleConsumer consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2190
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2191
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2192
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2193
                    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2194
                    RandomGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2195
                    double o = origin, b = bound;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2196
                    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2197
                        consumer.accept(RandomSupport.boundedNextDouble(r, o, b));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2198
                    } while (++i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2199
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2200
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2201
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2202
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2203
        /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2204
         * Spliterator for stream of generators of type SplittableGenerator.  We multiplex the two
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2205
         * versions into one class by treating "infinite" as equivalent to Long.MAX_VALUE.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2206
         * For splits, it uses the standard divide-by-two approach.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2207
         */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2208
        static class RandomSplitsSpliterator extends RandomSpliterator implements Spliterator<SplittableGenerator> {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2209
            final SplittableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2210
            final SplittableGenerator constructingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2211
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2212
            RandomSplitsSpliterator(SplittableGenerator generatingGenerator,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2213
				    long index, long fence,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2214
				    SplittableGenerator constructingGenerator) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2215
                super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2216
                this.generatingGenerator = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2217
                this.constructingGenerator = constructingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2218
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2219
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2220
            public Spliterator<SplittableGenerator> trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2221
                long i = index, m = (i + fence) >>> 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2222
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2223
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2224
                return new RandomSplitsSpliterator(generatingGenerator.split(), i, m, constructingGenerator);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2225
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2226
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2227
            public boolean tryAdvance(Consumer<? super SplittableGenerator> consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2228
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2229
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2230
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2231
                    consumer.accept(constructingGenerator.split(generatingGenerator));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2232
                    index = i + 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2233
                    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2234
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2235
                else return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2236
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2237
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2238
            public void forEachRemaining(Consumer<? super SplittableGenerator> consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2239
                if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2240
                long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2241
                if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2242
                    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2243
                    SplittableGenerator c = constructingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2244
                    SplittableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2245
                    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2246
                        consumer.accept(c.split(r));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2247
                    } while (++i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2248
                }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2249
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2250
        }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2251
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2252
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2253
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2254
    /**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2255
     * This class provides much of the implementation of the {@link SplittableGenerator} interface, to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2256
     * minimize the effort required to implement this interface.  It is similar to the class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2257
     * {@link AbstractSplittableGenerator} but makes use of the brine technique for ensuring that
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2258
     * distinct generators created by a single call to a {@code splits} method have distinct state cycles.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2259
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2260
     * To implement a pseudorandom number generator, the programmer needs only to extend this class and
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2261
     * provide implementations for the methods {@code nextInt()}, {@code nextLong()}, {@code period()},
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2262
     * and {@code split(SplittableGenerator, long)}.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2263
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2264
     * The programmer should generally provide at least three constructors: one that takes no arguments,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2265
     * one that accepts a {@code long} seed value, and one that accepts an array of seed {@code byte}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2266
     * values. This class provides a public {@code initialSeed()} method that may be useful in
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2267
     * initializing some static state from which to derive defaults seeds for use by the no-argument
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2268
     * constructor.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2269
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2270
     * For the stream methods (such as {@code ints()} and {@code splits()}), this class provides
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2271
     * {@link Spliterator}-based implementations that allow parallel execution when appropriate.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2272
     * <p>
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2273
     * The documentation for each non-abstract method in this class describes its implementation in
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2274
     * detail. Each of these methods may be overridden if the pseudorandom number generator being
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2275
     * implemented admits a more efficient implementation.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2276
     *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2277
     * @since 14
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2278
     */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2279
    public abstract static class AbstractSplittableWithBrineGenerator
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2280
	extends AbstractSplittableGenerator {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2281
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2282
	/*
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2283
	 * Implementation Overview.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2284
	 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2285
         * This class provides most of the "user API" methods needed to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2286
         * satisfy the interface SplittableGenerator.  Most of these methods
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2287
         * are in turn inherited from AbstractSplittableGenerator and the non-public class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2288
         * AbstractSpliteratorGenerator; this class provides four versions of the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2289
         * splits method and defines the spliterators necessary to support
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2290
         * them.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2291
	 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2292
	 * File organization: First the non-public methods needed by the class
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2293
	 * AbstractSplittableWithBrineGenerator, then the main public methods,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2294
	 * followed by some custom spliterator classes needed for stream methods.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2295
	 */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2296
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2297
	// The salt consists groups of bits each SALT_SHIFT in size, starting from
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2298
	// the left-hand (high-order) end of the word.  We can regard them as
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2299
	// digits base (1 << SALT_SHIFT).  If SALT_SHIFT does not divide 64
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2300
	// evenly, then any leftover bits at the low end of the word are zero.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2301
	// The lowest digit of the salt is set to the largest possible digit
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2302
	// (all 1-bits, or ((1 << SALT_SHIFT) - 1)); all other digits are set
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2303
	// to a randomly chosen value less than that largest possible digit.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2304
	// The salt may be shifted left by SALT_SHIFT any number of times.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2305
	// If any salt remains in the word, its right-hand end can be identified
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2306
	// by searching from left to right for an occurrence of a digit that is
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2307
	// all 1-bits (not that we ever do that; this is simply a proof that one
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2308
	// can identify the boundary between the salt and the index if any salt
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2309
	// remains in the word).  The idea is that before computing the bitwise OR
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2310
	// of an index and the salt, one can first check to see whether the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2311
	// bitwise AND is nonzero; if so, one can shift the salt left by
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2312
	// SALT_SHIFT and try again.  In this way, when the bitwise OR is
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2313
	// computed, if the salt is nonzero then its rightmost 1-bit is to the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2314
	// left of the leftmost 1-bit of the index.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2315
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2316
	// We need 2 <= SALT_SHIFT <= 63 (3 through 8 are good values; 4 is probably best)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2317
	static final int SALT_SHIFT = 4;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2318
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2319
	// Methods required by class AbstractSpliteratorGenerator (override)
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2320
	Spliterator<SplittableGenerator> makeSplitsSpliterator(long index, long fence, SplittableGenerator source) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2321
	    // This little algorithm to generate a new salt value is carefully
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2322
	    // designed to work even if SALT_SHIFT does not evenly divide 64
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2323
	    // (the number of bits in a long value).
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2324
	    long bits = nextLong();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2325
	    long multiplier = (1 << SALT_SHIFT) - 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2326
	    long salt = multiplier << (64 - SALT_SHIFT);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2327
	    while ((salt & multiplier) != 0) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2328
		long digit = Math.multiplyHigh(bits, multiplier);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2329
		salt = (salt >>> SALT_SHIFT) | (digit << (64 - SALT_SHIFT));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2330
		bits *= multiplier;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2331
	    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2332
	    // This is the point at which newly generated salt gets injected into
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2333
	    // the root of a newly created brine-generating splits-spliterator.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2334
	    return new RandomSplitsSpliteratorWithSalt(source, index, fence, this, salt);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2335
	}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2336
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2337
	/* ---------------- public methods ---------------- */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2338
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2339
	// Stream methods for splitting
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2340
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2341
	/**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2342
	 * Constructs and returns a new instance of {@code AbstractSplittableWithBrineGenerator}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2343
	 * that shares no mutable state with this instance. However, with very high
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2344
	 * probability, the set of values collectively generated by the two objects
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2345
	 * should have the same statistical properties as if the same quantity of
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2346
	 * values were generated by a single thread using a single may be
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2347
	 * {@code AbstractSplittableWithBrineGenerator} object. Either or both of the two objects
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2348
	 * further split using the {@code split()} method, and the same expected
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2349
	 * statistical properties apply to the entire set of generators constructed
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2350
	 * by such recursive splitting.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2351
	 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2352
	 * @param brine a long value, of which the low 63 bits provide a unique id
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2353
	 * among calls to this method for constructing a single series of Generator objects.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2354
	 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2355
	 * @return the new {@code AbstractSplittableWithBrineGenerator} instance
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2356
	 */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2357
	public SplittableGenerator split(long brine) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2358
	    return this.split(this, brine);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2359
	}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2360
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2361
	/**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2362
	 * Constructs and returns a new instance of {@code L64X128MixRandom}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2363
	 * that shares no mutable state with this instance.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2364
	 * However, with very high probability, the set of values collectively
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2365
	 * generated by the two objects has the same statistical properties as if
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2366
	 * same the quantity of values were generated by a single thread using
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2367
	 * a single {@code L64X128MixRandom} object.  Either or both of the two
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2368
	 * objects may be further split using the {@code split} method,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2369
	 * and the same expected statistical properties apply to the
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2370
	 * entire set of generators constructed by such recursive splitting.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2371
	 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2372
	 * @param source a {@code SplittableGenerator} instance to be used instead
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2373
	 *               of this one as a source of pseudorandom bits used to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2374
	 *               initialize the state of the new ones.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2375
	 * @return a new instance of {@code L64X128MixRandom}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2376
	 */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2377
	public SplittableGenerator split(SplittableGenerator source) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2378
	    // It's a one-off: supply randomly chosen brine
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2379
	    return this.split(source, source.nextLong());
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2380
	}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2381
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2382
	/**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2383
	 * Constructs and returns a new instance of {@code AbstractSplittableWithBrineGenerator}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2384
	 * that shares no mutable state with this instance. However, with very high
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2385
	 * probability, the set of values collectively generated by the two objects
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2386
	 * should have the same statistical properties as if the same quantity of
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2387
	 * values were generated by a single thread using a single may be
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2388
	 * {@code AbstractSplittableWithBrineGenerator} object. Either or both of the two objects
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2389
	 * further split using the {@code split()} method, and the same expected
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2390
	 * statistical properties apply to the entire set of generators constructed
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2391
	 * by such recursive splitting.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2392
	 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2393
	 * @param source a {@code SplittableGenerator} instance to be used instead
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2394
	 *               of this one as a source of pseudorandom bits used to
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2395
	 *               initialize the state of the new ones.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2396
	 * @param brine a long value, of which the low 63 bits provide a unique id
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2397
	 *              among calls to this method for constructing a single series of
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2398
	 *              {@code RandomGenerator} objects.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2399
	 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2400
	 * @return the new {@code AbstractSplittableWithBrineGenerator} instance
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2401
	 */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2402
	public abstract SplittableGenerator split(SplittableGenerator source, long brine);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2403
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2404
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2405
	/* ---------------- spliterator ---------------- */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2406
	/**
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2407
	 * Alternate spliterator for stream of generators of type SplittableGenerator.  We multiplex
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2408
	 * the two versions into one class by treating "infinite" as equivalent to Long.MAX_VALUE.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2409
	 * For splits, it uses the standard divide-by-two approach.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2410
	 *
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2411
	 * This differs from {@code SplittableGenerator.RandomSplitsSpliterator} in that it provides
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2412
	 * a brine argument (a mixture of salt and an index) when calling the {@code split} method.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2413
	 */
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2414
	static class RandomSplitsSpliteratorWithSalt
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2415
	    extends RandomSpliterator implements Spliterator<SplittableGenerator> {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2416
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2417
	    final SplittableGenerator generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2418
	    final AbstractSplittableWithBrineGenerator constructingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2419
	    long salt;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2420
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2421
	    // Important invariant: 0 <= index <= fence
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2422
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2423
	    // Important invariant: if salt and index are both nonzero,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2424
	    // the rightmost 1-bit of salt is to the left of the leftmost 1-bit of index.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2425
	    // If necessary, the salt can be leftshifted by SALT_SHIFT as many times as
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2426
	    // necessary to maintain the invariant.
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2427
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2428
	    RandomSplitsSpliteratorWithSalt(SplittableGenerator generatingGenerator, long index, long fence,
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2429
					    AbstractSplittableWithBrineGenerator constructingGenerator, long salt) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2430
		super(index, fence);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2431
		this.generatingGenerator = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2432
		this.constructingGenerator = constructingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2433
		while ((salt != 0) && (Long.compareUnsigned(salt & -salt, index) <= 0)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2434
		    salt = salt << SALT_SHIFT;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2435
		}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2436
		this.salt = salt;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2437
	    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2438
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2439
            public Spliterator<SplittableGenerator> trySplit() {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2440
                long i = index, m = (i + fence) >>> 1;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2441
                if (m <= i) return null;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2442
		RandomSplitsSpliteratorWithSalt result =
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2443
		    new RandomSplitsSpliteratorWithSalt(generatingGenerator.split(), i, m, constructingGenerator, salt);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2444
                index = m;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2445
		while ((salt != 0) && (Long.compareUnsigned(salt & -salt, index) <= 0)) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2446
		    salt = salt << SALT_SHIFT;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2447
		}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2448
		return result;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2449
            }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2450
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2451
	    public boolean tryAdvance(Consumer<? super SplittableGenerator> consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2452
		if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2453
		long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2454
		if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2455
		    consumer.accept(constructingGenerator.split(generatingGenerator, salt | i));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2456
		    ++i;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2457
		    index = i;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2458
		    if ((i & salt) != 0) salt <<= SALT_SHIFT;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2459
		    return true;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2460
		}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2461
		return false;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2462
	    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2463
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2464
	    public void forEachRemaining(Consumer<? super SplittableGenerator> consumer) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2465
		if (consumer == null) throw new NullPointerException();
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2466
		long i = index, f = fence;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2467
		if (i < f) {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2468
		    index = f;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2469
		    AbstractSplittableWithBrineGenerator c = constructingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2470
		    SplittableGenerator r = generatingGenerator;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2471
		    do {
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2472
			consumer.accept(c.split(r, salt | i));
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2473
			++i;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2474
			if ((i & salt) != 0) salt <<= SALT_SHIFT;
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2475
		    } while (i < f);
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2476
		}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2477
	    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2478
	}
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2479
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2480
    }
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2481
da026c172c1e add missing files
jlaskey
parents:
diff changeset
  2482
}