package org.jgap.util;
/**
Abstract superclass for emulations of java.util.Random with
various underlying generators. These generators provide a
superset of the methods of the built-in Java generator, and
allow easy replacement of the low-level byte-stream random
generator without the need to reimplement the higher-level
calls.
<p>
The nature of the data returned by the functions in this class
depends upon the generator provided by the class derived from it.
If the generator is algorithmic, the data are pseudorandom; if a
hardware generator is employed, genuine random data may be
obtained. For brevity, in this document, we use <em>random</em>
to refer to the data returned, whatever its actual source.
<p>
Designed and implemented in July 1996 by
<a href="http://www.fourmilab.ch/">John Walker</a>,
<a href="mailto:kelvin@fourmilab.ch">kelvin@fourmilab.ch</a>.
@see java.util.Random
*/
public abstract class randomX {
private int nbits = 0;
private boolean iset = false;
/** Reset when seed changes. A generator which supports seed
must call this method by <tt>super.setSeed()</tt> when its own
<tt>setSeed(</tt><i>long</i><tt>)</tt> method is called. This
allows randomX to discard any buffered data in the
<tt>nextBit()</tt> and <tt>nextGaussian()</tt> methods so that
subsequent calls will immediately reflect the new seed.
<p>
If a derived class does not permit specification of a seed
(hardware-based generators, for example), it should declare:
<p>
<blockquote>
<tt>private void setSeed(long seed) { }</tt>
</blockquote>
<p>
which will hide the setSeed method from its users and cause
a compile-time error if a program attempts to specify a seed. */
public void setSeed() {
nbits = 0;
iset = false;
}
/** Return next [pseudo]random byte from low level generator. All
generators derived from this class must implement
<tt>nextByte()</tt>. */
public abstract byte nextByte();
/* Emulation of standard java.util.Random methods. Given
an implementation of nextByte() in the derived class, these
methods provide all the other forms of results. A derived
class is, of course, free to reimplement any of these.
For example, a generator which produces 31 high-quality
pseudorandom bits on each call might reimplement nextBit(),
nextShort(), and nextFloat() to avoid the inefficiency of
passing individual bytes to the parent class, then reassembling
to return to the caller. */
/** @return the next random, uniformly distributed, <tt>int</tt>
value. */
public int nextInt() {
return (int) ((((int) nextShort()) << 16) | (((int) nextShort()) & 0xFFFF));
}
/** @return the next random, uniformly distributed, <tt>long</tt>
value. */
public long nextLong() {
return (long) ((((long) nextInt()) << 32) | (((long) nextInt()) & 0xFFFFFFFFl));
}
/** @return the next random, uniformly distributed, <tt>float</tt>
value, greater than or equal to 0 and less than 1. */
public float nextFloat() {
return (float) ((nextInt() & 0x7FFFFFFF) / (0x7FFFFFFF * 1.0));
}
/** @return the next random, uniformly distributed, <tt>double</tt>
value, greater than or equal to 0 and less than 1. */
public double nextDouble() {
return (double) ((nextLong() & 0x7FFFFFFFFFFFFFFFl) /
(0x7FFFFFFFFFFFFFFFl * 1.0));
}
private double gset;
/** @return the next Gaussian (normal, or bell-curve) distributed
random value, with mean of 0.0 and standard deviation
1.0. */
public double nextGaussian() {
double fac, rsq, v1, v2;
if (!iset) {
do {
v1 = 2 * nextDouble() - 1;
v2 = 2 * nextDouble() - 1;
rsq = v1 * v1 + v2 * v2;
} while (rsq > 1.0 || rsq == 0.0);
fac = Math.sqrt(-2.0 * Math.log(rsq) / rsq);
gset = v1 * fac;
iset = true;
return v2 * fac;
} else {
iset = false;
return gset;
}
}
// Extended generator access methods with default implementations
private byte b;
/** @return the next random bit, as a <tt>boolean</tt>. */
public boolean nextBit() {
boolean bit;
if (nbits <= 0) {
b = nextByte();
nbits = 8;
}
bit = (b & 0x80) != 0;
b <<= 1;
nbits--;
return bit;
}
/** Fill a portion of an array of bytes with random data.
@param buf array of <tt>byte</tt> to fill.
@param buflen number of bytes to store.
*/
public void nextByte(byte buf[], int buflen) {
int i = 0;
while (buflen-- > 0) {
buf[i++] = nextByte();
}
}
/** Fill an array of bytes with random data.
@param buf array of <tt>byte</tt>s to fill.
*/
public void nextByte(byte buf[]) {
nextByte(buf, buf.length);
}
/** @return the next random, uniformly distributed, <tt>short</tt>
value. */
public short nextShort() {
return (short) ((((short) nextByte()) << 8) | ((short) (nextByte() & 0xFF)));
}
}