Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RanluxppEngineImpl.cxx
Go to the documentation of this file.
1// @(#)root/mathcore:$Id$
2// Author: Jonas Hahnfeld 11/2020
3
4/*************************************************************************
5 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class ROOT::Math::RanluxppEngine
13Implementation of the RANLUX++ generator
14
15RANLUX++ is an LCG equivalent of RANLUX using 576 bit numbers.
16
17The idea of the generator (such as the initialization method) and the algorithm
18for the modulo operation are described in
19A. Sibidanov, *A revision of the subtract-with-borrow random numbergenerators*,
20*Computer Physics Communications*, 221(2017), 299-303,
21preprint https://arxiv.org/pdf/1705.03123.pdf
22
23The code is loosely based on the Assembly implementation by A. Sibidanov
24available at https://github.com/sibidanov/ranluxpp/.
25
26Compared to the original generator, this implementation contains a fix to ensure
27that the modulo operation of the LCG always returns the smallest value congruent
28to the modulus (based on notes by M. Lüscher). Also, the generator converts the
29LCG state back to RANLUX numbers (implementation based on notes by M. Lüscher).
30This avoids a bias in the generated numbers because the upper bits of the LCG
31state, that is smaller than the modulus \f$ m = 2^{576} - 2^{240} + 1 \f$ (not
32a power of 2!), have a higher probability of being 0 than 1. And finally, this
33implementation draws 48 random bits for each generated floating point number
34(instead of 52 bits as in the original generator) to maintain the theoretical
35properties from understanding the original transition function of RANLUX as a
36chaotic dynamical system.
37*/
38
39#include "Math/RanluxppEngine.h"
40
41#include "ranluxpp/mulmod.h"
42#include "ranluxpp/ranlux_lcg.h"
43
44#include <cassert>
45#include <cstdint>
46
47namespace {
48
49// Variable templates are a feature of C++14, use the older technique of having
50// a static member in a template class.
51
52// The coefficients have been determined using Python, and in parts compared to the values given by Sibidanov.
53//
54// >>> def print_hex(a):
55// ... while a > 0:
56// ... print('{0:#018x}'.format(a & 0xffffffffffffffff))
57// ... a >>= 64
58// ...
59// >>> m = 2 ** 576 - 2 ** 240 + 1
60// >>> a = m - (m - 1) // 2 ** 24
61// >>> kA = pow(a, <w>, m)
62// >>> print_hex(kA)
63
64template <int p>
65struct RanluxppData;
66
67template <>
68struct RanluxppData<24> {
69 static const uint64_t kA[9];
70};
71// Also given by Sibidanov
72const uint64_t RanluxppData<24>::kA[] = {
73 0x0000000000000000, 0x0000000000000000, 0x0000000000010000, 0xfffe000000000000, 0xffffffffffffffff,
74 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffeffffffff, 0xffffffffffffffff,
75};
76
77template <>
78struct RanluxppData<218> {
79 static const uint64_t kA[9];
80};
81const uint64_t RanluxppData<218>::kA[] = {
82 0xf445fffffffffd94, 0xfffffd74ffffffff, 0x000000000ba5ffff, 0xfc76000000000942, 0xfffffaaaffffffff,
83 0x0000000000b0ffff, 0x027b0000000007d1, 0xfffff96000000000, 0xfffffffff8e4ffff,
84};
85
86template <>
87struct RanluxppData<223> {
88 static const uint64_t kA[9];
89};
90// Also given by Sibidanov
91const uint64_t RanluxppData<223>::kA[] = {
92 0x0000000ba6000000, 0x0a00000000094200, 0xffeef0fffffffffa, 0xfffffffe25ffffff, 0x7b0000000007d0ff,
93 0xfff9600000000002, 0xfffffff8e4ffffff, 0xba00000000026cff, 0x00028b000000000b,
94};
95
96template <>
97struct RanluxppData<389> {
98 static const uint64_t kA[9];
99};
100// Also given by Sibidanov
101const uint64_t RanluxppData<389>::kA[] = {
102 0x00002ecac9000000, 0x740000002c389600, 0xb9c8a6ffffffe525, 0xfffff593cfffffff, 0xab0000001e93f2ff,
103 0xe4ab160000000d92, 0xffffdf6604ffffff, 0x020000000b9242ff, 0x0df0600000002ee0,
104};
105
106template <>
107struct RanluxppData<404> {
108 static const uint64_t kA[9];
109};
110const uint64_t RanluxppData<404>::kA[] = {
111 0x2eabffffffc9d08b, 0x00012612ffffff99, 0x0000007c3ebe0000, 0x353600000047bba1, 0xffd3c769ffffffd1,
112 0x0000001ada8bffff, 0x6c30000000463759, 0xffb2a1440000000a, 0xffffffc634beffff,
113};
114
115template <>
116struct RanluxppData<778> {
117 static const uint64_t kA[9];
118};
119const uint64_t RanluxppData<778>::kA[] = {
120 0x872de42d9dca512b, 0xdbf015ea1662f8a0, 0x01f48f0d28482e96, 0x392fca0b3be2ae04, 0xed00881af896ce54,
121 0x14f0a768664013f3, 0x9489f52deb1f7f80, 0x72139804e09c0f37, 0x2146b0bb92a2f9a4,
122};
123
124template <>
125struct RanluxppData<794> {
126 static const uint64_t kA[9];
127};
128const uint64_t RanluxppData<794>::kA[] = {
129 0x428df7227a2ca7c9, 0xde32225faaa74b1a, 0x4b9d965ca1ebd668, 0x78d15f59e58e2aff, 0x240fea15e99d075f,
130 0xfe0b70f2d7b7d169, 0x75a535f4c41d51fb, 0x1a5ef0b7233b93e1, 0xbc787ca783d5d5a9,
131};
132
133template <>
134struct RanluxppData<2048> {
135 static const uint64_t kA[9];
136};
137// Also given by Sibidanov
138const uint64_t RanluxppData<2048>::kA[] = {
139 0xed7faa90747aaad9, 0x4cec2c78af55c101, 0xe64dcb31c48228ec, 0x6d8a15a13bee7cb0, 0x20b2ca60cb78c509,
140 0x256c3d3c662ea36c, 0xff74e54107684ed2, 0x492edfcc0cc8e753, 0xb48c187cf5b22097,
141};
142
143} // end anonymous namespace
144
145namespace ROOT {
146namespace Math {
147
148template <int w, int p, int u>
150 // Needs direct access to private members to initialize its four states.
151 friend class RanluxppCompatEngineLuescherImpl<w, p>;
152
153private:
154 uint64_t fState[9]; ///< RANLUX state of the generator
155 unsigned fCarry; ///< Carry bit of the RANLUX state
156 int fPosition = 0; ///< Current position in bits
157
158 static constexpr const uint64_t *kA = RanluxppData<p>::kA;
159 static constexpr int kMaxPos = (u == 0) ? 9 * 64 : u * w;
160 static_assert(kMaxPos <= 576, "maximum position larger than 576 bits");
161
162 /// Advance with given multiplier
163 void Advance(const uint64_t *a)
164 {
165 uint64_t lcg[9];
166 to_lcg(fState, fCarry, lcg);
167 mulmod(a, lcg);
168 to_ranlux(lcg, fState, fCarry);
169 fPosition = 0;
170 }
171
172 /// Produce next block of random bits
173 void Advance()
174 {
175 Advance(kA);
176 }
177
178 /// Skip 24 RANLUX numbers
179 void Skip24()
180 {
181 Advance(RanluxppData<24>::kA);
182 }
183
184public:
185 /// Return the next random bits, generate a new block if necessary
186 uint64_t NextRandomBits()
187 {
188 if (fPosition + w > kMaxPos) {
189 Advance();
190 }
191
192 int idx = fPosition / 64;
193 int offset = fPosition % 64;
194 int numBits = 64 - offset;
195
196 uint64_t bits = fState[idx] >> offset;
197 if (numBits < w) {
198 bits |= fState[idx + 1] << numBits;
199 }
200 bits &= ((uint64_t(1) << w) - 1);
201
202 fPosition += w;
203 assert(fPosition <= kMaxPos && "position out of range!");
204
205 return bits;
206 }
207
208 /// Return a floating point number, converted from the next random bits.
210 {
211 static constexpr double div = 1.0 / (uint64_t(1) << w);
212 uint64_t bits = NextRandomBits();
213 return bits * div;
214 }
215
216 /// Initialize and seed the state of the generator as in James' implementation
217 void SetSeedJames(uint64_t s)
218 {
219 // Multiplicative Congruential generator using formula constants of L'Ecuyer
220 // as described in "A review of pseudorandom number generators" (Fred James)
221 // published in Computer Physics Communications 60 (1990) pages 329-344.
222 int64_t seed = s;
223 auto next = [&]() {
224 const int a = 0xd1a4, b = 0x9c4e, c = 0x2fb3, d = 0x7fffffab;
225 int64_t k = seed / a;
226 seed = b * (seed - k * a) - k * c ;
227 if (seed < 0) seed += d;
228 return seed & 0xffffff;
229 };
230
231 // Iteration is reversed because the first number from the MCG goes to the
232 // highest position.
233 for (int i = 6; i >= 0; i -= 3) {
234 uint64_t r[8];
235 for (int j = 0; j < 8; j++) {
236 r[j] = next();
237 }
238
239 fState[i+0] = r[7] + (r[6] << 24) + (r[5] << 48);
240 fState[i+1] = (r[5] >> 16) + (r[4] << 8) + (r[3] << 32) + (r[2] << 56);
241 fState[i+2] = (r[2] >> 8) + (r[1] << 16) + (r[0] << 40);
242 }
243 fCarry = !seed;
244
245 Skip24();
246 }
247
248 /// Initialize and seed the state of the generator as in gsl_rng_ranlx*
249 void SetSeedGsl(uint32_t s, bool ranlxd)
250 {
251 if (s == 0) {
252 // The default seed for gsl_rng_ranlx* is 1.
253 s = 1;
254 }
255
256 uint32_t bits = s;
257 auto next_bit = [&]() {
258 int b13 = (bits >> 18) & 0x1;
259 int b31 = bits & 0x1;
260 uint32_t bn = b13 ^ b31;
261 bits = (bn << 30) + (bits >> 1);
262 return b31;
263 };
264 auto next = [&]() {
265 uint64_t ix = 0;
266 for (int i = 0; i < 48; i++) {
267 int iy = next_bit();
268 if (ranlxd) {
269 iy = (iy + 1) % 2;
270 }
271 ix = 2 * ix + iy;
272 }
273 return ix;
274 };
275
276 for (int i = 0; i < 9; i += 3) {
277 uint64_t r[4];
278 for (int j = 0; j < 4; j++) {
279 r[j] = next();
280 }
281
282 fState[i+0] = r[0] + (r[1] << 48);
283 fState[i+1] = (r[1] >> 16) + (r[2] << 32);
284 fState[i+2] = (r[2] >> 32) + (r[3] << 16);
285 }
286
287 fCarry = 0;
288 fPosition = 0;
289 Advance();
290 }
291
292 /// Initialize and seed the state of the generator as proposed by Sibidanov
293 void SetSeedSibidanov(uint64_t s)
294 {
295 uint64_t lcg[9];
296 lcg[0] = 1;
297 for (int i = 1; i < 9; i++) {
298 lcg[i] = 0;
299 }
300
301 uint64_t a_seed[9];
302 // Skip 2 ** 96 states.
303 powermod(kA, a_seed, uint64_t(1) << 48);
304 powermod(a_seed, a_seed, uint64_t(1) << 48);
305 // Skip another s states.
306 powermod(a_seed, a_seed, s);
307 mulmod(a_seed, lcg);
308
309 to_ranlux(lcg, fState, fCarry);
310 fPosition = 0;
311 }
312
313 /// Initialize and seed the state of the generator as described by the C++ standard
314 void SetSeedStd24(uint64_t s)
315 {
316 // Seed LCG with given parameters.
317 uint64_t seed = s;
318 const uint64_t a = 40014, m = 2147483563;
319 auto next = [&]() {
320 seed = (a * seed) % m;
321 return seed & 0xffffff;
322 };
323
324 for (int i = 0; i < 9; i += 3) {
325 uint64_t r[8];
326 for (int j = 0; j < 8; j++) {
327 r[j] = next();
328 }
329
330 fState[i+0] = r[0] + (r[1] << 24) + (r[2] << 48);
331 fState[i+1] = (r[2] >> 16) + (r[3] << 8) + (r[4] << 32) + (r[5] << 56);
332 fState[i+2] = (r[5] >> 8) + (r[6] << 16) + (r[7] << 40);
333 }
334 fCarry = !seed;
335
336 Skip24();
337 }
338
339 /// Initialize and seed the state of the generator as described by the C++ standard
340 void SetSeedStd48(uint64_t s)
341 {
342 // Seed LCG with given parameters.
343 uint64_t seed = s;
344 const uint64_t a = 40014, m = 2147483563;
345 auto next = [&]() {
346 seed = (a * seed) % m;
347 uint64_t result = seed;
348 seed = (a * seed) % m;
349 result += seed << 32;
350 return result & 0xffffffffffff;
351 };
352
353 for (int i = 0; i < 9; i += 3) {
354 uint64_t r[4];
355 for (int j = 0; j < 4; j++) {
356 r[j] = next();
357 }
358
359 fState[i+0] = r[0] + (r[1] << 48);
360 fState[i+1] = (r[1] >> 16) + (r[2] << 32);
361 fState[i+2] = (r[2] >> 32) + (r[3] << 16);
362 }
363 fCarry = !seed;
364
365 Skip24();
366 }
367
368 /// Skip `n` random numbers without generating them
369 void Skip(uint64_t n)
370 {
371 int left = (kMaxPos - fPosition) / w;
372 assert(left >= 0 && "position was out of range!");
373 if (n < (uint64_t)left) {
374 // Just skip the next few entries in the currently available bits.
375 fPosition += n * w;
376 assert(fPosition <= kMaxPos && "position out of range!");
377 return;
378 }
379
380 n -= left;
381 // Need to advance and possibly skip over blocks.
382 int nPerState = kMaxPos / w;
383 int skip = (n / nPerState);
384
385 uint64_t a_skip[9];
386 powermod(kA, a_skip, skip + 1);
387
388 uint64_t lcg[9];
389 to_lcg(fState, fCarry, lcg);
390 mulmod(a_skip, lcg);
391 to_ranlux(lcg, fState, fCarry);
392
393 // Potentially skip numbers in the freshly generated block.
394 int remaining = n - skip * nPerState;
395 assert(remaining >= 0 && "should not end up at a negative position!");
396 fPosition = remaining * w;
397 assert(fPosition <= kMaxPos && "position out of range!");
398 }
399};
400
401template <int p>
403{
404 this->SetSeed(seed);
405}
406
407template <int p>
409
410template <int p>
412{
413 return (*this)();
414}
415
416template <int p>
418{
419 return fImpl->NextRandomFloat();
420}
421
422template <int p>
424{
425 return fImpl->NextRandomBits();
426}
427
428template <int p>
429void RanluxppEngine<p>::SetSeed(uint64_t seed)
430{
431 fImpl->SetSeedSibidanov(seed);
432}
433
434template <int p>
436{
437 fImpl->Skip(n);
438}
439
440template class RanluxppEngine<24>;
441template class RanluxppEngine<2048>;
442
443
444template <int p>
446{
447 this->SetSeed(seed);
448}
449
450template <int p>
452
453template <int p>
455{
456 return (*this)();
457}
458
459template <int p>
461{
462 return fImpl->NextRandomFloat();
463}
464
465template <int p>
467{
468 return fImpl->NextRandomBits();
469}
470
471template <int p>
473{
474 fImpl->SetSeedJames(seed);
475}
476
477template <int p>
479{
480 fImpl->Skip(n);
481}
482
483template class RanluxppCompatEngineJames<223>;
484template class RanluxppCompatEngineJames<389>;
485
486
487template <int p>
489{
490 this->SetSeed(seed);
491}
492
493template <int p>
495
496template <int p>
498{
499 return (*this)();
500}
501
502template <int p>
504{
505 return fImpl->NextRandomFloat();
506}
507
508template <int p>
510{
511 return fImpl->NextRandomBits();
512}
513
514template <int p>
516{
517 fImpl->SetSeedGsl(seed, /*ranlxd=*/false);
518}
519
520template <int p>
522{
523 fImpl->Skip(n);
524}
525
529
530
531template <int p>
533{
534 this->SetSeed(seed);
535}
536
537template <int p>
539
540template <int p>
542{
543 return (*this)();
544}
545
546template <int p>
548{
549 return fImpl->NextRandomFloat();
550}
551
552template <int p>
554{
555 return fImpl->NextRandomBits();
556}
557
558template <int p>
560{
561 fImpl->SetSeedGsl(seed, /*ranlxd=*/true);
562}
563
564template <int p>
566{
567 fImpl->Skip(n);
568}
569
572
573
574template <int w, int p>
576
577private:
578 RanluxppEngineImpl<w, p> fStates[4]; ///< The states of this generator
579 int fNextState = 0; ///< The index of the next state
580
581public:
582 /// Return the next random bits, generate a new block if necessary
583 uint64_t NextRandomBits()
584 {
585 uint64_t bits = fStates[fNextState].NextRandomBits();
586 fNextState = (fNextState + 1) % 4;
587 return bits;
588 }
589
590 /// Return a floating point number, converted from the next random bits.
592 {
593 double number = fStates[fNextState].NextRandomFloat();
594 fNextState = (fNextState + 1) % 4;
595 return number;
596 }
597
598 /// Initialize and seed the state of the generator as in Lüscher's ranlxs
599 void SetSeed(uint32_t s, bool ranlxd)
600 {
601 uint32_t bits = s;
602 auto next_bit = [&]() {
603 int b13 = (bits >> 18) & 0x1;
604 int b31 = bits & 0x1;
605 uint32_t bn = b13 ^ b31;
606 bits = (bn << 30) + (bits >> 1);
607 return b31;
608 };
609 auto next = [&]() {
610 uint64_t ix = 0;
611 for (int l = 0; l < 24; l++) {
612 ix = 2 * ix + next_bit();
613 }
614 return ix;
615 };
616
617 for (int i = 0; i < 4; i++) {
618 auto &state = fStates[i];
619 for (int j = 0; j < 9; j += 3) {
620 uint64_t r[8];
621 for (int m = 0; m < 8; m++) {
622 uint64_t ix = next();
623 // Lüscher's implementation uses k = (j / 3) * 8 + m, so only
624 // the value of m is important for (k % 4).
625 if ((!ranlxd && (m % 4) == i) || (ranlxd && (m % 4) != i)) {
626 ix = 16777215 - ix;
627 }
628 r[m] = ix;
629 }
630
631 state.fState[j+0] = r[0] + (r[1] << 24) + (r[2] << 48);
632 state.fState[j+1] = (r[2] >> 16) + (r[3] << 8) + (r[4] << 32) + (r[5] << 56);
633 state.fState[j+2] = (r[5] >> 8) + (r[6] << 16) + (r[7] << 40);
634 }
635
636 state.fCarry = 0;
637 state.fPosition = 0;
638 state.Advance();
639 }
640
641 fNextState = 0;
642 }
643
644 /// Skip `n` random numbers without generating them
645 void Skip(uint64_t n)
646 {
647 uint64_t nPerState = n / 4;
648 int remainder = n % 4;
649 for (int i = 0; i < 4; i++) {
650 int idx = (fNextState + i) % 4;
651 uint64_t nForThisState = nPerState;
652 if (i < remainder) {
653 nForThisState++;
654 }
655 fStates[idx].Skip(nForThisState);
656 }
657 // Switch the next state according to the remainder.
658 fNextState = (fNextState + remainder) % 4;
659 }
660};
661
662template <int p>
664{
665 this->SetSeed(seed);
666}
667
668template <int p>
670
671template <int p>
673{
674 return (*this)();
675}
676
677template <int p>
679{
680 return fImpl->NextRandomFloat();
681}
682
683template <int p>
685{
686 return fImpl->NextRandomBits();
687}
688
689template <int p>
691{
692 fImpl->SetSeed(seed, /*ranlxd=*/false);
693}
694
695template <int p>
697{
698 fImpl->Skip(n);
699}
700
704
705
706template <int p>
708{
709 this->SetSeed(seed);
710}
711
712template <int p>
714
715template <int p>
717{
718 return (*this)();
719}
720
721template <int p>
723{
724 return fImpl->NextRandomFloat();
725}
726
727template <int p>
729{
730 return fImpl->NextRandomBits();
731}
732
733template <int p>
735{
736 fImpl->SetSeed(seed, /*ranlxd=*/true);
737}
738
739template <int p>
741{
742 fImpl->Skip(n);
743}
744
747
748
750{
751 this->SetSeed(seed);
752}
753
755
757{
758 return (*this)();
759}
760
762{
763 return fImpl->NextRandomFloat();
764}
765
767{
768 return fImpl->NextRandomBits();
769}
770
772{
773 fImpl->SetSeedStd24(seed);
774}
775
777{
778 fImpl->Skip(n);
779}
780
781
783{
784 this->SetSeed(seed);
785}
786
788
790{
791 return (*this)();
792}
793
795{
796 return fImpl->NextRandomFloat();
797}
798
800{
801 return fImpl->NextRandomBits();
802}
803
805{
806 fImpl->SetSeedStd48(seed);
807}
808
810{
811 fImpl->Skip(n);
812}
813
814} // end namespace Math
815} // end namespace ROOT
ROOT::R::TRInterface & r
Definition Object.C:4
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
Compatibility engine for gsl_rng_ranlxd* from the GNU Scientific Library.
uint64_t IntRndm()
Generate a random integer value with 48 bits.
void SetSeed(uint64_t seed)
Initialize and seed the state of the generator.
void Skip(uint64_t n)
Skip n random numbers without generating them.
double Rndm() override
Generate a floating point random number with 48 bits of randomness.
double operator()()
Generate a floating point random number (non-virtual method)
Compatibility engine for gsl_rng_ranlxs* from the GNU Scientific Library.
double operator()()
Generate a floating point random number (non-virtual method)
double Rndm() override
Generate a floating point random number with 24 bits of randomness.
void Skip(uint64_t n)
Skip n random numbers without generating them.
uint64_t IntRndm()
Generate a random integer value with 24 bits.
void SetSeed(uint64_t seed)
Initialize and seed the state of the generator.
double operator()()
Generate a floating point random number (non-virtual method)
void Skip(uint64_t n)
Skip n random numbers without generating them.
void SetSeed(uint64_t seed)
Initialize and seed the state of the generator.
double Rndm() override
Generate a floating point random number with 24 bits of randomness.
uint64_t IntRndm()
Generate a random integer value with 24 bits.
RanluxppCompatEngineJames(uint64_t seed=314159265)
double NextRandomFloat()
Return a floating point number, converted from the next random bits.
uint64_t NextRandomBits()
Return the next random bits, generate a new block if necessary.
void SetSeed(uint32_t s, bool ranlxd)
Initialize and seed the state of the generator as in Lüscher's ranlxs.
void Skip(uint64_t n)
Skip n random numbers without generating them.
Compatibility engine for Lüscher's ranlxd implementation written in C.
uint64_t IntRndm()
Generate a random integer value with 48 bits.
void SetSeed(uint64_t seed)
Initialize and seed the state of the generator.
void Skip(uint64_t n)
Skip n random numbers without generating them.
double Rndm() override
Generate a floating point random number with 48 bits of randomness.
double operator()()
Generate a floating point random number (non-virtual method)
Compatibility engine for Lüscher's ranlxs implementation written in C.
double operator()()
Generate a floating point random number (non-virtual method)
double Rndm() override
Generate a floating point random number with 24 bits of randomness.
void SetSeed(uint64_t seed)
Initialize and seed the state of the generator.
void Skip(uint64_t n)
Skip n random numbers without generating them.
uint64_t IntRndm()
Generate a random integer value with 24 bits.
void Skip(uint64_t n)
Skip n random numbers without generating them.
uint64_t IntRndm()
Generate a random integer value with 24 bits.
double Rndm() override
Generate a floating point random number with 24 bits of randomness.
void SetSeed(uint64_t seed)
Initialize and seed the state of the generator.
double operator()()
Generate a floating point random number (non-virtual method)
void SetSeed(uint64_t seed)
Initialize and seed the state of the generator.
double operator()()
Generate a floating point random number (non-virtual method)
void Skip(uint64_t n)
Skip n random numbers without generating them.
uint64_t IntRndm()
Generate a random integer value with 48 bits.
double Rndm() override
Generate a floating point random number with 48 bits of randomness.
void SetSeedGsl(uint32_t s, bool ranlxd)
Initialize and seed the state of the generator as in gsl_rng_ranlx*.
static constexpr const uint64_t * kA
unsigned fCarry
Carry bit of the RANLUX state.
void SetSeedStd24(uint64_t s)
Initialize and seed the state of the generator as described by the C++ standard.
void SetSeedJames(uint64_t s)
Initialize and seed the state of the generator as in James' implementation.
void Skip(uint64_t n)
Skip n random numbers without generating them.
void SetSeedStd48(uint64_t s)
Initialize and seed the state of the generator as described by the C++ standard.
double NextRandomFloat()
Return a floating point number, converted from the next random bits.
void Advance(const uint64_t *a)
Advance with given multiplier.
void SetSeedSibidanov(uint64_t s)
Initialize and seed the state of the generator as proposed by Sibidanov.
uint64_t NextRandomBits()
Return the next random bits, generate a new block if necessary.
uint64_t fState[9]
RANLUX state of the generator.
int fPosition
Current position in bits.
void Skip24()
Skip 24 RANLUX numbers.
void Advance()
Produce next block of random bits.
Implementation of the RANLUX++ generator.
uint64_t IntRndm()
Generate a random integer value with 48 bits.
double Rndm() override
Generate a double-precision random number with 48 bits of randomness.
void Skip(uint64_t n)
Skip n random numbers without generating them.
void SetSeed(uint64_t seed)
Initialize and seed the state of the generator.
double operator()()
Generate a double-precision random number (non-virtual method)
RanluxppEngine(uint64_t seed=314159265)
const Int_t n
Definition legend1.C:16
static void mulmod(const uint64_t *in1, uint64_t *inout)
Combine multiply9x9 and mod_m with internal temporary storage.
Definition mulmod.h:215
static void powermod(const uint64_t *base, uint64_t *res, uint64_t n)
Compute base to the n modulo m.
Definition mulmod.h:229
Namespace for new Math classes and functions.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
static void to_lcg(const uint64_t *ranlux, unsigned c, uint64_t *lcg)
Convert RANLUX numbers to an LCG state.
Definition ranlux_lcg.h:26
static void to_ranlux(const uint64_t *lcg, uint64_t *ranlux, unsigned &c_out)
Convert an LCG state to RANLUX numbers.
Definition ranlux_lcg.h:58
auto * m
Definition textangle.C:8
auto * l
Definition textangle.C:4