File indexing completed on 2025-11-04 10:29:50
0001 
0002 
0003 
0004 #ifndef VECGEOM_BASE_RNG_H_
0005 #define VECGEOM_BASE_RNG_H_
0006 
0007 #include "VecGeom/base/Global.h"
0008 
0009 #ifdef VECCORE_CUDA
0010 #include <cuda.h>
0011 #include <curand_kernel.h>
0012 #else
0013 #include <random>
0014 #endif
0015 
0016 namespace vecgeom {
0017 inline namespace VECGEOM_IMPL_NAMESPACE {
0018 
0019 #ifdef VECCORE_CUDA
0020 class RNG;
0021 
0022 
0023 namespace RNGvar {
0024 extern VECCORE_ATT_DEVICE unsigned long gMaxInstance;
0025 extern VECCORE_ATT_DEVICE RNG **gInstances;
0026 }
0027 #endif
0028 
0029 
0030 
0031 
0032 class RNG {
0033 
0034 private:
0035 #ifdef VECCORE_CUDA
0036 
0037 #ifdef __CUDA_ARCH__
0038   curandState fState;
0039 #else
0040 
0041 #endif
0042 
0043   VECCORE_ATT_HOST_DEVICE
0044   VECGEOM_FORCE_INLINE
0045   Precision GetUniform()
0046   {
0047 #ifdef __CUDA_ARCH__
0048     return curand_uniform(&fState);
0049 #else
0050     return (Precision)rand() / RAND_MAX;
0051 #endif
0052   }
0053 
0054 #else
0055 
0056   std::mt19937 rng;
0057   std::uniform_real_distribution<> uniform_dist;
0058 
0059   VECGEOM_FORCE_INLINE
0060   Precision GetUniform() { return uniform_dist(rng); }
0061 
0062 #endif
0063 
0064 public:
0065 #ifdef VECCORE_CUDA
0066   
0067   VECCORE_ATT_HOST_DEVICE
0068   RNG()
0069   {
0070 #ifdef __CUDA_ARCH__
0071     curand_init(0 , 0 , 0 , &fState);
0072 #else
0073 
0074 #endif
0075   }
0076 #else
0077   RNG() : rng(0), uniform_dist(0, 1) {}
0078 #endif
0079 
0080 public:
0081 
0082 
0083 
0084 #ifdef __CUDA_ARCH__
0085   VECCORE_ATT_DEVICE
0086   static void InitInstances(unsigned long nthreads)
0087   {
0088     unsigned int tid = (threadIdx.x + blockIdx.x * blockDim.x);
0089 
0090     if (tid == 0) {
0091       RNGvar::gMaxInstance = nthreads;
0092       RNGvar::gInstances   = new RNG *[nthreads];
0093     }
0094     __syncthreads();
0095 
0096     for (int i = tid; i < nthreads; i += blockDim.x * gridDim.x) {
0097       RNGvar::gInstances[i] = new RNG;
0098     }
0099   }
0100 #endif
0101 
0102 #ifndef VECCORE_CUDA
0103   void seed(unsigned long seed_val) { rng.seed(seed_val); }
0104 #endif
0105   
0106 
0107 
0108   VECCORE_ATT_HOST_DEVICE
0109   static RNG &Instance()
0110   {
0111 #ifdef __CUDA_ARCH__
0112     unsigned int tid = (threadIdx.x + blockIdx.x * blockDim.x);
0113     if (tid < RNGvar::gMaxInstance)
0114       return *(RNGvar::gInstances[tid]);
0115     else
0116       return *(new RNG);
0117 #else
0118     static RNG instance;
0119     return instance;
0120 #endif
0121   }
0122 
0123   
0124 
0125 
0126 
0127   VECCORE_ATT_HOST_DEVICE
0128   VECGEOM_FORCE_INLINE
0129   Precision uniform(const Precision min = 0., const Precision max = 1.) { return min + (max - min) * GetUniform(); }
0130 
0131   VECCORE_ATT_HOST_DEVICE
0132   VECGEOM_FORCE_INLINE
0133   int Poisson(const Precision lambda)
0134   {
0135     int k                  = 0;
0136     const Precision target = exp(-lambda);
0137     Precision p            = GetUniform();
0138     while (p < target) {
0139       p *= GetUniform();
0140       ++k;
0141     }
0142     return k;
0143   }
0144 
0145   
0146   VECCORE_ATT_HOST_DEVICE
0147   VECGEOM_FORCE_INLINE
0148   Precision Gaus(Precision ave = 0.0, Precision sig = 1.0) { return Gauss(ave, sig); }
0149 
0150   VECCORE_ATT_HOST_DEVICE
0151   VECGEOM_FORCE_INLINE
0152   Precision Gauss(Precision ave = 0.0, Precision sig = 1.0)
0153   {
0154     Precision x1, x2, w;
0155 
0156     do {
0157       x1 = 2.0 * GetUniform() - 1.0;
0158       x2 = 2.0 * GetUniform() - 1.0;
0159       w  = x1 * x1 + x2 * x2;
0160     } while (w >= 1.0);
0161 
0162     w = std::sqrt((-2.0 * std::log(w)) / w);
0163     return ave + (x1 * w * sig);
0164   }
0165 
0166   
0167 
0168 
0169 
0170   VECCORE_ATT_HOST_DEVICE
0171   VECGEOM_FORCE_INLINE
0172   void uniform_array(size_t n, Precision *array, const Precision min = 0., const Precision max = 1.)
0173   {
0174     for (size_t i = 0; i < n; ++i) {
0175       array[i] = min + (max - min) * GetUniform();
0176     }
0177   }
0178 
0179 private:
0180   RNG(RNG const &);
0181   RNG &operator=(RNG const &);
0182 };
0183 }
0184 } 
0185 
0186 #endif