Blame rng/ranlxs.c

Packit 67cb25
/* rng/ranlxs.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 M. Luescher's second generation
Packit 67cb25
   version of the RANLUX generator.
Packit 67cb25
Packit 67cb25
   Thanks to Martin Luescher for providing information on this
Packit 67cb25
   generator.
Packit 67cb25
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
static unsigned long int ranlxs_get (void *vstate);
Packit 67cb25
static inline double ranlxs_get_double (void *vstate);
Packit 67cb25
static void ranlxs_set_lux (void *state, unsigned long int s, unsigned int luxury);
Packit 67cb25
static void ranlxs0_set (void *state, unsigned long int s);
Packit 67cb25
static void ranlxs1_set (void *state, unsigned long int s);
Packit 67cb25
static void ranlxs2_set (void *state, unsigned long int s);
Packit 67cb25
Packit 67cb25
static const int next[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0};
Packit 67cb25
static const int snext[24] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
Packit 67cb25
                              14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0};
Packit 67cb25
Packit 67cb25
static const double sbase = 16777216.0;         /* 2^24 */
Packit 67cb25
static const double sone_bit = 1.0 / 16777216.0;        /* 1/2^24 */
Packit 67cb25
static const double one_bit = 1.0 / 281474976710656.0;  /* 1/2^48 */
Packit 67cb25
Packit 67cb25
static const double shift = 268435456.0;        /* 2^28 */
Packit 67cb25
Packit 67cb25
#define RANLUX_STEP(x1,x2,i1,i2,i3)      \
Packit 67cb25
          x1=xdbl[i1] - xdbl[i2];        \
Packit 67cb25
          if (x2 < 0)                    \
Packit 67cb25
          {                              \
Packit 67cb25
            x1-=one_bit;                 \
Packit 67cb25
            x2+=1;                       \
Packit 67cb25
          }                              \
Packit 67cb25
          xdbl[i3]=x2
Packit 67cb25
Packit 67cb25
typedef struct
Packit 67cb25
  {
Packit 67cb25
    double xdbl[12], ydbl[12];  /* doubles first so they are 8-byte aligned */
Packit 67cb25
    double carry;
Packit 67cb25
    float xflt[24];
Packit 67cb25
    unsigned int ir;
Packit 67cb25
    unsigned int jr;
Packit 67cb25
    unsigned int is;
Packit 67cb25
    unsigned int is_old;
Packit 67cb25
    unsigned int pr;
Packit 67cb25
  }
