29#if defined (HAVE_CONFIG_H)
45static double xlgamma (
double x)
47 return std::lgamma (
x);
56#define C0 9.18938533204672742e-01
57#define C1 8.33333333333333333e-02
58#define C3 -2.77777777777777778e-03
59#define C5 7.93650793650793651e-04
60#define C7 -5.95238095238095238e-04
62 static double logfak[30L] =
64 0.00000000000000000, 0.00000000000000000, 0.69314718055994531,
65 1.79175946922805500, 3.17805383034794562, 4.78749174278204599,
66 6.57925121201010100, 8.52516136106541430, 10.60460290274525023,
67 12.80182748008146961, 15.10441257307551530, 17.50230784587388584,
68 19.98721449566188615, 22.55216385312342289, 25.19122118273868150,
69 27.89927138384089157, 30.67186010608067280, 33.50507345013688888,
70 36.39544520803305358, 39.33988418719949404, 42.33561646075348503,
71 45.38013889847690803, 48.47118135183522388, 51.60667556776437357,
72 54.78472939811231919, 58.00360522298051994, 61.26170176100200198,
73 64.55753862700633106, 67.88974313718153498, 71.25703896716800901
82 return ((k + 0.5)*std::log (k) - k +
C0
83 + r*(
C1 + rr*(
C3 + rr*(
C5 + rr*
C7))));
86 return (logfak[
static_cast<int> (k)]);
121f (
double k,
double l_nu,
double c_pm)
123 return exp (k * l_nu - flogfak (k) - c_pm);
129 static double my_last = -1.0;
130 static double m, k2, k4, k1, k5;
131 static double dl, dr, r1, r2, r4, r5, ll, lr, l_my, c_pm,
132 f1, f2, f4, f5, p1, p2, p3, p4, p5, p6;
141 Ds = std::sqrt (my + 0.25);
146 k2 =
ceil (my - 0.5 - Ds);
147 k4 = std::floor (my - 0.5 + Ds);
148 k1 = k2 + k2 - m + 1L;
158 r4 = my / (k4 + 1.0);
159 r5 = my / (k5 + 1.0);
166 l_my = std::log (my);
167 c_pm = m * l_my - flogfak (m);
170 f2 =
f (k2, l_my, c_pm);
171 f4 =
f (k4, l_my, c_pm);
172 f1 =
f (k1, l_my, c_pm);
173 f5 =
f (k5, l_my, c_pm);
177 p1 = f2 * (dl + 1.0);
179 p3 = f4 * (dr + 1.0) + p2;
195 if ((
V = U - p1) < 0.0)
return (k2 + std::floor (U/f2));
198 if ((W =
V / dl) < f1 )
return (k1 + std::floor (
V/f1));
203 if (W <= f2 - Dk * (f2 - f2/r2))
208 if ((
V = f2 + f2 - W) < 1.0)
212 if (
V <= f2 + Dk * (1.0 - f2)/(dl + 1.0))
217 if (
V <=
f (Y, l_my, c_pm))
return (Y);
226 if ((
V = U - p3) < 0.0)
return (k4 - std::floor ((U - p2)/f4));
229 if ((W =
V / dr) < f5 )
return (k5 - std::floor (
V/f5));
234 if (W <= f4 - Dk * (f4 - f4*r4))
239 if ((
V = f4 + f4 - W) < 1.0)
243 if (
V <= f4 + Dk * (1.0 - f4)/ dr)
248 if (
V <=
f (Y, l_my, c_pm))
return (Y);
258 Dk = std::floor (1.0 - std::log (W)/ll);
259 if ((X = k1 - Dk) < 0L)
continue;
261 if (W <= f1 - Dk * (f1 - f1/r1))
267 Dk = std::floor (1.0 - std::log (W)/lr);
270 if (W <= f5 - Dk * (f5 - f5*r5))
278 if (std::log (W) <= X * l_my - flogfak (X) - c_pm)
return (X);
300poisson_cdf_lookup (
double lambda, T *p, std::size_t n)
306 int intlambda =
static_cast<int> (std::floor (lambda));
311 t[0] = P = exp (-lambda);
312 for (tableidx = 1; tableidx <= intlambda; tableidx++)
314 P = P*lambda/
static_cast<double> (tableidx);
315 t[tableidx] = t[tableidx-1] + P;
327 int k = (u > 0.458 ? intlambda : 0);
336 p[i] =
static_cast<T
> (k);
346 P = P*lambda/
static_cast<double> (tableidx);
347 t[tableidx] = t[tableidx-1] + P;
350 if (t[tableidx] == t[tableidx-1]) t[tableidx] = 1.0;
352 if (u <= t[tableidx-1])
break;
358 p[i] =
static_cast<T
> (tableidx-1);
365poisson_rejection (
double lambda, T *p, std::size_t n)
367 double sq = std::sqrt (2.0*lambda);
368 double alxm = std::log (lambda);
369 double g = lambda*alxm - xlgamma (lambda+1.0);
372 for (i = 0; i < n; i++)
380 em = sq * y + lambda;
383 em = std::floor (em);
384 t = 0.9*(1.0+y*y)* exp (em*alxm-flogfak (em)-g);
408 if (L < 0.0 || math::isinf (L))
411 p[i] = numeric_limits<T>::NaN ();
415 poisson_cdf_lookup<T> (L, p, n);
425 const double sqrtL = std::sqrt (L);
426 for (i = 0; i < n; i++)
428 p[i] = std::floor (rand_normal<T> () * sqrtL + L + 0.5);
445 if (L < 0.0) ret = numeric_limits<T>::NaN ();
455 t *= rand_uniform<T> ();
463 poisson_rejection<T> (L, &ret, 1);
465 else if (math::isinf (L))
469 ret = numeric_limits<T>::NaN ();
474 ret = std::floor (rand_normal<T> () * std::sqrt (L) + L + 0.5);
475 if (ret < 0.0) ret = 0.0;
483OCTAVE_END_NAMESPACE(octave)
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
F77_RET_T const F77_INT const F77_INT const F77_INT const F77_DBLE const F77_DBLE F77_INT F77_DBLE * V
std::complex< T > ceil(const std::complex< T > &x)
F77_RET_T const F77_DBLE * x
F77_RET_T const F77_DBLE const F77_DBLE * f
double rand_uniform< double >()
void rand_poisson(T L_arg, octave_idx_type n, T *p)
template void rand_poisson< double >(double, octave_idx_type, double *)
template void rand_poisson< float >(float, octave_idx_type, float *)