File indexing completed on 2026-10-30 09:40:31
0001
0002
0003
0004 #ifndef VECGEOM_BASE_RNG_H_
0005 #define VECGEOM_BASE_RNG_H_
0006
0007 #include "VecGeom/base/Global.h"
0008
0009 #include <cstdint>
0010 #include <random>
0011
0012 namespace vecgeom {
0013
0014
0015
0016
0017 class RNG {
0018
0019 private:
0020 std::mt19937 rng;
0021 std::uniform_real_distribution<> uniform_dist;
0022
0023 VECGEOM_FORCE_INLINE
0024 Precision GetUniform() { return uniform_dist(rng); }
0025
0026 public:
0027 RNG() : rng(0), uniform_dist(0, 1) {}
0028
0029 public:
0030 using Seed_t = std::mt19937::result_type;
0031
0032 void seed(unsigned long seed_val) { rng.seed(static_cast<Seed_t>(seed_val)); }
0033
0034
0035
0036
0037
0038
0039 static Seed_t MakeStreamSeed(unsigned long base_seed, unsigned long stream_id = 0)
0040 {
0041 std::uint64_t z = static_cast<std::uint64_t>(base_seed);
0042 z += 0x9e3779b97f4a7c15ULL + static_cast<std::uint64_t>(stream_id);
0043 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
0044 z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
0045 z = z ^ (z >> 31);
0046 return static_cast<Seed_t>(z);
0047 }
0048
0049
0050 static void SeedEngine(RNG &engine, unsigned long base_seed, unsigned long stream_id = 0)
0051 {
0052 engine.seed(MakeStreamSeed(base_seed, stream_id));
0053 }
0054
0055
0056
0057
0058 static RNG &Instance()
0059 {
0060
0061
0062 static thread_local RNG instance;
0063 return instance;
0064 }
0065
0066
0067 static void SeedStream(unsigned long base_seed, unsigned long stream_id = 0)
0068 {
0069 SeedEngine(Instance(), base_seed, stream_id);
0070 }
0071
0072
0073
0074
0075
0076 Precision uniform(const Precision min = 0., const Precision max = 1.) { return min + (max - min) * GetUniform(); }
0077
0078 int Poisson(const Precision lambda)
0079 {
0080 int k = 0;
0081 const Precision target = exp(-lambda);
0082 Precision p = GetUniform();
0083 while (p < target) {
0084 p *= GetUniform();
0085 ++k;
0086 }
0087 return k;
0088 }
0089
0090
0091 Precision Gaus(Precision ave = 0.0, Precision sig = 1.0) { return Gauss(ave, sig); }
0092
0093 Precision Gauss(Precision ave = 0.0, Precision sig = 1.0)
0094 {
0095 Precision x1, x2, w;
0096
0097 do {
0098 x1 = 2.0 * GetUniform() - 1.0;
0099 x2 = 2.0 * GetUniform() - 1.0;
0100 w = x1 * x1 + x2 * x2;
0101 } while (w >= 1.0);
0102
0103 w = std::sqrt((-2.0 * std::log(w)) / w);
0104 return ave + (x1 * w * sig);
0105 }
0106
0107
0108
0109
0110
0111 void uniform_array(size_t n, Precision *array, const Precision min = 0., const Precision max = 1.)
0112 {
0113 for (size_t i = 0; i < n; ++i) {
0114 array[i] = min + (max - min) * GetUniform();
0115 }
0116 }
0117
0118 private:
0119 RNG(RNG const &);
0120 RNG &operator=(RNG const &);
0121 };
0122
0123 }
0124
0125 #endif