Packit 67cb25
ranlxs_state_t;
Packit 67cb25
Packit 67cb25
static void increment_state (ranlxs_state_t * state);
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
increment_state (ranlxs_state_t * state)
Packit 67cb25
{
Packit 67cb25
  int k, kmax, m;
Packit 67cb25
  double x, y1, y2, y3;
Packit 67cb25
Packit 67cb25
  float *xflt = state->xflt;
Packit 67cb25
  double *xdbl = state->xdbl;
Packit 67cb25
  double *ydbl = state->ydbl;
Packit 67cb25
  double carry = state->carry;
Packit 67cb25
  unsigned int ir = state->ir;
Packit 67cb25
  unsigned int jr = state->jr;
Packit 67cb25
Packit 67cb25
  for (k = 0; ir > 0; ++k)
Packit 67cb25
    {
Packit 67cb25
      y1 = xdbl[jr] - xdbl[ir];
Packit 67cb25
      y2 = y1 - carry;
Packit 67cb25
      if (y2 < 0)
Packit 67cb25
        {
Packit 67cb25
          carry = one_bit;
Packit 67cb25
          y2 += 1;
Packit 67cb25
        }
Packit 67cb25
      else
Packit 67cb25
        {
Packit 67cb25
          carry = 0;
Packit 67cb25
        }
Packit 67cb25
      xdbl[ir] = y2;
Packit 67cb25
      ir = next[ir];
Packit 67cb25
      jr = next[jr];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  kmax = state->pr - 12;
Packit 67cb25
Packit 67cb25
  for (; k <= kmax; k += 12)
Packit 67cb25
    {
Packit 67cb25
      y1 = xdbl[7] - xdbl[0];
Packit 67cb25
      y1 -= carry;
Packit 67cb25
Packit 67cb25
      RANLUX_STEP (y2, y1, 8, 1, 0);
Packit 67cb25
      RANLUX_STEP (y3, y2, 9, 2, 1);
Packit 67cb25
      RANLUX_STEP (y1, y3, 10, 3, 2);
Packit 67cb25
      RANLUX_STEP (y2, y1, 11, 4, 3);
Packit 67cb25
      RANLUX_STEP (y3, y2, 0, 5, 4);
Packit 67cb25
      RANLUX_STEP (y1, y3, 1, 6, 5);
Packit 67cb25
      RANLUX_STEP (y2, y1, 2, 7, 6);
Packit 67cb25
      RANLUX_STEP (y3, y2, 3, 8, 7);
Packit 67cb25
      RANLUX_STEP (y1, y3, 4, 9, 8);
Packit 67cb25
      RANLUX_STEP (y2, y1, 5, 10, 9);
Packit 67cb25
      RANLUX_STEP (y3, y2, 6, 11, 10);
Packit 67cb25
Packit 67cb25
      if (y3 < 0)
Packit 67cb25
        {
Packit 67cb25
          carry = one_bit;
Packit 67cb25
          y3 += 1;
Packit 67cb25
        }
Packit 67cb25
      else
Packit 67cb25
        {
Packit 67cb25
          carry = 0;
Packit 67cb25
        }
Packit 67cb25
      xdbl[11] = y3;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  kmax = state->pr;
Packit 67cb25
Packit 67cb25
  for (; k < kmax; ++k)
Packit 67cb25
    {
Packit 67cb25
      y1 = xdbl[jr] - xdbl[ir];
Packit 67cb25
      y2 = y1 - carry;
Packit 67cb25
      if (y2 < 0)
Packit 67cb25
        {
Packit 67cb25
          carry = one_bit;
Packit 67cb25
          y2 += 1;
Packit 67cb25
        }
Packit 67cb25
      else
Packit 67cb25
        {
Packit 67cb25
          carry = 0;
Packit 67cb25
        }
Packit 67cb25
      xdbl[ir] = y2;
Packit 67cb25
      ydbl[ir] = y2 + shift;
Packit 67cb25
      ir = next[ir];
Packit 67cb25
      jr = next[jr];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  ydbl[ir] = xdbl[ir] + shift;
Packit 67cb25
Packit 67cb25
  for (k = next[ir]; k > 0;)
Packit 67cb25
    {
Packit 67cb25
      ydbl[k] = xdbl[k] + shift;
Packit 67cb25
      k = next[k];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (k = 0, m = 0; k < 12; ++k)
Packit 67cb25
    {
Packit 67cb25
      x = xdbl[k];
Packit 67cb25
      y2 = ydbl[k] - shift;
Packit 67cb25
      if (y2 > x)
Packit 67cb25
        y2 -= sone_bit;
Packit 67cb25
      y1 = (x - y2) * sbase;
Packit 67cb25
Packit 67cb25
      xflt[m++] = (float) y1;
Packit 67cb25
      xflt[m++] = (float) y2;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  state->ir = ir;
Packit 67cb25
  state->is = 2 * ir;
Packit 67cb25
  state->is_old = 2 * ir;
Packit 67cb25
  state->jr = jr;
Packit 67cb25
  state->carry = carry;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
static inline double
Packit 67cb25
ranlxs_get_double (void *vstate)
Packit 67cb25
{
Packit 67cb25
  ranlxs_state_t *state = (ranlxs_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  const unsigned int is = snext[state->is];
Packit 67cb25
Packit 67cb25
  state->is = is;
Packit 67cb25
Packit 67cb25
  if (is == state->is_old)
Packit 67cb25
    increment_state (state);
Packit 67cb25
Packit 67cb25
  return state->xflt[state->is];
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static unsigned long int
Packit 67cb25
ranlxs_get (void *vstate)
Packit 67cb25
{
Packit 67cb25
  return ranlxs_get_double (vstate) * 16777216.0;       /* 2^24 */
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
ranlxs_set_lux (void *vstate, unsigned long int s, unsigned int luxury)
Packit 67cb25
{
Packit 67cb25
  ranlxs_state_t *state = (ranlxs_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  int ibit, jbit, i, k, m, xbit[31];
Packit 67cb25
  double x, y;
Packit 67cb25
Packit 67cb25
  long int seed;
Packit 67cb25
Packit 67cb25
  if (s == 0)
Packit 67cb25
    s = 1;                      /* default seed is 1 */
Packit 67cb25
Packit 67cb25
  seed = s;
Packit 67cb25
Packit 67cb25
  i = seed & 0x7FFFFFFFUL;  /* Allowed seeds for ranlxs are 0 .. 2^31-1 */
Packit 67cb25
Packit 67cb25
  for (k = 0; k < 31; ++k)
Packit 67cb25
    {
Packit 67cb25
      xbit[k] = i % 2;
Packit 67cb25
      i /= 2;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  ibit = 0;
Packit 67cb25
  jbit = 18;
Packit 67cb25
Packit 67cb25
  for (k = 0; k < 12; ++k)
Packit 67cb25
    {
Packit 67cb25
      x = 0;
Packit 67cb25
Packit 67cb25
      for (m = 1; m <= 48; ++m)
Packit 67cb25
        {
Packit 67cb25
          y = (double) xbit[ibit];
Packit 67cb25
          x += x + y;
Packit 67cb25
          xbit[ibit] = (xbit[ibit] + xbit[jbit]) % 2;
Packit 67cb25
          ibit = (ibit + 1) % 31;
Packit 67cb25
          jbit = (jbit + 1) % 31;
Packit 67cb25
        }
Packit 67cb25
      state->xdbl[k] = one_bit * x;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  state->carry = 0;
Packit 67cb25
  state->ir = 0;
Packit 67cb25
  state->jr = 7;
Packit 67cb25
  state->is = 23;
Packit 67cb25
  state->is_old = 0;
Packit 67cb25
  state->pr = luxury;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
ranlxs0_set (void *vstate, unsigned long int s)
Packit 67cb25
{
Packit 67cb25
  ranlxs_set_lux (vstate, s, 109);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
void
Packit 67cb25
ranlxs1_set (void *vstate, unsigned long int s)
Packit 67cb25
{
Packit 67cb25
  ranlxs_set_lux (vstate, s, 202);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
ranlxs2_set (void *vstate, unsigned long int s)
Packit 67cb25
{
Packit 67cb25
  ranlxs_set_lux (vstate, s, 397);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
static const gsl_rng_type ranlxs0_type =
Packit 67cb25
{"ranlxs0",                     /* name */
Packit 67cb25
 0x00ffffffUL,                  /* RAND_MAX */
Packit 67cb25
 0,                             /* RAND_MIN */
Packit 67cb25
 sizeof (ranlxs_state_t),
Packit 67cb25
 &ranlxs0_set,
Packit 67cb25
 &ranlxs_get,
Packit 67cb25
 &ranlxs_get_double};
Packit 67cb25
Packit 67cb25
static const gsl_rng_type ranlxs1_type =
Packit 67cb25
{"ranlxs1",                     /* name */
Packit 67cb25
 0x00ffffffUL,                  /* RAND_MAX */
Packit 67cb25
 0,                             /* RAND_MIN */
Packit 67cb25
 sizeof (ranlxs_state_t),
Packit 67cb25
 &ranlxs1_set,
Packit 67cb25
 &ranlxs_get,
Packit 67cb25
 &ranlxs_get_double};
Packit 67cb25
Packit 67cb25
static const gsl_rng_type ranlxs2_type =
Packit 67cb25
{"ranlxs2",                     /* name */
Packit 67cb25
 0x00ffffffUL,                  /* RAND_MAX */
Packit 67cb25
 0,                             /* RAND_MIN */
Packit 67cb25
 sizeof (ranlxs_state_t),
Packit 67cb25
 &ranlxs2_set,
Packit 67cb25
 &ranlxs_get,
Packit 67cb25
 &ranlxs_get_double};
Packit 67cb25
Packit 67cb25
const gsl_rng_type *gsl_rng_ranlxs0 = &ranlxs0_type;
Packit 67cb25
const gsl_rng_type *gsl_rng_ranlxs1 = &ranlxs1_type;
Packit 67cb25
const gsl_rng_type *gsl_rng_ranlxs2 = &ranlxs2_type;