CAEN Utility  2.0.2
Utilities for CAEN projects
CAENRandom.c
Go to the documentation of this file.
1 /******************************************************************************
2 *
3 * CAEN SpA - Software Division
4 * Via Vetraia, 11 - 55049 - Viareggio ITALY
5 * +39 0594 388 398 - www.caen.it
6 *
7 *******************************************************************************
8 *
9 * Copyright (C) 2019-2022 CAEN SpA
10 *
11 * This file is part of the CAEN Utility.
12 *
13 * The CAEN Utility is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 3 of the License, or (at your option) any later version.
17 *
18 * The CAEN Utility is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with the CAEN Utility; if not, see
25 * https://www.gnu.org/licenses/.
26 *
27 * SPDX-License-Identifier: LGPL-3.0-or-later
28 *
29 ***************************************************************************/
37 #include <CAENRandom.h>
38 
39 #include <math.h>
40 #include <inttypes.h>
41 
42 #include <CAENLogger.h>
43 #include <CAENMultiplatform.h>
44 
45 INIT_C_LOGGER("CAENRandomLog.txt", "CAENRandom.c");
46 
47 /*
48  * The code is partially inspired from ROOT MathCore Library TRandom3,
49  * developed by Peter Malzacher and released under GNU LGPL 2 (or any later).
50  */
51 
52 /*
53 * Types used by this generator
54 */
57  bool seeded;
58 };
59 
60 struct _librarystate {
61  struct _initializedstuff v32;
62  struct _initializedstuff v64;
63 };
64 
65 struct _statevector {
66  uint32_t *v32;
67  uint64_t *v64;
68 };
69 
70 struct _integer {
71  uint32_t v32;
72  uint64_t v64;
73 };
74 
76  struct _statevector vector;
77  struct _integer index;
78 };
79 
80 /*
81 * Internal state
82 */
83 static struct _librarystate lState;
84 static struct _internalstate iState;
85 
86 /*
87 * Generator constants
88 */
90 static const struct _integer kW = {
91  UINT32_C(32),
92  UINT64_C(64)
93 };
94 
96 static const struct _integer kM = {
97  UINT32_C(397),
98  UINT64_C(156)
99 };
100 
102 static const struct _integer kN = {
103  UINT32_C(624),
104  UINT64_C(312)
105 };
106 
108 static const struct _integer kA = {
109  UINT32_C(0x9908b0df),
110  UINT64_C(0xb5026f5aa96619e9)
111 };
112 
114 static const struct _integer kB = {
115  UINT32_C(0x9d2c5680),
116  UINT64_C(0x71d67fffeda60000)
117 };
118 
120 static const struct _integer kC = {
121  UINT32_C(0xefc60000),
122  UINT64_C(0xfff7eee000000000)
123 };
124 
126 static const struct _integer kD = {
127  UINT32_C(0xffffffff),
128  UINT64_C(0x5555555555555555)
129 };
130 
132 static const struct _integer kS = {
133  UINT32_C(7),
134  UINT64_C(17)
135 };
136 
138 static const struct _integer kT = {
139  UINT32_C(15),
140  UINT64_C(37)
141 };
142 
144 static const struct _integer kU = {
145  UINT32_C(11),
146  UINT64_C(29)
147 };
148 
150 static const struct _integer kL = {
151  UINT32_C(18),
152  UINT64_C(43)
153 };
154 
156 static const struct _integer kF = {
157  UINT32_C(1812433253),
158  UINT64_C(6364136223846793005)
159 };
160 
162 static const struct _integer kDefaultSeed = {
163  UINT32_C(5489),
164  UINT64_C(5489)
165 };
166 
168 static const struct _integer kLowerMask = {
169  UINT32_C(0x7fffffff),
170  UINT64_C(0x7fffffff)
171 };
172 
173 int32_t c_rand32_init(void) {
174  if (lState.v32.initialized)
176 
177  // Initialize memory for the state vector
178  iState.vector.v32 = c_malloc(sizeof(*iState.vector.v32) * (size_t)kN.v32);
179  if (iState.vector.v32 == NULL) {
180  logMsg(c_logger_Severity_ERROR, "%s(): state vector allocation failed.", __func__);
182  }
183 
185 
187 }
188 
189 void c_rand32_deinit(void) {
190  if (!lState.v32.initialized)
191  return;
195  iState.vector.v32 = NULL;
196  iState.index.v32 = 0;
197 }
198 
199 int32_t c_rand64_init(void) {
200  if (lState.v64.initialized)
202 
203  // Initialize memory for the state vector
204  iState.vector.v64 = c_malloc(sizeof(*iState.vector.v64) * (size_t)kN.v64);
205  if (iState.vector.v64 == NULL) {
206  logMsg(c_logger_Severity_ERROR, "%s(): state vector allocation failed.", __func__);
208  }
209 
211 
213 }
214 
215 void c_rand64_deinit(void) {
216  if (!lState.v64.initialized)
217  return;
221  iState.vector.v64 = NULL;
222  iState.index.v64 = 0;
223 }
224 
225 void c_rand32_seed(uint32_t seed) {
226  // Check if initialized.
227  if (!lState.v32.initialized) {
228  logMsg(c_logger_Severity_WARNING, "%s(): generator not initialized. Calling c_rand32_init() and continuing...", __func__);
229  c_rand32_init();
230  }
231 
232  uint32_t prev = iState.vector.v32[0] = seed;
233  for (uint32_t i = 1; i < kN.v32; ++i)
234  prev = iState.vector.v32[i] = (i + kF.v32 * (prev ^ (prev >> (kW.v32 - 2))));
235 
236  iState.index.v32 = kN.v32;
237  lState.v32.seeded = TRUE;
238 }
239 
240 void c_rand64_seed(uint64_t seed) {
241  // Check if initialized.
242  if (!lState.v64.initialized) {
243  logMsg(c_logger_Severity_WARNING, "%s(): generator not initialized. Calling c_rand64_init() and continuing...", __func__);
244  c_rand64_init();
245  }
246 
247  uint64_t prev = iState.vector.v64[0] = seed;
248  for (uint64_t i = 1; i < kN.v64; ++i)
249  prev = iState.vector.v64[i] = (i + kF.v64 * (prev ^ (prev >> (kW.v64 - 2))));
250 
251  iState.index.v64 = kN.v64;
252  lState.v64.seeded = TRUE;
253 }
254 
255 static void _twist32(void) {
256  uint32_t i = 0;
257 
258  for (; i < kN.v32 - kM.v32; ++i) {
259  uint32_t tmp = (iState.vector.v32[i] & ~kLowerMask.v32) | (iState.vector.v32[i + 1] & kLowerMask.v32);
260  iState.vector.v32[i] = iState.vector.v32[i + kM.v32] ^ (tmp >> 1) ^ ((tmp & 1) ? kA.v32 : 0);
261  }
262 
263  for (; i < kN.v32 - 1; ++i) {
264  uint32_t tmp = (iState.vector.v32[i] & ~kLowerMask.v32) | (iState.vector.v32[i + 1] & kLowerMask.v32);
265  iState.vector.v32[i] = iState.vector.v32[i + kM.v32 - kN.v32] ^ (tmp >> 1) ^ ((tmp & 1) ? kA.v32 : 0);
266  }
267 
268  uint32_t tmp = (iState.vector.v32[kN.v32 - 1] & ~kLowerMask.v32) | (iState.vector.v32[0] & kLowerMask.v32);
269  iState.vector.v32[kN.v32 - 1] = iState.vector.v32[kM.v32 - 1] ^ (tmp >> 1) ^ ((tmp & 1) ? kA.v32 : 0);
270 
271  iState.index.v32 = 0;
272 }
273 
274 static void _twist64(void) {
275  uint64_t i = 0;
276 
277  for (; i < kN.v64 - kM.v64; ++i) {
278  uint64_t tmp = (iState.vector.v64[i] & ~kLowerMask.v64) | (iState.vector.v64[i + 1] & kLowerMask.v64);
279  iState.vector.v64[i] = iState.vector.v64[i + kM.v64] ^ (tmp >> 1) ^ ((tmp & 1) ? kA.v64 : 0);
280  }
281 
282  for (; i < kN.v64 - 1; ++i) {
283  uint64_t tmp = (iState.vector.v64[i] & ~kLowerMask.v64) | (iState.vector.v64[i + 1] & kLowerMask.v64);
284  iState.vector.v64[i] = iState.vector.v64[i + kM.v64 - kN.v64] ^ (tmp >> 1) ^ ((tmp & 1) ? kA.v64 : 0);
285  }
286 
287  uint64_t tmp = (iState.vector.v64[kN.v64 - 1] & ~kLowerMask.v64) | (iState.vector.v64[0] & kLowerMask.v64);
288  iState.vector.v64[kN.v64 - 1] = iState.vector.v64[kM.v64 - 1] ^ (tmp >> 1) ^ ((tmp & 1) ? kA.v64 : 0);
289 
290  iState.index.v64 = 0;
291 }
292 
294  if (c_unlikely(!lState.v32.seeded)) {
295  logMsg(c_logger_Severity_WARNING, "%s(): generator not seeded. Calling c_rand32_seed() with default seed %"PRIu32" and continuing...", __func__, kDefaultSeed.v32);
296  c_rand32_seed(kDefaultSeed.v32);
297  }
298 
299  // Twist
300  if (c_unlikely(iState.index.v32 >= kN.v32))
301  _twist32();
302 
303  uint32_t y = iState.vector.v32[iState.index.v32++];
304  y ^= (y >> kU.v32) & kD.v32;
305  y ^= (y << kS.v32) & kB.v32;
306  y ^= (y << kT.v32) & kC.v32;
307  y ^= (y >> kL.v32);
308 
309  return y;
310 }
311 
313  if (c_unlikely(!lState.v64.seeded)) {
314  logMsg(c_logger_Severity_WARNING, "%s(): generator not seeded. Calling c_rand64_seed() with default seed %"PRIu64" and continuing...", __func__, kDefaultSeed.v64);
315  c_rand64_seed(kDefaultSeed.v64);
316  }
317 
318  // Twist
319  if (c_unlikely(iState.index.v64 >= kN.v64))
320  _twist64();
321 
322  uint64_t y = iState.vector.v64[iState.index.v64++];
323  y ^= (y >> kU.v64) & kD.v64;
324  y ^= (y << kS.v64) & kB.v64;
325  y ^= (y << kT.v64) & kC.v64;
326  y ^= (y >> kL.v64);
327 
328  return y;
329 }
330 
332  const double twom32 = 0x1p-32;
333  return c_rand32_int() * twom32;
334 }
335 
337  const double twom64 = 0x1p-64;
338  return c_rand64_int() * twom64;
339 }
340 
342  static bool valid = FALSE;
343  static double res_next = 0.;
344  double res_this;
345 
346  if (!valid) {
347  double u, v, s;
348 
349  do {
350  // get a point in the unit circle
351  u = fma(2., c_rand64(), -1.);
352  v = fma(2., c_rand64(), -1.);
353  s = u * u + v * v;
354  } while (s > 1.);
355 
356  const double f = sqrt(-2. * log(s) / s);
357 
358  // save second value for next call
359  res_this = f * u;
360  res_next = f * v;
361  valid = TRUE;
362  }
363  else {
364  res_this = res_next;
365  valid = FALSE;
366  }
367 
368  return res_this;
369 }
uint32_t v32
Definition: CAENRandom.c:71
struct _initializedstuff v32
Definition: CAENRandom.c:61
static const struct _integer kD
The XOR mask used as parameter d in the tempering process of the generation algorithm.
Definition: CAENRandom.c:126
static const struct _integer kA
The XOR mask applied as the linear function on each twist.
Definition: CAENRandom.c:108
static struct _internalstate iState
Internal state.
Definition: CAENRandom.c:84
void c_free(void *ptr)
static struct _librarystate lState
Library state.
Definition: CAENRandom.c:83
static const struct _integer kDefaultSeed
The default seed used on construction or seeding.
Definition: CAENRandom.c:162
int32_t c_rand64_init(void)
Definition: CAENRandom.c:199
void c_rand32_seed(uint32_t seed)
Definition: CAENRandom.c:225
static const struct _integer kC
The XOR mask used as parameter c in the tempering process of the generation algorithm.
Definition: CAENRandom.c:120
void c_rand32_deinit(void)
Definition: CAENRandom.c:189
static const struct _integer kS
The shift size of parameter s used in the tempering process of the generation algorithm.
Definition: CAENRandom.c:132
uint64_t c_rand64_int(void)
Definition: CAENRandom.c:312
uint32_t c_rand32_int(void)
Definition: CAENRandom.c:293
static const struct _integer kLowerMask
The mask with 31 1&#39;s, where 31 is the number of bits that mark the separation point of words on each ...
Definition: CAENRandom.c:168
static const struct _integer kF
The initialization multiplier used to seed the state sequence when a single value is used as seed...
Definition: CAENRandom.c:156
int32_t c_rand32_init(void)
Definition: CAENRandom.c:173
static const struct _integer kU
The shift size of parameter u used in the tempering process of the generation algorithm.
Definition: CAENRandom.c:144
#define c_unlikely(x)
Definition: CAENUtility.h:293
static const struct _integer kT
The shift size of parameter t used in the tempering process of the generation algorithm.
Definition: CAENRandom.c:138
double c_rand(void)
Definition: CAENRandom.c:331
#define TRUE
#define FALSE
void * c_malloc(size_t size)
static const struct _integer kB
The XOR mask used as parameter b in the tempering process of the generation algorithm.
Definition: CAENRandom.c:114
Generic wrappers to platform-dependent functions.
static const struct _integer kM
The shift size used on twists to transform the values.
Definition: CAENRandom.c:96
double c_rand64_normal(void)
Definition: CAENRandom.c:341
uint32_t * v32
Definition: CAENRandom.c:66
#define INIT_C_LOGGER(fname, mname)
Definition: CAENLogger.h:139
static const struct _integer kW
The number of bits of each word in the state sequence.
Definition: CAENRandom.c:90
struct _integer index
Definition: CAENRandom.c:77
void c_rand64_deinit(void)
Definition: CAENRandom.c:215
Pseudo-random number generator implemented on MT19937.
Logger implemented in C.
#define logMsg(s,...)
Definition: CAENLogger.h:157
struct _initializedstuff v64
Definition: CAENRandom.c:62
static void _twist64(void)
Definition: CAENRandom.c:274
#define c_use_decl_annotations
Definition: CAENUtility.h:278
uint64_t v64
Definition: CAENRandom.c:72
void c_rand64_seed(uint64_t seed)
Definition: CAENRandom.c:240
uint64_t * v64
Definition: CAENRandom.c:67
static const struct _integer kN
The number of elements in the state sequence (degree of recurrence).
Definition: CAENRandom.c:102
static const struct _integer kL
The shift size of parameter l used in the tempering process of the generation algorithm.
Definition: CAENRandom.c:150
struct _statevector vector
Definition: CAENRandom.c:76
static void _twist32(void)
Definition: CAENRandom.c:255
double c_rand64(void)
Definition: CAENRandom.c:336