/* random.h

   written by Frederic Bois
   modifications by Don Robert Maszle
   8 January 1992
   
   Copyright (c) 1993.  Don Maszle, Frederic Bois.  All rights reserved.

   -- Revisions -----
     Logfile:  SCCS/s.random.h
    Revision:  1.3
        Date:  8/7/93
     Modtime:  21:38:09
      Author:  @a
   -- SCCS  ---------

   Header for random number generator.  See random.c for extensive
   documentation.

   Gives prototypes for random functions.  Also defines a type
   "VARIATE" which is a real continuous random variate specification.
*/

#ifndef _RANDOM_INCLUDED

    /*-- If defined this allows smaller variate functions to be
         defined as macros so that they are inlined for speed.

         !!! Note that these macros may have the side effect !!!
         !!! that arguments are evaluated more than once.    !!!

         The #ifndef block is designed in case you want to specify the
         option explicitly before including this header.
     */
#ifndef VARIATE_CALCS_CAN_BE_MACROS
#define VARIATE_CALCS_CAN_BE_MACROS
#endif


#ifdef VARIATE_CALCS_CAN_BE_MACROS
#include <math.h>
#endif

/*-- Variate types */

typedef enum tagVariateType {
  UniformVariate,  LogUniformVariate,

  NormalVariate, _NormalVariate,
  TruncNormalVariate,
  LogNormalVariate,
  TruncLogNormalVariate,

  GammaVariate,    _GammaVariate,
  BetaVariate,     Chi2Variate,

  BinomialVariate,
  PiecewiseConstantVariate

} VariateType;  /* tagVariateType */


/*-- A VARIATE is a VariateType, with a range, and shape parameters */

   /*-- The shape parameters mean the following 
        for:
          NormalVariate:  -no parms-
          _NormalVariate: rgdParms[0] = mean,      [1]: variance
          BetaVariate:      rgdParms[0] = alpha,     [1]: beta
          BinomialVariate:  rgdParms[0] = p, rglParms[0]: n
          Chi2Variate:      rglParms[0] = d.o.f.
          GammaVariate:     rgdParms[0] = a
          _GammaVariate:    rgdParms[0] = a,         [1]: b
          PiecewiseConstant: rdlParms[0] = clSamples

        They are undefined for other variates.
        Please use the RGx_ values below.
    */

    /*-- Indices into rgxParm arrays */

#define RGD_ALPHA     0         /*-- Shape parms for Beta */
#define RGD_BETA      1

#define RGD_MEAN      0         /*-- Parameters for Normal */
#define RGD_STDDEV    1

#define RGD_PR_ONE_TRIAL 0      /*-- Parameters for Binomial */
#define RGL_CLTRIALS     0

#define RGD_DOF          0      /*-- Parameters for Chi2 */

#define RGL_CLSAMPLES 0         /*-- Count of samples for PiecewiseConstant */

#define MAX_VARIATE_PARMS 4

typedef struct tagVARIATE {
  VariateType vtType;           /*-- The type of the random variate */
  double dMin, dMax;            /*-- The range of the Variate */
  double dValue;                /*-- The current value of the variate */

  double rgdParms[MAX_VARIATE_PARMS]; /*-- Real parameters    */
  long   rglParms[MAX_VARIATE_PARMS]; /*-- Integer parameters */

  double *rgdX;                 /*-- Ordinates of SumX  points */
  double *rgdSumX;              /*-- Piecewise Linear Cumulative for speed */

} VARIATE;  /* struct tagVARIATE */  

/* ----- Macros  */

#ifdef VARIATE_CALCS_CAN_BE_MACROS

#define UniformRandom(a, b)    ( Random()*((b) - (a)) + (a) )
#define LogUniformRandom(a, b) ( (a)*pow((b)/(a), Random()) )
#define _NormalRandom(m, s)  ( (m) + (s)*NormalRandom() )
#define LogNormalRandom(m, s)  ( exp(_NormalRandom((m), (s))) )
#define _GammaRandom(a, b)     ( (b)*GammaRandom(a) )
#define Chi2Random(dof)        ( _GammaRandom((dof)/2.0, 2.0) )
#endif

/* ----- Prototypes  */
                                /*-- Initialize the random generators */
void InitRandom (double dSeed, int bWarmUp);

                                /*-- Two random generators */
double RandomShuffle (void);    /*   ..one that shuffles its output, */
double Random (void);           /*   ..and one that doesn't */

                                /*-- Several types of random variates */ 
#ifndef VARIATE_CALCS_CAN_BE_MACROS

double UniformRandom (double a, double b);
double LogUniformRandom (double a, double b);
double _NormalRandom (double dMean, double dStdDev);
double LogNormalRandom(double dMean, double dStdDev);
double _GammaRandom (double a, double b);
double Chi2Random (double dof);

#endif

double BetaRandom (double a, double b, double alpha, double beta);
double BinomialRandom (double p, long n);
double NormalRandom (void);
double GammaRandom (double a);
double TruncNormalRandom (double dMean, double dStdDev, double a, double b);
double TruncLogNormalRandom(double dMean, double dStdDev, double a, double b);

void multinomial (long n, int dim, double *p, double *x);


    /*-- Utility functions */

double lnGamma (double x);

    /*-- Routines for VARIATES */

double CalcVariate (VARIATE *pvariate);    /*-- Calc and return new value */
double ValueOfVariate (VARIATE *pvariate); /*-- Return current value      */

#ifdef ndef
double CalcPdf (VARIATE *pvariate, double x); /*-- Value of pdf at x */
#endif

#define _RANDOM_INCLUDED
#endif
