Added MACS source
[htsworkflow.git] / htswanalysis / MACS / lib / gsl / gsl-1.11 / rng / ranlux.c
1 /* rng/ranlux.c
2  * 
3  * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 James Theiler, Brian Gough
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <gsl/gsl_rng.h>
23
24 /* This is a lagged fibonacci generator with skipping developed by Luescher.
25    The sequence is a series of 24-bit integers, x_n, 
26
27    x_n = d_n + b_n
28
29    where d_n = x_{n-10} - x_{n-24} - c_{n-1}, b_n = 0 if d_n >= 0 and
30    b_n = 2^24 if d_n < 0, c_n = 0 if d_n >= 0 and c_n = 1 if d_n < 0,
31    where after 24 samples a group of p integers are "skipped", to
32    reduce correlations. By default p = 199, but can be increased to
33    365.
34
35    The period of the generator is around 10^171. 
36
37    From: M. Luescher, "A portable high-quality random number generator
38    for lattice field theory calculations", Computer Physics
39    Communications, 79 (1994) 100-110.
40
41    Available on the net as hep-lat/9309020 at http://xxx.lanl.gov/
42
43    See also,
44
45    F. James, "RANLUX: A Fortran implementation of the high-quality
46    pseudo-random number generator of Luscher", Computer Physics
47    Communications, 79 (1994) 111-114
48
49    Kenneth G. Hamilton, F. James, "Acceleration of RANLUX", Computer
50    Physics Communications, 101 (1997) 241-248
51
52    Kenneth G. Hamilton, "Assembler RANLUX for PCs", Computer Physics
53    Communications, 101 (1997) 249-253  */
54
55 static inline unsigned long int ranlux_get (void *vstate);
56 static double ranlux_get_double (void *vstate);
57 static void ranlux_set_lux (void *state, unsigned long int s, unsigned int luxury);
58 static void ranlux_set (void *state, unsigned long int s);
59 static void ranlux389_set (void *state, unsigned long int s);
60
61 static const unsigned long int mask_lo = 0x00ffffffUL;  /* 2^24 - 1 */
62 static const unsigned long int mask_hi = ~0x00ffffffUL;
63 static const unsigned long int two24 = 16777216;        /* 2^24 */
64
65 typedef struct
66   {
67     unsigned int i;
68     unsigned int j;
69     unsigned int n;
70     unsigned int skip;
71     unsigned int carry;
72     unsigned long int u[24];
73   }
74 ranlux_state_t;
75
76 static inline unsigned long int increment_state (ranlux_state_t * state);
77
78 static inline unsigned long int
79 increment_state (ranlux_state_t * state)
80 {
81   unsigned int i = state->i;
82   unsigned int j = state->j;
83   long int delta = state->u[j] - state->u[i] - state->carry;
84
85   if (delta & mask_hi)
86     {
87       state->carry = 1;
88       delta &= mask_lo;
89     }
90   else
91     {
92       state->carry = 0;
93     }
94
95   state->u[i] = delta;
96
97   if (i == 0)
98     {
99       i = 23;
100     }
101   else
102     {
103       i--;
104     }
105
106   state->i = i;
107
108   if (j == 0)
109     {
110       j = 23;
111     }
112   else
113     {
114       j--;
115     }
116
117   state->j = j;
118
119   return delta;
120 }
121
122 static inline unsigned long int
123 ranlux_get (void *vstate)
124 {
125   ranlux_state_t *state = (ranlux_state_t *) vstate;
126   const unsigned int skip = state->skip;
127   unsigned long int r = increment_state (state);
128
129   state->n++;
130
131   if (state->n == 24)
132     {
133       unsigned int i;
134       state->n = 0;
135       for (i = 0; i < skip; i++)
136         increment_state (state);
137     }
138
139   return r;
140 }
141
142 static double
143 ranlux_get_double (void *vstate)
144 {
145   return ranlux_get (vstate) / 16777216.0;
146 }
147
148 static void
149 ranlux_set_lux (void *vstate, unsigned long int s, unsigned int luxury)
150 {
151   ranlux_state_t *state = (ranlux_state_t *) vstate;
152   int i;
153
154   long int seed;
155
156   if (s == 0)
157     s = 314159265;      /* default seed is 314159265 */
158
159   seed = s;
160
161   /* This is the initialization algorithm of F. James, widely in use
162      for RANLUX. */
163
164   for (i = 0; i < 24; i++)
165     {
166       unsigned long int k = seed / 53668;
167       seed = 40014 * (seed - k * 53668) - k * 12211;
168       if (seed < 0)
169         {
170           seed += 2147483563;
171         }
172       state->u[i] = seed % two24;
173     }
174
175   state->i = 23;
176   state->j = 9;
177   state->n = 0;
178   state->skip = luxury - 24;
179
180   if (state->u[23] & mask_hi)
181     {
182       state->carry = 1;
183     }
184   else
185     {
186       state->carry = 0;
187     }
188 }
189
190 static void
191 ranlux_set (void *vstate, unsigned long int s)
192 {
193   ranlux_set_lux (vstate, s, 223);
194 }
195
196 static void
197 ranlux389_set (void *vstate, unsigned long int s)
198 {
199   ranlux_set_lux (vstate, s, 389);
200 }
201
202
203 static const gsl_rng_type ranlux_type =
204 {"ranlux",                      /* name */
205  0x00ffffffUL,                  /* RAND_MAX */
206  0,                             /* RAND_MIN */
207  sizeof (ranlux_state_t),
208  &ranlux_set,
209  &ranlux_get,
210  &ranlux_get_double};
211
212 static const gsl_rng_type ranlux389_type =
213 {"ranlux389",                   /* name */
214  0x00ffffffUL,                  /* RAND_MAX */
215  0,                             /* RAND_MIN */
216  sizeof (ranlux_state_t),
217  &ranlux389_set,
218  &ranlux_get,
219  &ranlux_get_double};
220
221 const gsl_rng_type *gsl_rng_ranlux = &ranlux_type;
222 const gsl_rng_type *gsl_rng_ranlux389 = &ranlux389_type;