001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.rng;
018
019import java.util.stream.DoubleStream;
020import java.util.stream.IntStream;
021import java.util.stream.LongStream;
022
023/**
024 * Applies to generators of random number sequences that follow a uniform
025 * distribution.
026 *
027 * @since 1.0
028 */
029public interface UniformRandomProvider {
030    /**
031     * Generates {@code byte} values and places them into a user-supplied array.
032     *
033     * <p>The number of random bytes produced is equal to the length of the byte array.
034     *
035     * @param bytes Byte array in which to put the random bytes.
036     * Cannot be {@code null}.
037     */
038    default void nextBytes(byte[] bytes) {
039        UniformRandomProviderSupport.nextBytes(this, bytes, 0, bytes.length);
040    }
041
042    /**
043     * Generates {@code byte} values and places them into a user-supplied array.
044     *
045     * <p>The array is filled with bytes extracted from random integers.
046     * This implies that the number of random bytes generated may be larger than
047     * the length of the byte array.
048     *
049     * @param bytes Array in which to put the generated bytes.
050     * Cannot be {@code null}.
051     * @param start Index at which to start inserting the generated bytes.
052     * @param len Number of bytes to insert.
053     * @throws IndexOutOfBoundsException if {@code start < 0} or
054     * {@code start >= bytes.length}.
055     * @throws IndexOutOfBoundsException if {@code len < 0} or
056     * {@code len > bytes.length - start}.
057     */
058    default void nextBytes(byte[] bytes, int start, int len) {
059        UniformRandomProviderSupport.validateFromIndexSize(start, len, bytes.length);
060        UniformRandomProviderSupport.nextBytes(this, bytes, start, len);
061    }
062
063    /**
064     * Generates an {@code int} value.
065     *
066     * @return the next random value.
067     */
068    default int nextInt() {
069        return (int) (nextLong() >>> 32);
070    }
071
072    /**
073     * Generates an {@code int} value between 0 (inclusive) and the
074     * specified value (exclusive).
075     *
076     * @param n Bound on the random number to be returned.  Must be positive.
077     * @return a random {@code int} value between 0 (inclusive) and {@code n}
078     * (exclusive).
079     * @throws IllegalArgumentException if {@code n} is not above zero.
080     */
081    default int nextInt(int n) {
082        UniformRandomProviderSupport.validateUpperBound(n);
083        return UniformRandomProviderSupport.nextInt(this, n);
084    }
085
086    /**
087     * Generates an {@code int} value between the specified {@code origin} (inclusive) and
088     * the specified {@code bound} (exclusive).
089     *
090     * @param origin Lower bound on the random number to be returned.
091     * @param bound Upper bound (exclusive) on the random number to be returned.
092     * @return a random {@code int} value between {@code origin} (inclusive) and
093     * {@code bound} (exclusive).
094     * @throws IllegalArgumentException if {@code origin} is greater than or equal to
095     * {@code bound}.
096     * @since 1.5
097     */
098    default int nextInt(int origin, int bound) {
099        UniformRandomProviderSupport.validateRange(origin, bound);
100        return UniformRandomProviderSupport.nextInt(this, origin, bound);
101    }
102
103    /**
104     * Generates a {@code long} value.
105     *
106     * @return the next random value.
107     */
108    long nextLong();
109
110    /**
111     * Generates a {@code long} value between 0 (inclusive) and the specified
112     * value (exclusive).
113     *
114     * @param n Bound on the random number to be returned.  Must be positive.
115     * @return a random {@code long} value between 0 (inclusive) and {@code n}
116     * (exclusive).
117     * @throws IllegalArgumentException if {@code n} is not greater than 0.
118     */
119    default long nextLong(long n) {
120        UniformRandomProviderSupport.validateUpperBound(n);
121        return UniformRandomProviderSupport.nextLong(this, n);
122    }
123
124    /**
125     * Generates a {@code long} value between the specified {@code origin} (inclusive) and
126     * the specified {@code bound} (exclusive).
127     *
128     * @param origin Lower bound on the random number to be returned.
129     * @param bound Upper bound (exclusive) on the random number to be returned.
130     * @return a random {@code long} value between {@code origin} (inclusive) and
131     * {@code bound} (exclusive).
132     * @throws IllegalArgumentException if {@code origin} is greater than or equal to
133     * {@code bound}.
134     * @since 1.5
135     */
136    default long nextLong(long origin, long bound) {
137        UniformRandomProviderSupport.validateRange(origin, bound);
138        return UniformRandomProviderSupport.nextLong(this, origin, bound);
139    }
140
141    /**
142     * Generates a {@code boolean} value.
143     *
144     * @return the next random value.
145     */
146    default boolean nextBoolean() {
147        return nextInt() < 0;
148    }
149
150    /**
151     * Generates a {@code float} value between 0 (inclusive) and 1 (exclusive).
152     *
153     * @return the next random value between 0 (inclusive) and 1 (exclusive).
154     */
155    default float nextFloat() {
156        return (nextInt() >>> 8) * 0x1.0p-24f;
157    }
158
159    /**
160     * Generates a {@code float} value between 0 (inclusive) and the
161     * specified {@code bound} (exclusive).
162     *
163     * @param bound Upper bound (exclusive) on the random number to be returned.
164     * @return a random {@code float} value between 0 (inclusive) and {@code bound}
165     * (exclusive).
166     * @throws IllegalArgumentException if {@code bound} is not both finite and greater than 0.
167     * @since 1.5
168     */
169    default float nextFloat(float bound) {
170        UniformRandomProviderSupport.validateUpperBound(bound);
171        return UniformRandomProviderSupport.nextFloat(this, bound);
172    }
173
174    /**
175     * Generates a {@code float} value between the specified {@code origin} (inclusive)
176     * and the specified {@code bound} (exclusive).
177     *
178     * @param origin Lower bound on the random number to be returned.
179     * @param bound Upper bound (exclusive) on the random number to be returned.
180     * @return a random {@code float} value between {@code origin} (inclusive) and
181     * {@code bound} (exclusive).
182     * @throws IllegalArgumentException if {@code origin} is not finite, or {@code bound}
183     * is not finite, or {@code origin} is greater than or equal to {@code bound}.
184     * @since 1.5
185     */
186    default float nextFloat(float origin, float bound) {
187        UniformRandomProviderSupport.validateRange(origin, bound);
188        return UniformRandomProviderSupport.nextFloat(this, origin, bound);
189    }
190
191    /**
192     * Generates a {@code double} value between 0 (inclusive) and 1 (exclusive).
193     *
194     * @return the next random value between 0 (inclusive) and 1 (exclusive).
195     */
196    default double nextDouble() {
197        return (nextLong() >>> 11) * 0x1.0p-53;
198    }
199
200    /**
201     * Generates a {@code double} value between 0 (inclusive) and the
202     * specified {@code bound} (exclusive).
203     *
204     * @param bound Upper bound (exclusive) on the random number to be returned.
205     * @return a random {@code double} value between 0 (inclusive) and {@code bound}
206     * (exclusive).
207     * @throws IllegalArgumentException if {@code bound} is not both finite and greater than 0.
208     * @since 1.5
209     */
210    default double nextDouble(double bound) {
211        UniformRandomProviderSupport.validateUpperBound(bound);
212        return UniformRandomProviderSupport.nextDouble(this, bound);
213    }
214
215    /**
216     * Generates a {@code double} value between the specified {@code origin} (inclusive)
217     * and the specified {@code bound} (exclusive).
218     *
219     * @param origin Lower bound on the random number to be returned.
220     * @param bound Upper bound (exclusive) on the random number to be returned.
221     * @return a random {@code double} value between {@code origin} (inclusive) and
222     * {@code bound} (exclusive).
223     * @throws IllegalArgumentException if {@code origin} is not finite, or {@code bound}
224     * is not finite, or {@code origin} is greater than or equal to {@code bound}.
225     * @since 1.5
226     */
227    default double nextDouble(double origin, double bound) {
228        UniformRandomProviderSupport.validateRange(origin, bound);
229        return UniformRandomProviderSupport.nextDouble(this, origin, bound);
230    }
231
232    /**
233     * Returns an effectively unlimited stream of {@code int} values.
234     *
235     * @return a stream of random {@code int} values.
236     * @since 1.5
237     */
238    default IntStream ints() {
239        return IntStream.generate(this::nextInt).sequential();
240    }
241
242    /**
243     * Returns an effectively unlimited stream of {@code int} values between the specified
244     * {@code origin} (inclusive) and the specified {@code bound} (exclusive).
245     *
246     * @param origin Lower bound on the random number to be returned.
247     * @param bound Upper bound (exclusive) on the random number to be returned.
248     * @return a stream of random values between the specified {@code origin} (inclusive)
249     * and the specified {@code bound} (exclusive).
250     * @throws IllegalArgumentException if {@code origin} is greater than or equal to
251     * {@code bound}.
252     * @since 1.5
253     */
254    default IntStream ints(int origin, int bound) {
255        UniformRandomProviderSupport.validateRange(origin, bound);
256        return IntStream.generate(() -> nextInt(origin, bound)).sequential();
257    }
258
259    /**
260     * Returns a stream producing the given {@code streamSize} number of {@code int}
261     * values.
262     *
263     * @param streamSize Number of values to generate.
264     * @return a stream of random {@code int} values; the stream is limited to the given
265     * {@code streamSize}.
266     * @throws IllegalArgumentException if {@code streamSize} is negative.
267     * @since 1.5
268     */
269    default IntStream ints(long streamSize) {
270        UniformRandomProviderSupport.validateStreamSize(streamSize);
271        return ints().limit(streamSize);
272    }
273
274    /**
275     * Returns a stream producing the given {@code streamSize} number of {@code int}
276     * values between the specified {@code origin} (inclusive) and the specified
277     * {@code bound} (exclusive).
278     *
279     * @param streamSize Number of values to generate.
280     * @param origin Lower bound on the random number to be returned.
281     * @param bound Upper bound (exclusive) on the random number to be returned.
282     * @return a stream of random values between the specified {@code origin} (inclusive)
283     * and the specified {@code bound} (exclusive); the stream is limited to the given
284     * {@code streamSize}.
285     * @throws IllegalArgumentException if {@code streamSize} is negative, or if
286     * {@code origin} is greater than or equal to {@code bound}.
287     * @since 1.5
288     */
289    default IntStream ints(long streamSize, int origin, int bound) {
290        UniformRandomProviderSupport.validateStreamSize(streamSize);
291        UniformRandomProviderSupport.validateRange(origin, bound);
292        return ints(origin, bound).limit(streamSize);
293    }
294
295    /**
296     * Returns an effectively unlimited stream of {@code long} values.
297     *
298     * @return a stream of random {@code long} values.
299     * @since 1.5
300     */
301    default LongStream longs() {
302        return LongStream.generate(this::nextLong).sequential();
303    }
304
305    /**
306     * Returns an effectively unlimited stream of {@code long} values between the
307     * specified {@code origin} (inclusive) and the specified {@code bound} (exclusive).
308     *
309     * @param origin Lower bound on the random number to be returned.
310     * @param bound Upper bound (exclusive) on the random number to be returned.
311     * @return a stream of random values between the specified {@code origin} (inclusive)
312     * and the specified {@code bound} (exclusive).
313     * @throws IllegalArgumentException if {@code origin} is greater than or equal to
314     * {@code bound}.
315     * @since 1.5
316     */
317    default LongStream longs(long origin, long bound) {
318        UniformRandomProviderSupport.validateRange(origin, bound);
319        return LongStream.generate(() -> nextLong(origin, bound)).sequential();
320    }
321
322    /**
323     * Returns a stream producing the given {@code streamSize} number of {@code long}
324     * values.
325     *
326     * @param streamSize Number of values to generate.
327     * @return a stream of random {@code long} values; the stream is limited to the given
328     * {@code streamSize}.
329     * @throws IllegalArgumentException if {@code streamSize} is negative.
330     * @since 1.5
331     */
332    default LongStream longs(long streamSize) {
333        UniformRandomProviderSupport.validateStreamSize(streamSize);
334        return longs().limit(streamSize);
335    }
336
337    /**
338     * Returns a stream producing the given {@code streamSize} number of {@code long}
339     * values between the specified {@code origin} (inclusive) and the specified
340     * {@code bound} (exclusive).
341     *
342     * @param streamSize Number of values to generate.
343     * @param origin Lower bound on the random number to be returned.
344     * @param bound Upper bound (exclusive) on the random number to be returned.
345     * @return a stream of random values between the specified {@code origin} (inclusive)
346     * and the specified {@code bound} (exclusive); the stream is limited to the given
347     * {@code streamSize}.
348     * @throws IllegalArgumentException if {@code streamSize} is negative, or if
349     * {@code origin} is greater than or equal to {@code bound}.
350     * @since 1.5
351     */
352    default LongStream longs(long streamSize, long origin, long bound) {
353        UniformRandomProviderSupport.validateStreamSize(streamSize);
354        UniformRandomProviderSupport.validateRange(origin, bound);
355        return longs(origin, bound).limit(streamSize);
356    }
357
358    /**
359     * Returns an effectively unlimited stream of {@code double} values between 0
360     * (inclusive) and 1 (exclusive).
361     *
362     * @return a stream of random values between 0 (inclusive) and 1 (exclusive).
363     * @since 1.5
364     */
365    default DoubleStream doubles() {
366        return DoubleStream.generate(this::nextDouble).sequential();
367    }
368
369    /**
370     * Returns an effectively unlimited stream of {@code double} values between the
371     * specified {@code origin} (inclusive) and the specified {@code bound} (exclusive).
372     *
373     * @param origin Lower bound on the random number to be returned.
374     * @param bound Upper bound (exclusive) on the random number to be returned.
375     * @return a stream of random values between the specified {@code origin} (inclusive)
376     * and the specified {@code bound} (exclusive).
377     * @throws IllegalArgumentException if {@code origin} is not finite, or {@code bound}
378     * is not finite, or {@code origin} is greater than or equal to {@code bound}.
379     * @since 1.5
380     */
381    default DoubleStream doubles(double origin, double bound) {
382        UniformRandomProviderSupport.validateRange(origin, bound);
383        return DoubleStream.generate(() -> nextDouble(origin, bound)).sequential();
384    }
385
386    /**
387     * Returns a stream producing the given {@code streamSize} number of {@code double}
388     * values between 0 (inclusive) and 1 (exclusive).
389     *
390     * @param streamSize Number of values to generate.
391     * @return a stream of random values between 0 (inclusive) and 1 (exclusive);
392     * the stream is limited to the given {@code streamSize}.
393     * @throws IllegalArgumentException if {@code streamSize} is negative.
394     * @since 1.5
395     */
396    default DoubleStream doubles(long streamSize) {
397        UniformRandomProviderSupport.validateStreamSize(streamSize);
398        return doubles().limit(streamSize);
399    }
400
401    /**
402     * Returns a stream producing the given {@code streamSize} number of {@code double}
403     * values between the specified {@code origin} (inclusive) and the specified
404     * {@code bound} (exclusive).
405     *
406     * @param streamSize Number of values to generate.
407     * @param origin Lower bound on the random number to be returned.
408     * @param bound Upper bound (exclusive) on the random number to be returned.
409     * @return a stream of random values between the specified {@code origin} (inclusive)
410     * and the specified {@code bound} (exclusive); the stream is limited to the given
411     * {@code streamSize}.
412     * @throws IllegalArgumentException if {@code streamSize} is negative, or if
413     * {@code origin} is not finite, or {@code bound} is not finite, or {@code origin} is
414     * greater than or equal to {@code bound}.
415     * @since 1.5
416     */
417    default DoubleStream doubles(long streamSize, double origin, double bound) {
418        UniformRandomProviderSupport.validateStreamSize(streamSize);
419        UniformRandomProviderSupport.validateRange(origin, bound);
420        return doubles(origin, bound).limit(streamSize);
421    }
422}