View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.rng;
18  
19  import java.util.stream.DoubleStream;
20  import java.util.stream.IntStream;
21  import java.util.stream.LongStream;
22  
23  /**
24   * Applies to generators of random number sequences that follow a uniform
25   * distribution.
26   *
27   * @since 1.0
28   */
29  public interface UniformRandomProvider {
30      /**
31       * Generates {@code byte} values and places them into a user-supplied array.
32       *
33       * <p>The number of random bytes produced is equal to the length of the byte array.
34       *
35       * @param bytes Byte array in which to put the random bytes.
36       * Cannot be {@code null}.
37       */
38      default void nextBytes(byte[] bytes) {
39          UniformRandomProviderSupport.nextBytes(this, bytes, 0, bytes.length);
40      }
41  
42      /**
43       * Generates {@code byte} values and places them into a user-supplied array.
44       *
45       * <p>The array is filled with bytes extracted from random integers.
46       * This implies that the number of random bytes generated may be larger than
47       * the length of the byte array.
48       *
49       * @param bytes Array in which to put the generated bytes.
50       * Cannot be {@code null}.
51       * @param start Index at which to start inserting the generated bytes.
52       * @param len Number of bytes to insert.
53       * @throws IndexOutOfBoundsException if {@code start < 0} or
54       * {@code start >= bytes.length}.
55       * @throws IndexOutOfBoundsException if {@code len < 0} or
56       * {@code len > bytes.length - start}.
57       */
58      default void nextBytes(byte[] bytes, int start, int len) {
59          UniformRandomProviderSupport.validateFromIndexSize(start, len, bytes.length);
60          UniformRandomProviderSupport.nextBytes(this, bytes, start, len);
61      }
62  
63      /**
64       * Generates an {@code int} value.
65       *
66       * @return the next random value.
67       */
68      default int nextInt() {
69          return (int) (nextLong() >>> 32);
70      }
71  
72      /**
73       * Generates an {@code int} value between 0 (inclusive) and the
74       * specified value (exclusive).
75       *
76       * @param n Bound on the random number to be returned.  Must be positive.
77       * @return a random {@code int} value between 0 (inclusive) and {@code n}
78       * (exclusive).
79       * @throws IllegalArgumentException if {@code n} is not above zero.
80       */
81      default int nextInt(int n) {
82          UniformRandomProviderSupport.validateUpperBound(n);
83          return UniformRandomProviderSupport.nextInt(this, n);
84      }
85  
86      /**
87       * Generates an {@code int} value between the specified {@code origin} (inclusive) and
88       * the specified {@code bound} (exclusive).
89       *
90       * @param origin Lower bound on the random number to be returned.
91       * @param bound Upper bound (exclusive) on the random number to be returned.
92       * @return a random {@code int} value between {@code origin} (inclusive) and
93       * {@code bound} (exclusive).
94       * @throws IllegalArgumentException if {@code origin} is greater than or equal to
95       * {@code bound}.
96       * @since 1.5
97       */
98      default int nextInt(int origin, int bound) {
99          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 }