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>
51namespace rocrand_device {
54constexpr double lambda_threshold_small = 64.0;
55constexpr double lambda_threshold_huge = 4000.0;
57template<
class State,
typename Result_Type =
unsigned int>
58__forceinline__ __device__ __host__ Result_Type poisson_distribution_small(State& state,
63 const double limit = exp(-lambda);
72 while (product > limit);
77__forceinline__ __device__ __host__
double lgamma_approx(
const double x)
81 const double z = x - 1.0;
85 const double coefs[n] = {
86 0.99999999999980993227684700473478,
87 676.520368121885098567009190444019,
88 -1259.13921672240287047156078755283,
89 771.3234287776530788486528258894,
90 -176.61502916214059906584551354,
91 12.507343278686904814458936853,
92 -0.13857109526572011689554707,
93 9.984369578019570859563e-6,
94 1.50563273514931155834e-7
98 for (
int i = n - 1; i > 0; i--)
100 sum += coefs[i] / (z + i);
104 const double log_sqrt_2_pi = 0.9189385332046727418;
105 const double e = 2.718281828459045090796;
106 return (log_sqrt_2_pi + log(sum) - g) + (z + 0.5) * log((z + g + 0.5) / e);
109template<
class State,
typename Result_Type =
unsigned int>
110__forceinline__ __device__ __host__ Result_Type poisson_distribution_large(State& state,
115 const double c = 0.767 - 3.36 / lambda;
116 const double beta = ROCRAND_PI_DOUBLE / sqrt(3.0 * lambda);
117 const double alpha = beta * lambda;
118 const double k = log(c) - lambda - log(beta);
119 const double log_lambda = log(lambda);
124 const double x = (alpha - log((1.0 - u) / u)) / beta;
125 const double n = floor(x + 0.5);
131 const double y = alpha - beta * x;
132 const double t = 1.0 + exp(y);
133 const double lhs = y + log(v / (t * t));
134 const double rhs = k + n * log_lambda - lgamma_approx(n + 1.0);
137 return static_cast<Result_Type
>(n);
142template<
class State,
typename Result_Type =
unsigned int>
143__forceinline__ __device__ __host__ Result_Type poisson_distribution_huge(State& state,
149 return static_cast<Result_Type
>(round(sqrt(lambda) * n + lambda));
152template<
class State,
typename Result_Type =
unsigned int>
153__forceinline__ __device__ __host__ Result_Type poisson_distribution(State& state,
double lambda)
155 if (lambda < lambda_threshold_small)
157 return poisson_distribution_small<State, Result_Type>(state, lambda);
159 else if (lambda <= lambda_threshold_huge)
161 return poisson_distribution_large<State, Result_Type>(state, lambda);
165 return poisson_distribution_huge<State, Result_Type>(state, lambda);
169template<
class State,
typename Result_Type =
unsigned int>
170__forceinline__ __device__ __host__ Result_Type poisson_distribution_itr(State& state,
186 double upow = pow + 500.0;
187 double ex = exp(-500.0);
192 L = exp((
double)(pow - lambda));
200 x *= ((double)lambda / (double) k);
203 }
while((
double)pow < lambda);
207template<
class State,
typename Result_Type =
unsigned int>
208__forceinline__ __device__ __host__ Result_Type poisson_distribution_inv(State& state,
213 return poisson_distribution_itr<State, Result_Type>(state, lambda);
217 return poisson_distribution_huge<State, Result_Type>(state, lambda);
235#ifndef ROCRAND_DETAIL_BM_NOT_IN_STATE
236__forceinline__ __device__ __host__
unsigned int rocrand_poisson(rocrand_state_philox4x32_10* state,
239 return rocrand_device::detail::poisson_distribution<rocrand_state_philox4x32_10*, unsigned int>(
255__forceinline__ __device__ __host__
259 rocrand_device::detail::poisson_distribution<rocrand_state_philox4x32_10*, unsigned int>(
262 rocrand_device::detail::poisson_distribution<rocrand_state_philox4x32_10*, unsigned int>(
265 rocrand_device::detail::poisson_distribution<rocrand_state_philox4x32_10*, unsigned int>(
268 rocrand_device::detail::poisson_distribution<rocrand_state_philox4x32_10*, unsigned int>(
285#ifndef ROCRAND_DETAIL_BM_NOT_IN_STATE
286__forceinline__ __device__ __host__
unsigned int rocrand_poisson(rocrand_state_mrg31k3p* state,
289 return rocrand_device::detail::poisson_distribution<rocrand_state_mrg31k3p*, unsigned int>(
306#ifndef ROCRAND_DETAIL_BM_NOT_IN_STATE
307__forceinline__ __device__ __host__
unsigned int rocrand_poisson(rocrand_state_mrg32k3a* state,
310 return rocrand_device::detail::poisson_distribution<rocrand_state_mrg32k3a*, unsigned int>(
327#ifndef ROCRAND_DETAIL_BM_NOT_IN_STATE
328__forceinline__ __device__ __host__
unsigned int rocrand_poisson(rocrand_state_xorwow* state,
331 return rocrand_device::detail::poisson_distribution<rocrand_state_xorwow*, unsigned int>(
348__forceinline__ __device__ __host__
351 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_mtgp32*, unsigned int>(
367__forceinline__ __device__ __host__
370 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_sobol32*, unsigned int>(
386__forceinline__ __device__ __host__
389 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_scrambled_sobol32*,
390 unsigned int>(state, lambda);
404__forceinline__ __device__ __host__
407 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_sobol64*, unsigned int>(
423__forceinline__ __device__ __host__
426 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_scrambled_sobol64*,
427 unsigned int>(state, lambda);
441__forceinline__ __device__ __host__
444 return rocrand_device::detail::poisson_distribution_inv<rocrand_state_lfsr113*, unsigned int>(
460__forceinline__ __device__ __host__
463 return rocrand_device::detail::poisson_distribution_inv(state, lambda);
477__forceinline__ __device__ __host__
480 return rocrand_device::detail::poisson_distribution_inv(state, lambda);
494__forceinline__ __device__ __host__
497 return rocrand_device::detail::poisson_distribution_inv(state, lambda);
511__forceinline__ __device__ __host__
514 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:236
__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:256
__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