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