/** @file psRandom.h
*  \brief Random Number Generators
*  \ingroup Math
*
*  This file will hold the prototypes for procedures which allocate, free,
*  and evaluate random number Generators.
*
*  @ingroup Math
*
*  @author GLG, MHPCC
*
*  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
*  @date $Date: 2005-08-23 23:23:05 $
*
*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
*/

#ifndef PS_RANDOM_H
#define PS_RANDOM_H

#include <stdio.h>
#include <stdbool.h>
#include <float.h>
#include <math.h>

#include "psVector.h"
#include "psScalar.h"
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>

/** \addtogroup Math
 *  \{
 */

/** Enumeration containing a flag for psRandom types.  */
typedef enum {
    PS_RANDOM_TAUS                     ///< A maximally equidistributed combined Tausworthe generator.
} psRandomType;

/** Data structure for psRandom.
 *  Contains information on the psRandom type and GNU Scientific Library random number generator.
 */
typedef struct
{
    psRandomType type;                 ///< The type of RNG
    gsl_rng *gsl;                      ///< The RNG itself
}
psRandom;

psU64 p_psRandomGetSystemSeed();

/** Allocates a psRandom struct.
 *  
 *  @return psRandom*:    A new psRandom structure.
 */
psRandom *psRandomAlloc(
    psRandomType type,                 ///< The type of RNG
    unsigned long seed                 ///< Known value with which to seed the RNG
);

/** Resets an existing psRandom struct.
 *  
 *  @return void
 */
void psRandomReset(
    psRandom *rand,                    ///< Existing psRandom struct to reset
    unsigned long seed                 ///< Known value with which to seed the RNG
);

/** Random number generator based on a uniform distribution on [0,1).
 *  Uses gsl_rng_uniform.
 *  
 *  @return double:     Random number.
 */
double psRandomUniform(
    const psRandom *r                  ///< psRandom struct for RNG
);

/** Random number generator based on a Gaussian deviate, N(0,1).
 *  Uses gsl_ran_gaussian.
 *  
 *  @return double:     Random number.
 */
double psRandomGaussian(
    const psRandom *r                  ///< psRandom struct for RNG
);

/** Random number generator based on a Gaussian deviate, N(0,1).
 *  Uses gsl_ran_gaussian.
 *  
 *  XXX: I created this since the above psLib spec for p_psRandomGaussian
 *  had no argument for sigma.  Verify that with IfA.
 *  
 *  @return double:     Random number.
 */
double p_psRandomGaussian(
    const psRandom *r,                  ///< psRandom struct for RNG
    double sigma
);

/** Random number generator based on a Poisson distribution with the given mean.
 *  Uses gsl_ran_poisson.
 *  
 *  @return double:     Random number.
 */
double psRandomPoisson(
    const psRandom *r,                 ///< psRandom struct for RNG
    double mean                         ///< Mean value
);

/* \} */// End of MathGroup Functions

#endif // #ifndef PS_RANDOM_H
