Blame rng/tt.c

Packit 67cb25
/* rng/tt.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 the TT800 twisted GSFR generator for 32 bit integers. It
Packit 67cb25
   has been superceded by MT19937 (mt.c). The period is 2^800.
Packit 67cb25
Packit 67cb25
   This implementation is based on tt800.c, July 8th 1996 version by
Packit 67cb25
   M. Matsumoto, email: matumoto@math.keio.ac.jp
Packit 67cb25
Packit 67cb25
   From: Makoto Matsumoto and Yoshiharu Kurita, "Twisted GFSR
Packit 67cb25
   Generators II", ACM Transactions on Modelling and Computer
Packit 67cb25
   Simulation, Vol. 4, No. 3, 1994, pages 254-266. */
Packit 67cb25
Packit 67cb25
static inline unsigned long int tt_get (void *vstate);
Packit 67cb25
static double tt_get_double (void *vstate);
Packit 67cb25
static void tt_set (void *state, unsigned long int s);
Packit 67cb25
Packit 67cb25
#define N 25
Packit 67cb25
#define M 7
Packit 67cb25
Packit 67cb25
typedef struct
Packit 67cb25
  {
Packit 67cb25
    int n;
Packit 67cb25
    unsigned long int x[N];
Packit 67cb25
  }
Packit 67cb25
tt_state_t;
Packit 67cb25
Packit 67cb25
static inline unsigned long int
Packit 67cb25
tt_get (void *vstate)
Packit 67cb25
{
Packit 67cb25
  tt_state_t *state = (tt_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  /* this is the magic vector, a */
Packit 67cb25
Packit 67cb25
  const unsigned long mag01[2] =
Packit 67cb25
  {0x00000000, 0x8ebfd028UL};
Packit 67cb25
  unsigned long int y;
Packit 67cb25
  unsigned long int *const x = state->x;
Packit 67cb25
  int n = state->n;
Packit 67cb25
Packit 67cb25
  if (n >= N)
Packit 67cb25
    {
Packit 67cb25
      int i;
Packit 67cb25
      for (i = 0; i < N - M; i++)
Packit 67cb25
        {
Packit 67cb25
          x[i] = x[i + M] ^ (x[i] >> 1) ^ mag01[x[i] % 2];
Packit 67cb25
        }
Packit 67cb25
      for (; i < N; i++)
Packit 67cb25
        {
Packit 67cb25
          x[i] = x[i + (M - N)] ^ (x[i] >> 1) ^ mag01[x[i] % 2];
Packit 67cb25
        };
Packit 67cb25
      n = 0;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  y = x[n];
Packit 67cb25
  y ^= (y << 7) & 0x2b5b2500UL;         /* s and b, magic vectors */
Packit 67cb25
  y ^= (y << 15) & 0xdb8b0000UL;        /* t and c, magic vectors */
Packit 67cb25
  y &= 0xffffffffUL;    /* you may delete this line if word size = 32 */
Packit 67cb25
Packit 67cb25
  /* The following line was added by Makoto Matsumoto in the 1996
Packit 67cb25
     version to improve lower bit's correlation.  Delete this line
Packit 67cb25
     to use the code published in 1994.  */
Packit 67cb25
Packit 67cb25
  y ^= (y >> 16);       /* added to the 1994 version */
Packit 67cb25
Packit 67cb25
  state->n = n + 1;
Packit 67cb25
Packit 67cb25
  return y;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static double
Packit 67cb25
tt_get_double (void * vstate)
Packit 67cb25
{
Packit 67cb25
  return tt_get (vstate) / 4294967296.0 ;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
tt_set (void *vstate, unsigned long int s)
Packit 67cb25
{
Packit 67cb25
  tt_state_t *state = (tt_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  const tt_state_t init_state =
Packit 67cb25
  {0,
Packit 67cb25
   {0x95f24dabUL, 0x0b685215UL, 0xe76ccae7UL,
Packit 67cb25
    0xaf3ec239UL, 0x715fad23UL, 0x24a590adUL,
Packit 67cb25
    0x69e4b5efUL, 0xbf456141UL, 0x96bc1b7bUL,
Packit 67cb25
    0xa7bdf825UL, 0xc1de75b7UL, 0x8858a9c9UL,
Packit 67cb25
    0x2da87693UL, 0xb657f9ddUL, 0xffdc8a9fUL,
Packit 67cb25
    0x8121da71UL, 0x8b823ecbUL, 0x885d05f5UL,
Packit 67cb25
    0x4e20cd47UL, 0x5a9ad5d9UL, 0x512c0c03UL,
Packit 67cb25
    0xea857ccdUL, 0x4cc1d30fUL, 0x8891a8a1UL,
Packit 67cb25
    0xa6b7aadbUL}};
Packit 67cb25
Packit 67cb25
Packit 67cb25
  if (s == 0)   /* default seed is given explicitly in the original code */
Packit 67cb25
    {
Packit 67cb25
      *state = init_state;
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      int i;
Packit 67cb25
Packit 67cb25
      state->n = 0;
Packit 67cb25
Packit 67cb25
      state->x[0] = s & 0xffffffffUL;
Packit 67cb25
Packit 67cb25
      for (i = 1; i < N; i++)
Packit 67cb25
        state->x[i] = (69069 * state->x[i - 1]) & 0xffffffffUL;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static const gsl_rng_type tt_type =
Packit 67cb25
{"tt800",                       /* name */
Packit 67cb25
 0xffffffffUL,                  /* RAND_MAX */
Packit 67cb25
 0,                             /* RAND_MIN */
Packit 67cb25
 sizeof (tt_state_t),
Packit 67cb25
 &tt_set,
Packit 67cb25
 &tt_get,
Packit 67cb25
 &tt_get_double};
Packit 67cb25
Packit 67cb25
const gsl_rng_type *gsl_rng_tt800 = &tt_type;