This commit is contained in:
457
L2J_Mobius_Test/java/com/l2jmobius/util/Rnd.java
Normal file
457
L2J_Mobius_Test/java/com/l2jmobius/util/Rnd.java
Normal file
@@ -0,0 +1,457 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* @author Forsaiken
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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.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 static 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.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
|
||||
* Each thread has it`s own random instance.<br>
|
||||
* Provides best parallel access speed.
|
||||
* @see com.l2jmobius.util.Rnd.ThreadLocalRandom
|
||||
*/
|
||||
UNSECURE_THREAD_LOCAL,
|
||||
|
||||
/**
|
||||
* Like {@link com.l2jmobius.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
|
||||
* Provides much faster parallel access speed.
|
||||
* @see com.l2jmobius.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<Seed>()
|
||||
{
|
||||
@Override
|
||||
public final Seed initialValue()
|
||||
{
|
||||
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ThreadLocalRandom(long seed)
|
||||
{
|
||||
_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 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.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()
|
||||
*/
|
||||
public static boolean nextBoolean()
|
||||
{
|
||||
return rnd.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 static void nextBytes(byte[] array)
|
||||
{
|
||||
rnd.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 static double nextDouble()
|
||||
{
|
||||
return rnd.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 static float nextFloat()
|
||||
{
|
||||
return rnd.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 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()
|
||||
*/
|
||||
public static int nextInt()
|
||||
{
|
||||
return rnd.nextInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param n
|
||||
* @return
|
||||
* @see com.l2jmobius.util.Rnd#get(int n)
|
||||
*/
|
||||
public static int nextInt(int n)
|
||||
{
|
||||
return get(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 static long nextLong()
|
||||
{
|
||||
return rnd.nextLong();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user