import java.util.Random;

/**
 * A class for generating random numbers according to distributions.
 * (A wrapper for java.util.Random)
 * @author Derek Bridge 666 d.bridge@cs.ucc.ie
 * Methods are partly based on ones in some code written for a textbook:
 * <EM>Data Structures and Problem Solving with Java (2nd edn)</EM>
 * by Mark Allen Weiss (http://www.cs.fiu.edu/~weiss/), Addison-Wesley, 2001
 */
public class CS2000Random
{
/* =======================================================================
       CONSTRUCTORS
   =======================================================================
*/
    /**
     * Allocates a random number generator.
     */
    public CS2000Random()
    {   generator = new Random();
    }

/* =======================================================================
       PUBLIC INTERFACE
   =======================================================================
*/
/* --Getters----------------------------------------------------------- */

    /**
     * Returns a random int according to a negative exponential distribution
     * @param theMean the desired mean for the distribution
     * @return a random int from a distribution with the desired mean
     */
    public int nextNegExp(int theMean)
    {   return (int) (Math.round(- theMean * 
            Math.log(nextNonZeroUniformDouble())));
    }

    /**
     * Returns a random int according to a Poisson distribution
     * @param theMean the desired mean for the distribution
     * @return a random int from a distribution with the desired mean
     */
    public int nextPoisson(int theMean)
    {   double limit = -theMean;
        double product = Math.log(nextNonZeroUniformDouble());
        int count;
        for(count = 0; product > limit; count++)
        {   product += Math.log(nextNonZeroUniformDouble());
        }
        return count;
    }

/* =======================================================================
       HELPER METHODS
   =======================================================================
*/
    /**
     * Generate a non-zero random double according to the uniform dist
     * @return a non-zero random double
     */
    private double nextNonZeroUniformDouble()
    {   double d = 0.0;
        do
        {   d = generator.nextDouble();
        } while (d == 0.0);
        return d;
    }

/* =======================================================================
       INSTANCE VARIABLES & CLASS VARIABLES
   =======================================================================
*/
    /**
     * The random number generator.
     */
    private Random generator;
}
