/***************************************************************************
 * rnd.C
 *
 * exports:  rnd(n)  -- returns a "random" integer in {0,1, ..., n-1}
 *           drnd(r) -- returns a "random" real in [0,r)
 *                 
 * P Rogaway - 10/95
 *
 * NOTE: uses brain-dead mechanisms;  These routines are inappropriate for 
 * applications requiring "unguessable" pseudorandom numbers (e.g., for 
 * cryptographic purposes).
 ***************************************************************************
 */

#ifndef IOSTREAMH
#include <iostream.h>
#endif
#ifndef __MATH_H__
#include <math.h>
#endif
#ifndef _SYS_TIME_H
#include <sys/time.h>
#endif
#ifndef __STDLIB_H__
#include <stdlib.h>
#endif 

#ifndef _SGI_SOURCE
  extern "C" int gettimeofday(struct timeval *tp,struct timezone *tz);
#endif

static const same_random_numbers_each_run = 0; // for debug, sometimes  useful
                                               // to set this to 1, so one 
                                               // always gets the same
                                               // "random" numbers.

/*
 * getseed 
 *    get a seed (just 32 bits) for the pseudorandom generator, using
 *    the simplest possible thing (time returned by gettimeofday()).
 */
static long getseed()
{
  if (same_random_numbers_each_run) {
    return 1;
  } 
  else {
    struct timeval tp; 
    struct timezone tzp;
    if (gettimeofday(&tp, &tzp)) { 
       cerr << "getseed:  gettimeofday failed\n";
       return 0;
    }
    return tp.tv_usec;
  }
}


///////////////////////////////////////////////////////////
// rnd(n) -- return a "random" integer in [0..n-1]
///////////////////////////////////////////////////////////
int rnd(int n)
{
  static first_time=1;                                       
  static char state[256];                                   
  if (first_time) {                                        
    first_time = 0;                                       
    unsigned int seed = (unsigned int) getseed();
    initstate(seed, state, 256);                           
  }
  if (n<0) {cerr << "Bad argument to rnd()\n"; return 0;}
  unsigned long mask = 1;
  while (mask<n) mask = 2*mask+1;
  for (;;) {
    long r = random();
    if ((r&mask) < n) return r&mask;
  }
} 


///////////////////////////////////////////////////////////
// drnd(r) -- return a "random" double in [0,.r)
///////////////////////////////////////////////////////////
double drnd(double r)
{
  static first_time=1;                                       
  if (first_time) {                                        
    first_time = 0;                                       
    long seed = long(getseed()); 
    srand48(seed);
  }
  return r*drand48();
}


