/////////////////////////////////////////////////////////////////////////////
// random1.cc
//
// SIMLIB version: 2.18
// Date: 2004-01-25
//
// Copyright (c) 1991-2004 Petr Peringer 
//
// This library is licensed under GNU Library GPL. See the file COPYING.
//

//
// base random number generator
// generate uniform distribution in the range 0 .. 0.99999999999....
//

////////////////////////////////////////////////////////////////////////////
// interface
//

#include "simlib.h"
#include "internal.h"

// external functions
void   RandomSeed(long seed);     // initialize random number seed
double Random();                  // base uniform generator 0-0.999999...
void   SetBaseRandomGenerator(double (*new_gen)()); // change base gen.

////////////////////////////////////////////////////////////////////////////
// implementation
//

SIMLIB_IMPLEMENTATION

////////////////////////////////////////////////////////////////////////////
// some constants for base generator
//

const long INICONST   = 1537L;
const long MULCONST   = 1220703125L;
// length of period = 536870912 !!!
 
const long MAXLONGINT = 0x7FFFFFFFUL;
const long SIGNBIT    = 0x80000000UL;

////////////////////////////////////////////////////////////////////////////
// random generator seed
//

static long SIMLIB_RandomSeed = INICONST ;

////////////////////////////////////////////////////////////////////////////
// RandomSeed - initialization of random generator
//
void RandomSeed(long seed)
{
  SIMLIB_RandomSeed = seed;
}

////////////////////////////////////////////////////////////////////////////
// SIMLIB_RandomBase --- default base uniform random number generator
//
// uses linear congruential method
// (not very good)
//
double SIMLIB_RandomBase()  // range <0..1)
{
  SIMLIB_RandomSeed *= MULCONST;
  if(SIMLIB_RandomSeed<0)  SIMLIB_RandomSeed ^= SIGNBIT;
  return (double)SIMLIB_RandomSeed/MAXLONGINT;
}

////////////////////////////////////////////////////////////////////////////
// pointer to base generator
//
static double (*SIMLIB_RandomBasePtr)() = SIMLIB_RandomBase;

////////////////////////////////////////////////////////////////////////////
// Random --- base uniform random number generator
//
// generate pseudorandom number in the range  0 .. 0.999999999999999999999
//
double Random()
{
  return SIMLIB_RandomBasePtr();
}

////////////////////////////////////////////////////////////////////////////
// SetBaseRandomGenerator --- change base random number generator
//
void SetBaseRandomGenerator(double (*new_gen)()) 
{
  if(new_gen)
    SIMLIB_RandomBasePtr = new_gen;
  else
    SIMLIB_RandomBasePtr = SIMLIB_RandomBase; // default value
}

// end

