/* * Copyright (c) 2006 Thomas Weise * * E-Mail : tweise@gmx.de * Creation Date : 2006-01-18 04:59:11 * Original Filename: org.sfc.math.stochastic.Randomizer.java * Version : 3.0.2 * Last modification: 2006-06-28 * by: Thomas Weise * * License : GNU LESSER GENERAL PUBLIC LICENSE * Version 2.1, February 1999 * You should have received a copy of this license along * with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA or download the license under * http://www.gnu.org/copyleft/lesser.html. * * Warranty : This software is provided "as is" without any * warranty; without even the implied warranty of * merchantability or fitness for a particular purpose. * See the Gnu Lesser General Public License for more * details. */ package org.sfc.math.stochastic; import java.net.InetAddress; import java.util.Random; import org.sfc.utils.HashCode; /** *
* This class provides routines to create random numbers for most of the * common random distributions. *
* Warning: This class is no longer thread safe. This allows us to speed * up the random number generation (ca. 2.5 times on P4, WinXP). *
* * @author Thomas Weise */ public class Randomizer extends Random { /** * The serial version uid. */ private static final long serialVersionUID = 1; /** * The random multiplier. */ private final static long MULTIPLIER = 0x5DEECE66DL; /** * The number to add when multiplication has been done. */ private final static long ADDEND = 0xBL; /** * The mask bits. */ private final static long MASK = (1L << 48) - 1; /** * An internal seed counter. */ private static int s_seed = -435735; /** * The fixed seed. * @see #set_fixed_seed() */ private final static long FIXED_SEED = 0x574e7d8fa8b34ca3L; /** * The seed of the randomizer. */ private long m_seed ; /** * Create a new randomizer. */ public Randomizer () { this(create_seed()); } /** * Create a new randomizer. * @param p_addr An internet address. */ public Randomizer (final InetAddress p_addr) { this( (p_addr != null) ? (HashCode.byte_array_hash_code(p_addr.getAddress()) + (p_addr.getCanonicalHostName().hashCode() << 32L)) : create_seed()); } /** * Create a seed for this randomizer. * @return A seed suitable for this randomizer. */ private static final long create_seed() { synchronized(Randomizer.class) { return ((s_seed++) + System.nanoTime() - System.currentTimeMillis() + Runtime.getRuntime().freeMemory() - Randomizer.class.hashCode()); } } /** * Reset the randomizer to a randomly chosen rand-sedd. You may call this * method after using a predefined rand-seed for a while and wish to create * real random numbers again. * @see #set_fixed_seed() * @see #setSeed(long) */ public final void reset() { this.m_seed = create_seed(); } /** * Set the random seed to a predefined, fixed seed which remains constant * in this VM. */ public final void set_fixed_seed() { this.setSeed(FIXED_SEED); } /** * Create a new randomizer. * @param p_seed The randomizer's initial seed. */ public Randomizer (final long p_seed) { super(p_seed); this.m_seed = p_seed; } /** * Obtain the randomizer's current seed. * @return The randomizer's current seed. */ public final long get_seed () { return this.m_seed; } /** * Generates the next pseudorandom number. Subclass should * override this, as this is used by all other methods.
* The general contract of next is that it returns an
* int value and if the argument bits is between 1
* and 32 (inclusive), then that many low-order bits of the
* returned value will be (approximately) independently chosen bit
* values, each of which is (approximately) equally likely to be
* 0 or 1.
* This is a linear congruential pseudorandom number generator, as
* defined by D. H. Lehmer and described by Donald E. Knuth in The
* Art of Computer Programming, Volume 2: Seminumerical
* Algorithms, section 3.2.1.
*
* @param p_bits random bits
* @return the next pseudorandom value from this random number generator's sequence.
* @since JDK1.1
*/
@Override
protected int next(final int p_bits)
{
long l_nextseed;
this.m_seed = l_nextseed = (((this.m_seed * MULTIPLIER) + ADDEND) & MASK);
return (int)(l_nextseed >>> (48 - p_bits));
}
/**
* Sets the seed of this random number generator using a single
* long
seed. The general contract of setSeed
* is that it alters the state of this random number generator
* object so as to be in exactly the same state as if it had just
* been created with the argument seed as a seed. The method
* setSeed is implemented by class Random as follows:
*
* The implementation of setSeed by class Random * happens to use only 48 bits of the given seed. In general, however, * an overriding method may use all 64 bits of the long argument * as a seed value. * * Note: Although the seed value is an AtomicLong, this method * must still be synchronized to ensure correct semantics * of haveNextNextGaussian. * * @param p_seed the initial seed. */ @Override public final void setSeed(final long p_seed) { this.m_seed = p_seed; } /** * Create a new normal* synchronized public void setSeed(long seed) { * this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1); * haveNextNextGaussian = false; * }
N(p_my, p_sigma)
distributed random
* number.
* @param p_my The average of the random distribution.
* @param p_sigma The standard deviation of the values distribution.
* @return A new N(p_my, p_sigma)
distributed random number.
*/
public final double normal (final double p_my,
final double p_sigma)
{
return (p_my + (this.nextGaussian() * p_sigma));
}
/**
* Returns an exponential exp(1)
distributed random number
* (where lambda is 1).
* @return An exponential exp(1)
distributed random number
* (where lambda is 1).
*/
public final double exponential ()
{
double l_d;
do
{
l_d = this.nextDouble();
} while(l_d <= 0.0d);
return -Math.log(l_d);
}
/**
* Returns an exponential exp(1)
distributed random number
* (where lambda is 1/p_average
).
* @param p_average The average of the returned random numbers.
* @return An exponential exp(1)
distributed random number
* (where lambda is 1/p_average
).
*/
public final double exponential (final double p_average)
{
double l_d;
do
{
l_d = this.nextDouble();
} while(l_d <= 0.0d);
return -Math.log(l_d) * p_average;
}
/**
* Create a random integer in the range [1,p_n]
, where the
* probability of a special integer getting drawn is proportional to its
* value. If you have p_n=3
, for example, the probability for
* for 1 getting drawn is 1/6, for 2 its 2/6 and for 3 its 3/6.
* @param p_n The maximum value.
* @return The new proportional random number.
*/
public final int proportional(int p_n)
{
int l_d;
l_d = (int)(this.nextDouble() * ( (p_n*(p_n+1)) >>> 1));
for(; p_n > 0; p_n--)
{
if(p_n > l_d) return p_n;
l_d -= p_n;
}
return 1;
}
}