/***************************************************************************
* Rand.h  (Random Number Generators)                                       *
*                                                                          *
* Header file for Rand.C, pseudo-random number utilities.  Rand is the     *
* base class for several different algorithms for generating pseudo-random *
* numbers.  Any method can generate individual samples or arrays of        *
* samples using "Eval".  The random seed can be reset at any time by       *
* calling "Seed" with any integer.  Random permutations of the integers    *
* 0,1,...(n-1) are generated by "Perm(n,P)".                               *
*                                                                          *
*   HISTORY                                                                *
*      Name    Date        Description                                     *
*                                                                          *
*      arvo    08/04/97    Changed to virtual functions.                   *
*      arvo    06/06/93    Optimization, especially for array evaluators.  *
*      arvo    10/06/91    Converted to C++                                *
*      arvo    11/20/89    Added "gen_seed" function to handle.            *
*      arvo    10/30/89    "state" allocation now done in rand_alloc.      *
*      arvo    07/08/89    Initial coding.                                 *
*                                                                          *
*--------------------------------------------------------------------------*
* Copyright (C) 1989, James Arvo                                           *
*                                                                          *
* This program is free software; you can redistribute it and/or modify it  *
* under the terms of the GNU General Public License as published by the    *
* Free Software Foundation.  See http://www.fsf.org/copyleft/gpl.html      *
*                                                                          *
* This program is distributed in the hope that it will be useful, but      *
* WITHOUT EXPRESS OR IMPLIED WARRANTY of merchantability or fitness for    *
* any particular purpose.  See the GNU General Public License for more     *
* details.                                                                 *
*                                                                          *
***************************************************************************/
#ifndef __RAND_INCLUDED__
#define __RAND_INCLUDED__

// Base class for random number generators.  This class contains
// several pure virtual functions, so it cannot be instanced directly.

class RandGen {
    public:
        RandGen() {}
        virtual float Eval(                  ) = 0;
        virtual void  Eval( int n, float x[] ) = 0;
        virtual void  Seed( long seed        ) = 0;
    public:
        void  Perm( int n, int P[] );
        float Interval( float a, float b );
        void  Eval( float &x ) { x = Eval(); }
    };


// Method 1: From "Numerical Recipes," by William H. Press, Brian P. 
// Flannery, Saul A. Teukolsky, and William T. Vetterling, p. 197.

class RandGen_1 : public RandGen {
    public:
        RandGen_1(           ) { Seed( 1    ); }
        RandGen_1( long seed ) { Seed( seed ); }
        virtual float Eval(                  );
        virtual void  Eval( int n, float x[] );
        virtual void  Seed( long seed        );
    private: 
        long index; 
        long seed;
        long shuffle[ 98 ];
    };


// Method 2: From "The Multiple Prime Random Number Generator," by 
// Alexander Haas, ACM Transactions on Mathematical Software, 
// Vol. 13, No. 4, December 1987, pp. 368-381.                                                      *

class RandGen_2 : public RandGen {
    public:
        RandGen_2(           ) { Seed( 1    ); }
        RandGen_2( long seed ) { Seed( seed ); }
        virtual float Eval(                  );
        virtual void  Eval( int n, float x[] );
        virtual void  Seed( long seed        );
    private: 
        long r;  
        long m;
        long i;
        long j;
    };


// Method 3: From "A More Portable Fortran Random Number Generator," 
// by Linus Schrage, ACM Transactions on Mathematical Software, 
// Vol. 5, No, 2, June 1979, pp. 132-138.                                                 *

class RandGen_3 : public RandGen {
    public:
        RandGen_3(           ) { Seed( 1    ); }
        RandGen_3( long seed ) { Seed( seed ); }
        virtual float Eval(                  );
        virtual void  Eval( int n, float x[] );
        virtual void  Seed( long seed        );
    private:
        long ix;
    };


inline float RandGen::Interval( float a, float b )
    {
    return ( a < b ) ?
        a + Eval() * ( b - a ) :
        b + Eval() * ( a - b ) ;
    }

#endif





