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}