New Rnd class.

This commit is contained in:
MobiusDev 2018-09-15 15:26:34 +00:00
parent 850c075c0e
commit f3907293c8
12 changed files with 882 additions and 4660 deletions

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,464 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.List;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
public static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
*/
UNSECURE_THREAD_LOCAL,
/**
* Provides much faster parallel access speed.
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<Seed>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<Random>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
/**
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
_seedLocal = new ThreadLocal<Seed>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static final Random directRandom()
{
return rnd.directRandom();
return RANDOM.get().nextBoolean();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static final double get()
public static void nextBytes(byte[] bytes)
{
return rnd.nextDouble();
RANDOM.get().nextBytes(bytes);
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static final int get(int n)
public static int get(int bound)
{
return rnd.get(n);
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static final int get(int min, int max)
public static int get(int origin, int bound)
{
return rnd.get(min, max);
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
* @return a random int value.
*/
public static final long get(long min, long max)
public static int nextInt()
{
return rnd.get(min, max);
}
public static final RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
return RANDOM.get().nextInt();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static final boolean nextBoolean()
public static long get(long bound)
{
return rnd.nextBoolean();
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static final void nextBytes(byte[] array)
public static long get(long origin, long bound)
{
rnd.nextBytes(array);
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @return a random long value.
*/
public static final double nextDouble()
public static long nextLong()
{
return rnd.nextDouble();
return RANDOM.get().nextLong();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static final float nextFloat()
public static double get(double bound)
{
return rnd.nextFloat();
return RANDOM.get().nextDouble() * bound;
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static final double nextGaussian()
public static double get(double origin, double bound)
{
return rnd.nextGaussian();
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static final int nextInt()
public static double nextDouble()
{
return rnd.nextInt();
}
public static final int nextInt(int n)
{
return get(n);
return RANDOM.get().nextDouble();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static final long nextLong()
public static double nextGaussian()
{
return rnd.nextLong();
}
/**
* Returns a randomly selected element taken from the given list.
* @param <T> type of list elements.
* @param list a list.
* @return a randomly selected element.
*/
public static final <T> T get(List<T> list)
{
if ((list == null) || (list.size() == 0))
{
return null;
}
return list.get(get(list.size()));
}
/**
* Returns a randomly selected element taken from the given array.
* @param <T> type of array elements.
* @param array an array.
* @return a randomly selected element.
*/
public static final <T> T get(T[] array)
{
if ((array == null) || (array.length == 0))
{
return null;
}
return array[get(array.length)];
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}

View File

@ -16,442 +16,129 @@
*/
package com.l2jmobius.commons.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
* @author Mobius
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
* Thread-specific random number generator.<br>
* Each is seeded with the thread ID, so the sequence of random numbers are unique between threads.
*/
public static final class NonAtomicRandom extends Random
{
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(long seed)
{
setSeed(seed);
}
@Override
public final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
protected static final class RandomContainer
{
private final Random _random;
protected RandomContainer(Random random)
{
_random = random;
}
public final Random directRandom()
{
return _random;
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(int n)
{
return (int) (_random.nextDouble() * n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public final int get(int min, int max)
{
return min + (int) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public final long get(long min, long max)
{
return min + (long) (_random.nextDouble() * ((max - min) + 1));
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
*/
public final boolean nextBoolean()
{
return _random.nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
*/
public final void nextBytes(byte[] array)
{
_random.nextBytes(array);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
*/
public final double nextDouble()
{
return _random.nextDouble();
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
*/
public final float nextFloat()
{
return _random.nextFloat();
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public final double nextGaussian()
{
return _random.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
*/
public final int nextInt()
{
return _random.nextInt();
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
*/
public final long nextLong()
{
return _random.nextLong();
}
}
/**
* @author Forsaiken
*/
public enum RandomType
{
/**
* For best random quality.
* @see java.security.SecureRandom
*/
SECURE,
/**
* For average random quality.
* @see java.util.Random
*/
UNSECURE_ATOMIC,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.commons.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.commons.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(long seed)
{
setSeed(seed);
}
final int next(int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private final ThreadLocal<Seed> _seedLocal;
public ThreadLocalRandom()
{
_seedLocal = new ThreadLocal<>()
private static ThreadLocal<Random> RANDOM = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
protected Random initialValue()
{
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
return new Random(System.nanoTime() + Thread.currentThread().getId());
}
};
}
public ThreadLocalRandom(long seed)
{
_seedLocal = new ThreadLocal<>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static Random directRandom()
{
return rnd.directRandom();
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see com.l2jmobius.commons.util.Rnd#nextDouble()
*/
public static double get()
{
return rnd.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public static int get(int n)
{
return rnd.get(n);
}
/**
* Gets a random integer number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random integer number from min to max
*/
public static int get(int min, int max)
{
return rnd.get(min, max);
}
/**
* Gets a random long number from min(inclusive) to max(inclusive)
* @param min The minimum value
* @param max The maximum value
* @return A random long number from min to max
*/
public static long get(long min, long max)
{
return rnd.get(min, max);
}
public static RandomContainer newInstance(RandomType type)
{
switch (type)
{
case UNSECURE_ATOMIC:
{
return new RandomContainer(new Random());
}
case UNSECURE_VOLATILE:
{
return new RandomContainer(new NonAtomicRandom());
}
case UNSECURE_THREAD_LOCAL:
{
return new RandomContainer(new ThreadLocalRandom());
}
case SECURE:
{
return new RandomContainer(new SecureRandom());
}
}
throw new IllegalArgumentException();
}
/**
* Get a random boolean state (true or false)
* @return A random boolean state (true or false)
* @see java.util.Random#nextBoolean()
* @return a random boolean value.
*/
public static boolean nextBoolean()
{
return rnd.nextBoolean();
return RANDOM.get().nextBoolean();
}
/**
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
* @param array The array to be filled with random byte numbers
* @see java.util.Random#nextBytes(byte[] bytes)
* Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array.
* @param bytes the byte array to fill with random bytes.
*/
public static void nextBytes(byte[] array)
public static void nextBytes(byte[] bytes)
{
rnd.nextBytes(array);
RANDOM.get().nextBytes(bytes);
}
/**
* Get a random double number from 0 to 1
* @return A random double number from 0 to 1
* @see java.util.Random#nextDouble()
* @param bound (int)
* @return a random int value between zero (inclusive) and the specified bound (exclusive).
*/
public static double nextDouble()
public static int get(int bound)
{
return rnd.nextDouble();
return (int) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random float number from 0 to 1
* @return A random integer number from 0 to 1
* @see java.util.Random#nextFloat()
* @param origin (int)
* @param bound (int)
* @return a random int value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static float nextFloat()
public static int get(int origin, int bound)
{
return rnd.nextFloat();
return origin + (int) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* Get a random gaussian double number from 0 to 1
* @return A random gaussian double number from 0 to 1
* @see java.util.Random#nextGaussian()
*/
public static double nextGaussian()
{
return rnd.nextGaussian();
}
/**
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
* @see java.util.Random#nextInt()
* @return a random int value.
*/
public static int nextInt()
{
return rnd.nextInt();
return RANDOM.get().nextInt();
}
/**
* @param n
* @return int
* @see com.l2jmobius.commons.util.Rnd#get(int n)
* @param bound (long)
* @return a random long value between zero (inclusive) and the specified bound (exclusive).
*/
public static int nextInt(int n)
public static long get(long bound)
{
return get(n);
return (long) (RANDOM.get().nextDouble() * bound);
}
/**
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
* @see java.util.Random#nextLong()
* @param origin (long)
* @param bound (long)
* @return a random long value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static long get(long origin, long bound)
{
return origin + (long) (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random long value.
*/
public static long nextLong()
{
return rnd.nextLong();
return RANDOM.get().nextLong();
}
/**
* @param bound (double)
* @return a random double value between zero (inclusive) and the specified bound (exclusive).
*/
public static double get(double bound)
{
return RANDOM.get().nextDouble() * bound;
}
/**
* @param origin (double)
* @param bound (double)
* @return a random double value between the specified origin (inclusive) and the specified bound (inclusive).
*/
public static double get(double origin, double bound)
{
return origin + (((bound - origin) + 1) * RANDOM.get().nextDouble());
}
/**
* @return a random double value between zero (inclusive) and one (exclusive).
*/
public static double nextDouble()
{
return RANDOM.get().nextDouble();
}
/**
* @return the next random, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.
*/
public static double nextGaussian()
{
return RANDOM.get().nextGaussian();
}
}