Blame rng/minstd.c

Packit 67cb25
/* rng/minstd.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 James Theiler, Brian Gough
Packit 67cb25
 * 
Packit 67cb25
 * This program is free software; you can redistribute it and/or modify
Packit 67cb25
 * it under the terms of the GNU General Public License as published by
Packit 67cb25
 * the Free Software Foundation; either version 3 of the License, or (at
Packit 67cb25
 * your option) any later version.
Packit 67cb25
 * 
Packit 67cb25
 * This program is distributed in the hope that it will be useful, but
Packit 67cb25
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 67cb25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 67cb25
 * General Public License for more details.
Packit 67cb25
 * 
Packit 67cb25
 * You should have received a copy of the GNU General Public License
Packit 67cb25
 * along with this program; if not, write to the Free Software
Packit 67cb25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
#include <config.h>
Packit 67cb25
#include <stdlib.h>
Packit 67cb25
#include <gsl/gsl_rng.h>
Packit 67cb25
Packit 67cb25
/* MINSTD is Park and Miller's minimal standard generator (i.e. it's
Packit 67cb25
   not particularly good).
Packit 67cb25
Packit 67cb25
   The sequence is
Packit 67cb25
Packit 67cb25
   x_{n+1} = (a x_n) mod m
Packit 67cb25
Packit 67cb25
   with a = 16807 and m = 2^31 - 1 = 2147483647. The seed specifies
Packit 67cb25
   the initial value, x_1.  
Packit 67cb25
Packit 67cb25
   The theoretical value of x_{10001} is 1043618065, starting with a
Packit 67cb25
   seed of x_1 = 1.
Packit 67cb25
Packit 67cb25
   The period of this generator is 2^31.
Packit 67cb25
Packit 67cb25
   It is used as the RNUN subroutine in the IMSL Library and the RAND
Packit 67cb25
   function in MATLAB. The generator is sometimes known by the acronym
Packit 67cb25
   "GGL" (I'm not sure what that stands for).
Packit 67cb25
Packit 67cb25
   From: Park and Miller, "Random Number Generators: Good ones are
Packit 67cb25
   hard to find" Communications of the ACM, October 1988, Volume 31,
Packit 67cb25
   No 10, pages 1192-1201. */
Packit 67cb25
Packit 67cb25
static inline unsigned long int minstd_get (void *vstate);
Packit 67cb25
static double minstd_get_double (void *vstate);
Packit 67cb25
static void minstd_set (void *state, unsigned long int s);
Packit 67cb25
Packit 67cb25
static const long int m = 2147483647, a = 16807, q = 127773, r = 2836;
Packit 67cb25
Packit 67cb25
typedef struct
Packit 67cb25
  {
Packit 67cb25
    unsigned long int x;
Packit 67cb25
  }
Packit 67cb25
minstd_state_t;
Packit 67cb25
Packit 67cb25
static inline unsigned long int
Packit 67cb25
minstd_get (void *vstate)
Packit 67cb25
{
Packit 67cb25
  minstd_state_t *state = (minstd_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  const unsigned long int x = state->x;
Packit 67cb25
Packit 67cb25
  const long int h = x / q;
Packit 67cb25
  const long int t = a * (x - h * q) - h * r;
Packit 67cb25
Packit 67cb25
  if (t < 0)
Packit 67cb25
    {
Packit 67cb25
      state->x = t + m;
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      state->x = t;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return state->x;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static double
Packit 67cb25
minstd_get_double (void *vstate)
Packit 67cb25
{
Packit 67cb25
  return minstd_get (vstate) / 2147483647.0;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
minstd_set (void *vstate, unsigned long int s)
Packit 67cb25
{
Packit 67cb25
  minstd_state_t *state = (minstd_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  if (s == 0)
Packit 67cb25
    s = 1;      /* default seed is 1 */
Packit 67cb25
Packit 67cb25
  state->x = s;
Packit 67cb25
Packit 67cb25
  return;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static const gsl_rng_type minstd_type =
Packit 67cb25
{"minstd",                      /* name */
Packit 67cb25
 2147483646,                    /* RAND_MAX */
Packit 67cb25
 1,                             /* RAND_MIN */
Packit 67cb25
 sizeof (minstd_state_t),
Packit 67cb25
 &minstd_set,
Packit 67cb25
 &minstd_get,
Packit 67cb25
 &minstd_get_double};
Packit 67cb25
Packit 67cb25
const gsl_rng_type *gsl_rng_minstd = &minstd_type;