21 #ifndef ROCRAND_POISSON_H_
22 #define ROCRAND_POISSON_H_
31 #include "rocrand/rocrand_lfsr113.h"
32 #include "rocrand/rocrand_mrg31k3p.h"
33 #include "rocrand/rocrand_mrg32k3a.h"
34 #include "rocrand/rocrand_mtgp32.h"
35 #include "rocrand/rocrand_philox4x32_10.h"
36 #include "rocrand/rocrand_scrambled_sobol32.h"
37 #include "rocrand/rocrand_scrambled_sobol64.h"
38 #include "rocrand/rocrand_sobol32.h"
39 #include "rocrand/rocrand_sobol64.h"
40 #include "rocrand/rocrand_threefry2x32_20.h"
41 #include "rocrand/rocrand_threefry2x64_20.h"
42 #include "rocrand/rocrand_threefry4x32_20.h"
43 #include "rocrand/rocrand_threefry4x64_20.h"
44 #include "rocrand/rocrand_xorwow.h"
46 #include "rocrand/rocrand_normal.h"
47 #include "rocrand/rocrand_uniform.h"
49 #include <hip/hip_runtime.h>
51 namespace rocrand_device
56 constexpr
double lambda_threshold_small = 64.0;
57 constexpr
double lambda_threshold_huge = 4000.0;
59 template<
class State,
typename Result_Type =
unsigned int>
60 __forceinline__ __device__ __host__
61 Result_Type poisson_distribution_small(State& state,
double lambda)
66 const double limit = exp(-lambda);
75 while(product > limit);
80 __forceinline__ __device__ __host__
81 double lgamma_approx(
const double x)
85 const double z = x - 1.0;
89 const double coefs[n] = {0.99999999999980993227684700473478,
90 676.520368121885098567009190444019,
91 -1259.13921672240287047156078755283,
92 771.3234287776530788486528258894,
93 -176.61502916214059906584551354,
94 12.507343278686904814458936853,
95 -0.13857109526572011689554707,
96 9.984369578019570859563e-6,
97 1.50563273514931155834e-7};
100 for(
int i = n - 1; i > 0; i--)
103 sum += coefs[i] / (z + i);
107 const double log_sqrt_2_pi = 0.9189385332046727418;
108 const double e = 2.718281828459045090796;
109 return (log_sqrt_2_pi + log(sum) - g) + (z + 0.5) * log((z + g + 0.5) / e);
112 template<
class State,
typename Result_Type =
unsigned int>
113 __forceinline__ __device__ __host__
114 Result_Type poisson_distribution_large(State& state,
double lambda)
118 const double c = 0.767 - 3.36 / lambda;
119 const double beta = ROCRAND_PI_DOUBLE / sqrt(3.0 * lambda);
120 const double alpha = beta * lambda;
121 const double k = log(c) - lambda - log(beta);
122 const double log_lambda = log(lambda);
127 const double x = (alpha - log((1.0 - u) / u)) / beta;
128 const double n = floor(x + 0.5);
134 const double y = alpha - beta * x;
135 const double t = 1.0 + exp(y);
136 const double lhs = y + log(v / (t * t));
137 const double rhs = k + n * log_lambda - lgamma_approx(n + 1.0);
140 return static_cast<Result_Type
>(n);
145 template<
class State,
typename Result_Type =
unsigned int>
146 __forceinline__ __device__ __host__
147 Result_Type poisson_distribution_huge(State& state,
double lambda)
152 return static_cast<Result_Type
>(round(sqrt(lambda) * n + lambda));
155 template<
class State,
typename Result_Type =
unsigned int>
156 __forceinline__ __device__ __host__
157 Result_Type poisson_distribution(State& state,
double lambda)
159 if(lambda < lambda_threshold_small)
161 return poisson_distribution_small<State, Result_Type>(state, lambda);
163 else if(lambda <= lambda_threshold_huge)
165 return poisson_distribution_large<State, Result_Type>(state, lambda);
169 return poisson_distribution_huge<State, Result_Type>(state, lambda);
173 template<
class State,
typename Result_Type =
unsigned int>
174 __forceinline__ __device__ __host__
175 Result_Type poisson_distribution_itr(State& state,
double lambda)
186 const double L = (lambda > 500.0) ? exp(-500.0) : exp(-lambda);
194 x *= ((double)lambda / (
double)k);
200 if((
double)500 < lambda)
208 x *= ((double)lambda / (
double)k);
215 template<
class State,
typename Result_Type =
unsigned int>
216 __forceinline__ __device__ __host__
217 Result_Type poisson_distribution_inv(State& state,
double lambda)
221 return poisson_distribution_itr<State, Result_Type>(state, lambda);
225 return poisson_distribution_huge<State, Result_Type>(state, lambda);
243 #ifndef ROCRAND_DETAIL_BM_NOT_IN_STATE
244 __forceinline__ __device__ __host__
247 return rocrand_device::detail::poisson_distribution<rocrand_state_philox4x32_10*, unsigned int>(
263 __forceinline__ __device__ __host__
267 rocrand_device::detail::poisson_distribution<rocrand_state_philox4x32_10*, unsigned int>(
270 rocrand_device::detail::poisson_distribution<rocrand_state_philox4x32_10*, unsigned int>(
273 rocrand_device::detail::poisson_distribution<rocrand_state_philox4x32_10*, unsigned int>(
276 rocrand_device::detail::poisson_distribution<rocrand_state_philox4x32_10*, unsigned int>(
293 #ifndef ROCRAND_DETAIL_BM_NOT_IN_STATE
294 __forceinline__ __device__ __host__
297 return rocrand_device::detail::poisson_distribution<rocrand_state_mrg31k3p*, unsigned int>(
314 #ifndef ROCRAND_DETAIL_BM_NOT_IN_STATE
315 __forceinline__ __device__ __host__
318 return rocrand_device::detail::poisson_distribution<rocrand_state_mrg32k3a*, unsigned int>(
335 #ifndef ROCRAND_DETAIL_BM_NOT_IN_STATE
336 __forceinline__ __device__ __host__
339 return rocrand_device::detail::poisson_distribution<rocrand_state_xorwow*, unsigned int>(
356 __forceinline__ __device__ __host__
359 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_mtgp32*, unsigned int>(
375 __forceinline__ __device__ __host__
378 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_sobol32*, unsigned int>(
394 __forceinline__ __device__ __host__
397 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_scrambled_sobol32*,
398 unsigned int>(state, lambda);
412 __forceinline__ __device__ __host__
415 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_sobol64*, unsigned int>(
431 __forceinline__ __device__ __host__
434 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_scrambled_sobol64*,
435 unsigned int>(state, lambda);
449 __forceinline__ __device__ __host__
452 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_lfsr113*, unsigned int>(
468 __forceinline__ __device__ __host__
471 return rocrand_device::detail::poisson_distribution_inv(state, lambda);
485 __forceinline__ __device__ __host__
488 return rocrand_device::detail::poisson_distribution_inv(state, lambda);
502 __forceinline__ __device__ __host__
505 return rocrand_device::detail::poisson_distribution_inv(state, lambda);
519 __forceinline__ __device__ __host__
522 return rocrand_device::detail::poisson_distribution_inv(state, lambda);
__forceinline__ __device__ __host__ unsigned int rocrand_poisson(rocrand_state_philox4x32_10 *state, double lambda)
Returns a Poisson-distributed unsigned int using Philox generator.
Definition: rocrand_poisson.h:245
__forceinline__ __device__ __host__ uint4 rocrand_poisson4(rocrand_state_philox4x32_10 *state, double lambda)
Returns four Poisson-distributed unsigned int values using Philox generator.
Definition: rocrand_poisson.h:264
__forceinline__ __device__ __host__ double rocrand_uniform_double(rocrand_state_philox4x32_10 *state)
Returns a uniformly distributed random double value from (0; 1] range.
Definition: rocrand_uniform.h:299
__forceinline__ __device__ __host__ double rocrand_normal_double(rocrand_state_philox4x32_10 *state)
Returns a normally distributed double value.
Definition: rocrand_normal.h:442