Blame rng/ran2.c

Packit 67cb25
/* rng/ran2.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
/* This is an implementation of the algorithm used in Numerical
Packit 67cb25
   Recipe's ran2 generator.  It is a L'Ecuyer combined recursive
Packit 67cb25
   generator with a 32-element shuffle-box.
Packit 67cb25
Packit 67cb25
   As far as I can tell, in general the effects of adding a shuffle
Packit 67cb25
   box cannot be proven theoretically, so the period of this generator
Packit 67cb25
   is unknown. 
Packit 67cb25
Packit 67cb25
   The period of the underlying combined generator is O(2^60). */
Packit 67cb25
Packit 67cb25
static inline unsigned long int ran2_get (void *vstate);
Packit 67cb25
static double ran2_get_double (void *vstate);
Packit 67cb25
static void ran2_set (void *state, unsigned long int s);
Packit 67cb25
Packit 67cb25
static const long int m1 = 2147483563, a1 = 40014, q1 = 53668, r1 = 12211;
Packit 67cb25
static const long int m2 = 2147483399, a2 = 40692, q2 = 52774, r2 = 3791;
Packit 67cb25
Packit 67cb25
#define N_SHUFFLE 32
Packit 67cb25
#define N_DIV (1 + 2147483562/N_SHUFFLE)
Packit 67cb25
Packit 67cb25
typedef struct
Packit 67cb25
  {
Packit 67cb25
    unsigned long int x;
Packit 67cb25
    unsigned long int y;
Packit 67cb25
    unsigned long int n;
Packit 67cb25
    unsigned long int shuffle[N_SHUFFLE];
Packit 67cb25
  }
Packit 67cb25
ran2_state_t;
Packit 67cb25
Packit 67cb25
static inline unsigned long int
Packit 67cb25
ran2_get (void *vstate)
Packit 67cb25
{
Packit 67cb25
  ran2_state_t *state = (ran2_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  const unsigned long int x = state->x;
Packit 67cb25
  const unsigned long int y = state->y;
Packit 67cb25
Packit 67cb25
  long int h1 = x / q1;
Packit 67cb25
  long int t1 = a1 * (x - h1 * q1) - h1 * r1;
Packit 67cb25
Packit 67cb25
  long int h2 = y / q2;
Packit 67cb25
  long int t2 = a2 * (y - h2 * q2) - h2 * r2;
Packit 67cb25
Packit 67cb25
  if (t1 < 0)
Packit 67cb25
    t1 += m1;
Packit 67cb25
Packit 67cb25
  if (t2 < 0)
Packit 67cb25
    t2 += m2;
Packit 67cb25
Packit 67cb25
  state->x = t1;
Packit 67cb25
  state->y = t2;
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    unsigned long int j = state->n / N_DIV;
Packit 67cb25
    long int delta = state->shuffle[j] - t2;
Packit 67cb25
    if (delta < 1)
Packit 67cb25
      delta += m1 - 1;
Packit 67cb25
    state->n = delta;
Packit 67cb25
    state->shuffle[j] = t1;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  return state->n;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static double
Packit 67cb25
ran2_get_double (void *vstate)
Packit 67cb25
{
Packit 67cb25
  float x_max = 1 - 1.2e-7f ; /* Numerical Recipes version of 1-FLT_EPS */
Packit 67cb25
Packit 67cb25
  float x = ran2_get (vstate) / 2147483563.0f ;
Packit 67cb25
 
Packit 67cb25
  if (x > x_max) 
Packit 67cb25
    return x_max ;
Packit 67cb25
  
Packit 67cb25
  return x ;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
ran2_set (void *vstate, unsigned long int s)
Packit 67cb25
{
Packit 67cb25
  ran2_state_t *state = (ran2_state_t *) vstate;
Packit 67cb25
  int i;
Packit 67cb25
Packit 67cb25
  if (s == 0)
Packit 67cb25
    s = 1;      /* default seed is 1 */
Packit 67cb25
Packit 67cb25
  state->y = s;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < 8; i++)
Packit 67cb25
    {
Packit 67cb25
      long int h = s / q1;
Packit 67cb25
      long int t = a1 * (s - h * q1) - h * r1;
Packit 67cb25
      if (t < 0)
Packit 67cb25
        t += m1;
Packit 67cb25
      s = t;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (i = N_SHUFFLE - 1; i >= 0; i--)
Packit 67cb25
    {
Packit 67cb25
      long int h = s / q1;
Packit 67cb25
      long int t = a1 * (s - h * q1) - h * r1;
Packit 67cb25
      if (t < 0)
Packit 67cb25
        t += m1;
Packit 67cb25
      s = t;
Packit 67cb25
      state->shuffle[i] = s;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  state->x = s;
Packit 67cb25
  state->n = s;
Packit 67cb25
Packit 67cb25
  return;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static const gsl_rng_type ran2_type =
Packit 67cb25
{"ran2",                        /* name */
Packit 67cb25
 2147483562,                    /* RAND_MAX */
Packit 67cb25
 1,                             /* RAND_MIN */
Packit 67cb25
 sizeof (ran2_state_t),
Packit 67cb25
 &ran2_set,
Packit 67cb25
 &ran2_get,
Packit 67cb25
 &ran2_get_double};
Packit 67cb25
Packit 67cb25
const gsl_rng_type *gsl_rng_ran2 = &ran2_type;