10static size_t poisson_inversion(uint64_t* state,
double lambda) {
11 double L = exp(-lambda);
17 p *= u64_to_double01(xoshiro256ss_next(state));
23static lmmc_status_t poisson_store_sample(
double sample,
size_t* out) {
24 const double exclusive_limit = (double)SIZE_MAX + 1.0;
25 if (!isfinite(sample) || sample < 0.0 || sample >= exclusive_limit) {
28 *out = (size_t)sample;
37static lmmc_status_t poisson_ptrd(uint64_t* state,
double lambda,
size_t* out) {
38 double smu = sqrt(lambda);
39 double b = 0.931 + 2.53 * smu;
40 double a = -0.059 + 0.02483 * b;
41 double inv_alpha = 1.1239 + 1.1328 / (b - 3.4);
42 double vr = 0.9277 - 3.6224 / (b - 2.0);
43 double us, v, u, k_real;
46 v = u64_to_double01(xoshiro256ss_next(state));
49 k_real = floor((2.0 * a / (0.5 - fabs(u)) + b) * u + lambda + 0.445);
51 return poisson_store_sample(k_real, out);
56 u = u64_to_double01(xoshiro256ss_next(state)) - 0.5;
59 u = ((u >= 0.0) ? 0.5 : -0.5) - u;
60 v = u64_to_double01(xoshiro256ss_next(state)) * vr;
64 if (us == 0.0 || (us < 0.013 && v > us)) {
68 k_real = floor((2.0 * a / us + b) * u + lambda + 0.445);
69 if (!isfinite(k_real)) {
81 v = v * inv_alpha / (a / (us * us) + b);
83 const double log_accept = k_real * log(lambda) - lambda - lgamma(k_real + 1.0);
84 if (!isfinite(log_accept)) {
87 if (log(v) <= log_accept) {
88 return poisson_store_sample(k_real, out);
99 if (rng == NULL || out == NULL) {
102 if (!isfinite(lambda) || lambda <= 0.0) {
107 *out = poisson_inversion(rng->
state, lambda);
109 return poisson_ptrd(rng->
state, lambda, out);
121static uint64_t binomial_inversion(uint64_t* state, uint64_t n,
double p) {
122 const double q = 1.0 - p;
123 const double qn = exp((
double)n * log1p(-p));
124 const double np = (double)n * p;
125 const uint64_t bound = (uint64_t)fmin((
double)n, np + 10.0 * sqrt(np * q + 1.0));
128 double u = u64_to_double01(xoshiro256ss_next(state));
135 u = u64_to_double01(xoshiro256ss_next(state));
138 px = (((double)(n - x + 1) * p) * px) / ((
double)x * q);
144static int binomial_btpe_accept(
145 uint64_t n,
double r,
double q, int64_t m,
double nrq,
146 double xm, int64_t y,
double v) {
147 const uint64_t k = y >= m ? (uint64_t)y - (uint64_t)m : (uint64_t)m - (uint64_t)y;
148 if (k <= 20 || (
double)k >= nrq / 2.0 - 1.0) {
149 const double s = r / q;
150 const double aa = s * ((double)n + 1.0);
154 for (i = m + 1; i <= y; ++i) {
155 f *= aa / (double)i - s;
158 for (i = y + 1; i <= m; ++i) {
159 f /= aa / (double)i - s;
166 const double kd = (double)k;
167 const double rho = (kd / nrq) *
168 ((kd * (kd / 3.0 + 0.625) + 1.0 / 6.0) / nrq + 0.5);
169 const double t = -kd * kd / (2.0 * nrq);
170 const double logv = log(v);
171 if (logv > t - rho) {
172 const double x1 = (double)y + 1.0;
173 const double f1 = (double)m + 1.0;
174 const double z = (double)n + 1.0 - (
double)m;
175 const double w = (double)n - (
double)y + 1.0;
176 const double x2 = x1 * x1, f2 = f1 * f1, z2 = z * z, w2 = w * w;
178 if (logv > t + rho) {
181 accept = xm * log(f1 / x1) + ((double)n - (double)m + 0.5) * log(z / w)
182 + ((double)y - (double)m) * log(w * r / (x1 * q))
183 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 / 166320.0
184 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) / z2) / z2) / z / 166320.0
185 - (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) / x1 / 166320.0
186 - (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) / w2) / w2) / w2) / w / 166320.0;
195static uint64_t binomial_btpe(uint64_t* state, uint64_t n,
double p) {
196 const double r = fmin(p, 1.0 - p);
197 const double q = 1.0 - r;
198 const double fm = (double)n * r + r;
199 const int64_t m = (int64_t)floor(fm);
200 const double p1 = floor(2.195 * sqrt((
double)n * r * q) - 4.6 * q) + 0.5;
201 const double xm = (double)m + 0.5;
202 const double xl = xm - p1;
203 const double xr = xm + p1;
204 const double c = 0.134 + 20.5 / (15.3 + (double)m);
205 double a = (fm - xl) / (fm - xl * r);
206 const double laml = a * (1.0 + a / 2.0);
208 const double p2 = p1 * (1.0 + 2.0 * c);
209 const double p3 = p2 + c / laml;
211 const double nrq = (double)n * r * q;
213 a = (xr - fm) / (xr * q);
214 lamr = a * (1.0 + a / 2.0);
218 double u = u64_to_double01(xoshiro256ss_next(state)) * p4;
219 double v = u64_to_double01(xoshiro256ss_next(state));
225 y = (int64_t)floor(xm - p1 * v + u);
226 result = (uint64_t)y;
227 return p > 0.5 ? n - result : result;
228 }
else if (u <= p2) {
229 x = xl + (u - p1) / c;
230 v = v * c + 1.0 - fabs((
double)m - x + 0.5) / p1;
234 y = (int64_t)floor(x);
235 }
else if (u <= p3) {
239 y = (int64_t)floor(xl + log(v) / laml);
243 v = v * (u - p2) * laml;
248 y = (int64_t)floor(xr - log(v) / lamr);
249 if (y < 0 || (uint64_t)y > n) {
252 v = v * (u - p3) * lamr;
255 if (!binomial_btpe_accept(n, r, q, m, nrq, xm, y, v)) {
259 uint64_t result = (uint64_t)y;
260 return p > 0.5 ? n - result : result;
265static uint64_t binomial_chunk(uint64_t* state, uint64_t n,
double p) {
266 const double working_p = p <= 0.5 ? p : 1.0 - p;
268 if ((
double)n * working_p < 30.0) {
269 value = binomial_inversion(state, n, working_p);
270 return p <= 0.5 ? value : n - value;
272 return binomial_btpe(state, n, p);
281 const uint64_t max_chunk = (UINT64_C(1) << 53) - UINT64_C(1);
284 if (rng == NULL || out == NULL || !isfinite(p) || p < 0.0 || p > 1.0) {
287 if (n == 0 || p == 0.0) {
296 remaining = (uint64_t)n;
297 while (remaining != 0) {
298 uint64_t chunk = remaining > max_chunk ? max_chunk : remaining;
299 total += binomial_chunk(rng->
state, chunk, p);
302 *out = (size_t)total;
double lmmc_real_t
Public and internal LMMC real type.
lmmc_status_t lmmc_rng_poisson(lmmc_rng_t *rng, lmmc_real_t lambda, size_t *out)
生成 Poisson 分布样本 。
lmmc_status_t lmmc_rng_binomial(lmmc_rng_t *rng, size_t n, lmmc_real_t p, size_t *out)
生成二项分布样本 Binomial(n, p)。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_INVALID_ARGUMENT