RandomElement.java

package edu.cornell.lassp.houle.RngPack;


import java.util.*;

/**
*   RandomElement is an abstract class that encapsulates random number
* generators.  To base a class on it,  you must define the method 
* <CODE>raw()</CODE> as described below.  It is also likely that you
* will want to define a constructor or another mechanism for seeding the
* the generator.  The other classes defined in <CODE>RandomElement</CODE>
* add value to the numbers generated by <CODE>raw()</CODE>
*
* <P>
* <A HREF="../src/edu/cornell/lassp/houle/RngPack/RandomElement.java">
* Source code </A> is available.
* 
* @author <A HREF="http://www.msc.cornell.edu/~houle"> Paul Houle </A> (E-mail: <A HREF="mailto:houle@msc.cornell.edu">houle@msc.cornell.edu</A>)
* @version 1.0
* 
* @see RandomJava
* @see RandomShuffle
*/

public abstract class RandomElement extends Object {

  Double BMoutput;                // constant needed by Box-Mueller algorithm

/**
* The abstract method that must be defined to make a working RandomElement.
* See the class <CODE>RandomJava</CODE> for an example of how to do this.
*
* @see RandomJava
*
* @return a random double in the range [0,1]
*/

  abstract public double raw();

/**
* Fill part or all of an array with doubles.  The method defined here uses multiple calls to
* <CODE>raw()</CODE> to fill the array.  You can eliminate the overhead of
* multiple method calls by subclassing this with a version of the generator
* that fills the array.  On our system this improves the efficiency of
* <CODE>Ranecu</CODE> by 20% when filling large arrays.
*
*
* @param d array to be filled with doubles
* @param n number of doubles to generate
*/     

  public void raw(double d[],int n)
  {
	for(int i=0;i<n;i++)
		d[i]=raw();
  };


/**
* Fill an entire array with doubles.  This method calls <CODE>raw(double d[],int n)</CODE>
* with <CODE>d=d.length</CODE>.  Since this adds little overhead for <CODE>d.length</CODE>
* large,  it is only necessary to override <CODE>raw(double d[],int n)</CODE>
*
* @param d array to be filled with doubles.
*/

 public void raw(double d[])
 {
	raw(d,d.length);
 };

/**  
@param hi upper limit of range
@return a random integer in the range 1,2,... ,<STRONG>hi</STRONG>
*/
  public int choose(int hi) {
  
  	return (int) (1+hi*raw());
  }
  
/**
@param lo lower limit of range
@param hi upper limit of range
@return a random integer in the range <STRONG>lo</STRONG>, <STRONG>lo</STRONG>+1, ... ,<STRONG>hi</STRONG>
*/
  
  public int choose(int lo,int hi) {
  
    return (int) (lo+(hi-lo+1)*raw());
  };

/**
@param lo lower limit of range
@param hi upper limit of range
@return a uniform random real in the range [<STRONG>lo</STRONG>,<STRONG>hi</STRONG>]
*/
  public double uniform(double lo,double hi) {
    return (lo+(hi-lo)*raw());
  };

/** 
gaussian() uses the Box-Muller algorithm to transform raw()'s into
gaussian deviates.

@return a random real with a gaussian distribution,  standard deviation 

*/
 
  public double gaussian()

  {
     double out,x,y,r,z;

     if (BMoutput != null)    
     {
         out = BMoutput.doubleValue();
         BMoutput = null;
         return(out);
     };

     do {
         x=uniform(-1,1);
         y=uniform(-1,1);
         r=x*x+y*y;
     } while (r >= 1.0);

     z=Math.sqrt(-2.0*Math.log(r)/r);
     BMoutput=new Double(x*z);
     return(y*z); 
   }; 

/**
* 
* @param sd standard deviation
* @return a gaussian distributed random real with standard deviation <STRONG>sd</STRONG>
*/

  public double gaussian(double sd)
  {
     return(gaussian()*sd);
  };

/**
*
* generate a power-law distribution with exponent <CODE>alpha</CODE>
* and lower cutoff
* <CODE>cut</CODE>
* <CENTER>
* </CENTER>
*
*@param alpha the exponent 
*@param cut the lower cutoff
*
*/

  public double powlaw(double alpha,double cut)
  {
	return cut*Math.pow(raw(), 1.0/(alpha+1.0) ) ;
  };

};