23#include <Random123/philox.h>
54 explicit PhiloxRng(std::uint32_t seed, std::uint32_t key_hi = 0xBEEFCAFE,
55 std::uint64_t substream = 0)
56 : key_{{seed, key_hi}},
57 ctr_{{0,
static_cast<std::uint32_t
>(substream),
58 static_cast<std::uint32_t
>(substream >> 32u), 0}} {}
63 buf_ = rng_(ctr_, key_);
67 return buf_[idx_++] * (1.0 / 4294967296.0);
71 double uniform(
double lo,
double hi) {
return std::fma(hi - lo,
uniform(), lo); }
80 buf_ = rng_(ctr_, key_);
84 std::uint64_t
const hi = buf_[idx_++];
85 std::uint64_t
const lo = buf_[idx_++];
86 std::uint64_t
const bits = (hi << 32U) | lo;
87 return static_cast<double>(bits >> 11U) * (1.0 / 9007199254740992.0);
97 double const u1 = 1.0 - draw(precision);
98 double const u2 = draw(precision);
99 return std::fma(sigma * std::sqrt(-2.0 * std::log(u1)),
100 std::cos(2.0 * std::numbers::pi * u2), mean);
107 throw std::invalid_argument(
108 "Provided alpha for gamma function approximation is less than 1. Consider using an "
109 "exact gamma function for this instance.");
111 const double a = 1.0 - (1.0 / (9.0 * alpha));
112 const double b = 1.0 / (3.0 * std::sqrt(alpha));
116 x = std::fma(b, gaussian(0.0, 1.0, precision), a);
119 return scale * alpha * x * x * x;
125 const double x = gamma_wh(alpha, 1, precision);
126 const double y = gamma_wh(zeta, 1, precision);
128 if (x == 0.0 && y == 0.0) {
129 return alpha >= zeta ? 1.0 : 0.0;
132 return 1.0 / (1.0 + (y / x));
134 const double r = x / y;
135 return r / (1.0 + r);
143 r123::Philox4x32 rng_;
144 r123::Philox4x32::key_type key_;
145 r123::Philox4x32::ctr_type ctr_;
146 r123::Philox4x32::ctr_type buf_{};
Definition philox_rng.hpp:43
double uniform()
Uniform in [0, 1), with 32 bits of resolution.
Definition philox_rng.hpp:61
double gamma_wh(double alpha, double scale=1, Precision precision=Precision::Bits32)
Definition philox_rng.hpp:105
PhiloxRng(std::uint32_t seed, std::uint32_t key_hi=0xBEEFCAFE, std::uint64_t substream=0)
key_hi selects an independent stream, so different generators seeded
Definition philox_rng.hpp:54
double uniform53()
Uniform in [0, 1) with full double resolution: combines two consecutive 32-bit Philox words into a 64...
Definition philox_rng.hpp:78
double gaussian(double mean, double sigma, Precision precision=Precision::Bits32)
Gaussian deviate by the Box–Muller transform, cosine branch only (two uniforms per deviate).
Definition philox_rng.hpp:96
double beta_dist_approx(double alpha, double zeta, Precision precision=Precision::Bits32)
Definition philox_rng.hpp:124
double uniform53(double lo, double hi)
Uniform in [lo, hi) with full double resolution.
Definition philox_rng.hpp:91
double uniform(double lo, double hi)
Uniform in [lo, hi), with 32 bits of resolution.
Definition philox_rng.hpp:71
Definition philox_rng.hpp:29
Precision
Definition philox_rng.hpp:41