package com.supaham.commons.utils; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Preconditions; import com.google.common.collect.Range; import java.util.Random; import javax.annotation.Nonnull; /** * Utility methods for working with {@link Random} instances. This class contains methods such as * {@link #nextInt(int)}, {@link #nextLong(long)}, and more. * * @since 0.1 */ public class RandomUtils { private static Random random = new Random(); /** * Returns a pseudo-random int between min and max, inclusive. This is equivalent to calling * {@link #nextInt(Random, int, int)} with {@link #getRandom()}. * * @param min min range * @param max max range * * @return random int in the given range. */ public static int nextInt(int min, int max) { return nextInt(random, min, max); } /** * Returns a pseudo-random int between min and max, inclusive. * * @param random random instance to use * @param min min range * @param max max range * * @return random int in the given range. */ public static int nextInt(@Nonnull Random random, int min, int max) { checkNotNull(random, "random cannot be null."); return random.nextInt((max - min) + 1) + min; } /** * Returns a pseudorandom, uniformly distributed int value between the given {@link Range}'s * lower * end point and upper end point. This is equivalent to calling {@link #nextInt(Random, Range)} * using {@link #getRandom()}. * * @param range range to generate int from * * @return a pseudorandom value */ public static int nextInt(Range<Integer> range) { return nextInt(random, range); } /** * Returns a pseudorandom, uniformly distributed int value between the given {@link Range}'s * lower * end point and upper end point. * * @param random random instance to use * @param range range to generate int from * * @return a pseudorandom value */ public static int nextInt(@Nonnull Random random, @Nonnull Range<Integer> range) { checkNotNull(range, "range cannot be null."); return nextInt(random, range.lowerEndpoint(), range.upperEndpoint()); } /** * Returns a pseudo-random double between 0 and {@code max}, inclusive. This is equivalent to * calling {@link #nextDouble(double, double)} with the first double as 0. * * @param max max range * * @return random double in the given range. */ public static double nextDouble(double max) { return nextDouble(0, max); } /** * Returns a pseudo-random double between min and max, inclusive. This is equivalent to calling * {@link #nextDouble(Random, double, double)} with {@link #getRandom()}. * * @param min min range * @param max max range * * @return random double in the given range. */ public static double nextDouble(double min, double max) { return nextDouble(random, min, max); } /** * Returns a pseudo-random double between min and max, inclusive. * * @param random random instance to use * @param min min range * @param max max range * * @return random double in the given range. */ public static double nextDouble(@Nonnull Random random, double min, double max) { Preconditions.checkNotNull(random, "random cannot be null."); return min + (max - min) * random.nextDouble(); } /** * Returns a pseudorandom, uniformly distributed long value between 0 (inclusive) and the * specified value (exclusive), drawn from this random number generator's sequence. * * @param bound maximum long generation boundary * * @return the next pseudorandom, uniformly distributed long value between 0 (inclusive) and n * (exclusive) from this random number generator's sequence * * @see #nextLong(Random, long) */ public static long nextLong(long bound) { return nextLong(0, bound); } /** * Returns a pseudorandom, uniformly distributed long value between 0 (inclusive) and the * specified value (exclusive), drawn from this random number generator's sequence. * * @param random random instance to use * @param bound maximum long generation boundary * * @return the next pseudorandom, uniformly distributed long value between 0 (inclusive) and n * (exclusive) from this random number generator's sequence * * @see #nextLong(Random, long, long) */ public static long nextLong(@Nonnull Random random, long bound) { return nextLong(random, 0, bound); } /** * Returns a pseudorandom, uniformly distributed long value between origin (inclusive) and the * bound (exclusive), drawn from this random number generator's sequence. <p/> <b>Note: This * piece * of code was copied directly from JDK 1.8 with minor visual changes, but same performance.</b> * * @param origin the least value, unless greater than bound * @param bound the upper bound (exclusive), must not equal origin * * @return a pseudorandom value * * @see #nextLong(Random, long, long) */ public static long nextLong(long origin, long bound) { return nextLong(random, origin, bound); } /** * The form of nextLong used by LongStream Spliterators. If origin is greater than bound, acts as * unbounded form of nextLong, else as bounded form. <p/> <b>Note: This piece of code was copied * directly from JDK 1.8 with minor visual changes, but same performance.</b> * * @param random random instance to use * @param origin the least value, unless greater than bound * @param bound the upper bound (exclusive), must not equal origin * * @return a pseudorandom value */ public static long nextLong(@Nonnull Random random, long origin, long bound) { checkNotNull(random, "random cannot be null."); long r = random.nextLong(); if (origin < bound) { long n = bound - origin, m = n - 1; if ((n & m) == 0L) { // power of two r = (r & m) + origin; } else if (n > 0L) { for (long u = r >>> 1; // ensure nonnegative u + m - (r = u % n) < 0L; // rejection check u = random.nextLong() >>> 1) { // retry } r += origin; } else { while (r < origin || r >= bound) { r = random.nextLong(); } } } return r; } public static Random getRandom() { return random; } /* ================================ * >> DELEGATE METHODS * ================================ */ /** * @see Random#nextBytes(byte[]) */ public static void nextBytes(byte[] bytes) { random.nextBytes(bytes); } /** * @see Random#nextInt() */ public static int nextInt() { return random.nextInt(); } /** * @see Random#nextInt(int) */ public static int nextInt(int bound) { return random.nextInt(bound); } /** * @see Random#nextLong() */ public static long nextLong() { return random.nextLong(); } /** * @see Random#nextBoolean() */ public static boolean nextBoolean() { return random.nextBoolean(); } /** * @see Random#nextFloat() */ public static float nextFloat() { return random.nextFloat(); } /** * @see Random#nextDouble() */ public static double nextDouble() { return random.nextDouble(); } /** * @see Random#nextGaussian() */ public static double nextGaussian() { return random.nextGaussian(); } }