Last commit for lcg.h: 8a155c1522c0818d43b6bae4cc5806ea41f88793

Parallel md code using OpenMP and MPI

Ramses van Zon [2016-09-29 14:34:01]
Parallel md code using OpenMP and MPI
/*
 * lcg.h - a 'linear congruential' random number generator with
 *         support for skip-ahead in log(n) time.  Able to mimic the
 *         rand48 family of random number functions.
 *
 * USAGE
 *
 * The linear congruential generator requires three parameters (a, b,
 * and m), and a state variable (s), which are kept in a 'lcg_t'
 * structure.
 *
 * FUNCTIONS
 *
 *  lcg_t lcg_init(uint64_t a, uint64_t b, uint64_t m, uint64_t seed);
 *  lcg_t lcg_init_rand48(long int seed);
 *
 *   The function lcg_init() can be used to set these variable and the
 *   'seed' for the state.  Default values for a, b and m to mimic the
 *   behaviour of the 'rand48' family functions are provided through
 *   the function lcg_init_rand48(), which only requires a long int
 *   'seed' parameter, which in the same way as srand48 would
 *   have. Both lcg_init functions return a 'lcg_t' to be used in
 *   calls to the other lcg_* functions.
 *
 *  void lcg_seed(lcg_t* lcg, uint64_t seed);
 *
 *   The function lcg_seed() resets the seed of the random number
 *   generator 'lcg'.
 *
 *  float     lcg_float (lcg_t* lcg);
 *  double    lcg_double(lcg_t* lcg);
 *  int32_t   lcg_int32 (lcg_t* lcg);
 *  int32_t   lcg_pint32(lcg_t* lcg);
 *  uint32_t  lcg_uint32(lcg_t* lcg);
 *  uint64_t  lcg_int64(lcg_t* lcg);
 *
 *   These functions return the next random number for the random
 *   number generator 'lcg', in the form of a float, double, 32-bit
 *   integer, and 64-bit integer, respectively. The three 32-bit
 *   versions differ in the range of returned values, according to the following table:
 *   -----------  ---------------
 *   function     range
 *   -----------  ---------------
 *   lcg_int32    [-2^31,2^31-1]
 *   lcg_pint32   [0,2^31-1]
 *   lcg_uint32   [0,2^32-1]
 *   -----------  ---------------
 *
 *  void lcg_skip(lcg_t* lcg, int64_t n);
 *
 *   The function lcg_skip() skips the next 'n' random numbers, in
 *   O(log n) time. In the current implementation, if n is negative,
 *   the function will abort (or do nothing if compiled with
 *   NDEBUG). The skip-ahead feature can be useful in parallel
 *   processing.
 *
 *  void   lcg_srand48(lcg_t* lcg, long int seed);
 *  long   lcg_lrand48(lcg_t* lcg);
 *  long   lcg_mrand48(lcg_t* lcg);
 *  double lcg_drand48(lcg_t* lcg);
 *
 *   These functions mimic the behavior of rand48. The 32-bit seed
 *   passed to 'lcg_srand48' is treated in the same way to generate
 *   the 48-bit seed, and the same algorithms are used to generate
 *   long integers ('lcg_lrand48()'), signed long integers
 *   ('lcg_mrand48()'), and double precision floating point numbers
 *   ('lcg_drand48()').  If 'lcg' is initialized with
 *   lcg_init_rand48, and the seed is subsequently set with
 *   lcg_srand48, the set of random numbers generated should be
 *   identical to using srand48(), lrand48(), mrand48(), and
 *   drand48().  The added benefit of using lcg over rand48 is that
 *   skip-ahead on 'lcg' is still possible (also rand48 is not in c99
 *   or c11 standard).
 *
 * IMPLEMENTATION
 *
 * Can be found in lcg.c.
 *
 *
 * (C) 2016 Ramses van Zon, SciNet HPC Consortium, Toronto, Canada
 *
 */

#ifndef LCG_HEADER_
#define LCG_HEADER_

#include <stdint.h>

typedef struct lcg_t {
    const uint64_t a;
    const uint64_t b;
    const uint64_t m;
    uint64_t s;
    double x2;
    int have;
} lcg_t;

lcg_t lcg_init(uint64_t a, uint64_t b, uint64_t m, uint64_t seed);
lcg_t lcg_init_rand48(int32_t seed);
lcg_t lcg_init_alt35(int64_t seed);

void lcg_seed(lcg_t* lcg, uint64_t seed);
void lcg_skip(lcg_t* lcg, int64_t n);

float    lcg_float(lcg_t* lcg);
double   lcg_double(lcg_t* lcg);
int32_t  lcg_int32(lcg_t* lcg);
int32_t  lcg_pint32(lcg_t* lcg);
uint32_t lcg_uint32(lcg_t* lcg);
uint64_t lcg_int64(lcg_t* lcg);

double   lcg_normal(lcg_t* lcg);

void     lcg_srand48(lcg_t* lcg, int32_t seed);
long int lcg_lrand48(lcg_t* lcg);
long int lcg_mrand48(lcg_t* lcg);
double   lcg_drand48(lcg_t* lcg);

#endif
ViewGit