package umontreal.iro.lecuyer.randvar;
import umontreal.iro.lecuyer.randvar.RandomVariateGen;
import cern.colt.list.DoubleArrayList;
import umontreal.iro.lecuyer.rng.RandomStream;
import umontreal.iro.lecuyer.probdist.Distribution;
/**
* This class represents a random variate generator whose values
* are cached for more efficiency when using
* common random numbers. An object
* from this class is constructed with a reference to a
* {@link RandomVariateGen} instance used to
* get the random numbers. These numbers
* are stored in an internal array to be retrieved later.
* The dimension of the array increases as the values
* are generated.
* If the {@link #nextDouble(()) nextDouble} method is called after
* the object is reset (by calling
* {@link #setCachedValues((DoubleArrayList)) setCachedValues}), it gives back the cached
* values instead of computing new ones.
* If the cache is exhausted before the generator is reset,
* new values are computed and added to the cache.
*
*
* Such caching allows for a better performance with
* common random numbers, when
* generating random variates is time-consuming.
* However, using such caching may lead to memory problems if
* a large quantity of random numbers are needed.
*
*/
public class RandomVariateGenWithCache extends RandomVariateGen {
private RandomVariateGen rvg;
private DoubleArrayList values;
private int index = 0;
private boolean caching = true;
/**
* Constructs a new cached random variate generator with
* internal generator rvg.
*
* @param rvg the random variate generator whose values are cached.
*
* @exception NullPointerException if rvg is null.
*
*
*/
public RandomVariateGenWithCache (RandomVariateGen rvg) {
if (rvg == null)
throw new NullPointerException
("The given random variate generator cannot be null");
this.rvg = rvg;
values = new DoubleArrayList();
}
/**
* Constructs a new cached random variate generator
* with internal generator rvg. The initialCapacity
* parameter is used to set the initial capacity of the internal array
* which can grow as needed; it does not limit the maximal
* number of cached values.
*
* @param rvg the random variate generator whose values are cached.
*
* @param initialCapacity the number of cached values.
*
* @exception NullPointerException if rvg is null.
*
*/
public RandomVariateGenWithCache (RandomVariateGen rvg,
int initialCapacity) {
if (rvg == null)
throw new NullPointerException
("The given random variate generator cannot be null");
this.rvg = rvg;
values = new DoubleArrayList (initialCapacity);
}
/**
* Determines if the random variate generator is caching values,
* default being true.
* When caching is turned OFF, the {@link #nextDouble(()) nextDouble}
* method simply calls the corresponding method on the internal
* random variate generator, without storing the generated values.
*
* @return the caching indicator.
*
*/
public boolean isCaching() {
return caching;
}
/**
* Sets the caching indicator to caching.
* If caching is turned OFF, this method calls {@link #clearCache(()) clearCache}
* to clear the cached values.
*
* @param caching the new value of the caching indicator.
*
*
*/
public void setCaching (boolean caching) {
if (this.caching && !caching)
clearCache();
this.caching = caching;
}
/**
* Returns a reference to the random variate generator
* whose values are cached.
*
* @return a reference to the random variate generator whose values are cached.
*
*/
public RandomVariateGen getCachedGen() {
return rvg;
}
/**
* Sets the random variate generator whose values are cached to
* rvg. If the generator is changed, the {@link #clearCache(()) clearCache}
* method is called.
*
* @param rvg the new random variate generator whose values are cached.
*
* @exception NullPointerException if rvg is null.
*
*
*/
public void setCachedGen (RandomVariateGen rvg) {
if (rvg == null)
throw new NullPointerException
("The given random variate generator cannot be null");
if (rvg == this.rvg)
return;
this.rvg = rvg;
clearCache();
}
/**
* Clears the cached values for this cached generator.
* Any subsequent call will then obtain new values
* from the internal generator.
*
*/
public void clearCache() {
//values.clear();
// Keep the array previously returned by getCachedValues
// intact to allow caching values for several
// replications.
values = new DoubleArrayList();
index = 0;
}
/**
* Resets this generator to recover values from the cache.
* Subsequent calls
* to {@link #nextDouble(()) nextDouble} will return the cached random
* values until all the values are returned. When the array
* of cached values is exhausted, the internal random variate
* generator is used to generate new values which are added
* to the internal array as well.
* This method is equivalent to calling {@link #setCacheIndex((int)) setCacheIndex}.
*
*/
public void initCache() {
index = 0;
}
/**
* Returns the total number of values cached by this generator.
*
* @return the total number of cached values.
*
*/
public int getNumCachedValues() {
return values.size();
}
/**
* Return the index of the next cached value that will be
* returned by the generator.
* If the cache is exhausted, the
* returned value corresponds to the value returned by
* {@link #getNumCachedValues(()) getNumCachedValues}, and a subsequent call to
* {@link #nextDouble(()) nextDouble} will generate a new variate rather than
* reading a previous one from the cache.
* If caching is disabled, this always returns 0.
*
* @return the index of the next cached value.
*
*/
public int getCacheIndex() {
return index;
}
/**
* Sets the index, in the cache, of the next value returned
* by {@link #nextDouble(()) nextDouble}.
* If newIndex is 0, this is equivalent to
* calling {@link #initCache(()) initCache}.
* If newIndex is {@link #getNumCachedValues(()) getNumCachedValues},
* subsequent calls to {@link #nextDouble(()) nextDouble} will add
* new values to the cache.
*
* @param newIndex the new index.
*
* @exception IllegalArgumentException if newIndex
* is negative or greater than or equal to the cache size.
*
*
*/
public void setCacheIndex (int newIndex) {
if (newIndex < 0 || newIndex > values.size())
throw new IllegalArgumentException
("newIndex must not be negative or greater than the cache size");
index = newIndex;
}
/**
* Returns an array list containing the values
* cached by this random variate generator.
*
* @return the array of cached values.
*
*/
public DoubleArrayList getCachedValues() {
return values;
}
/**
* Sets the array list containing the cached
* values to values.
* This resets the cache index to
* the size of the given array.
*
* @param values the array list of cached values.
*
* @exception NullPointerException if values is null.
*
*
*/
public void setCachedValues (DoubleArrayList values) {
if (values == null)
throw new NullPointerException();
this.values = values;
index = values.size();
}
public double nextDouble() {
if (!caching)
return rvg.nextDouble();
else if (index >= values.size()) {
double v = rvg.nextDouble();
values.add (v);
++index;
return v;
}
else
return values.getQuick (index++);
}
public void nextArrayOfDouble (double[] v, int start, int n) {
if (!caching) {
rvg.nextArrayOfDouble (v, start, n);
return;
}
int remainingValues = values.size() - index;
if (remainingValues < 0)
remainingValues = 0;
int ncpy = Math.min (n, remainingValues);
if (ncpy > 0) {
System.arraycopy (values.elements(), index, v, start, ncpy);
index += ncpy;
}
int ngen = n - ncpy;
if (ngen > 0) {
rvg.nextArrayOfDouble (v, start + ncpy, ngen);
for (int i = ncpy; i < n; i++) {
values.add (v[start + i]);
++index;
}
}
}
public RandomStream getStream() {
return rvg.getStream();
}
public Distribution getDistribution() {
return rvg.getDistribution();
}
}
Ads help maintain this website.