Coverage Report

Created: 2026-10-28 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/r-source/src/nmath/rpois.c
Line
Count
Source
1
/*
2
 *  Mathlib : A C Library of Special Functions
3
 *  Copyright (C) 1998 Ross Ihaka
4
 *  Copyright (C) 2000-2011 The R Core Team
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, a copy is available at
18
 *  https://www.R-project.org/Licenses/
19
 *
20
 *  SYNOPSIS
21
 *
22
 *    #include <Rmath.h>
23
 *    double rpois(double lambda)
24
 *
25
 *  DESCRIPTION
26
 *
27
 *    Random variates from the Poisson distribution.
28
 *
29
 *  REFERENCE
30
 *
31
 *    Ahrens, J.H. and Dieter, U. (1982).
32
 *    Computer generation of Poisson deviates
33
 *    from modified normal distributions.
34
 *    ACM Trans. Math. Software 8, 163-179.
35
 */
36
37
#include "nmath.h"
38
39
0
#define a0  -0.5
40
0
#define a1   0.3333333
41
0
#define a2  -0.2500068
42
0
#define a3   0.2000118
43
0
#define a4  -0.1661269
44
0
#define a5   0.1421878
45
0
#define a6  -0.1384794
46
0
#define a7   0.1250060
47
48
0
#define one_7 0.1428571428571428571
49
0
#define one_12  0.0833333333333333333
50
0
#define one_24  0.0416666666666666667
51
52
0
#define repeat for(;;)
53
54
double rpois(double mu)
55
0
{
56
    /* Factorial Table (0:9)! */
57
0
    const static double fact[10] =
58
0
    {
59
0
  1., 1., 2., 6., 24., 120., 720., 5040., 40320., 362880.
60
0
    };
61
62
    /* These are static --- persistent between calls for same mu : */
63
0
    static int l, m;
64
65
0
    static double b1, b2, c, c0, c1, c2, c3;
66
0
    static double pp[36], p0, p, q, s, d, omega;
67
0
    static double big_l;/* integer "w/o overflow" */
68
0
    static double muprev = 0., muprev2 = 0.;/*, muold  = 0.*/
69
70
    /* Local Vars  [initialize some for -Wall]: */
71
0
    double del, difmuk= 0., E= 0., fk= 0., fx, fy, g, px, py, t, u= 0., v, x;
72
0
    double pois = -1.;
73
0
    int k, kflag, big_mu, new_big_mu = FALSE;
74
75
0
    if (!R_FINITE(mu) || mu < 0)
76
0
  ML_WARN_return_NAN;
77
78
0
    if (mu <= 0.)
79
0
  return 0.;
80
81
0
    big_mu = mu >= 10.;
82
0
    if(big_mu)
83
0
  new_big_mu = FALSE;
84
85
0
    if (!(big_mu && mu == muprev)) {/* maybe compute new persistent par.s */
86
87
0
  if (big_mu) {
88
0
      new_big_mu = TRUE;
89
      /* Case A. (recalculation of s,d,l  because mu has changed):
90
       * The poisson probabilities pk exceed the discrete normal
91
       * probabilities fk whenever k >= m(mu).
92
       */
93
0
      muprev = mu;
94
0
      s = sqrt(mu);
95
0
      d = 6. * mu * mu;
96
0
      big_l = floor(mu - 1.1484);
97
      /* = an upper bound to m(mu) for all mu >= 10.*/
98
0
  }
99
0
  else { /* Small mu ( < 10) -- not using normal approx. */
100
101
      /* Case B. (start new table and calculate p0 if necessary) */
102
103
      /*muprev = 0.;-* such that next time, mu != muprev ..*/
104
0
      if (mu != muprev) {
105
0
    muprev = mu;
106
0
    m = imax2(1, (int) mu);
107
0
    l = 0; /* pp[] is already ok up to pp[l] */
108
0
    q = p0 = p = exp(-mu);
109
0
      }
110
111
0
      repeat {
112
    /* Step U. uniform sample for inversion method */
113
0
    u = unif_rand();
114
0
    if (u <= p0)
115
0
        return 0.;
116
117
    /* Step T. table comparison until the end pp[l] of the
118
       pp-table of cumulative poisson probabilities
119
       (0.458 > ~= pp[9](= 0.45792971447) for mu=10 ) */
120
0
    if (l != 0) {
121
0
        for (k = (u <= 0.458) ? 1 : imin2(l, m);  k <= l; k++)
122
0
      if (u <= pp[k])
123
0
          return (double)k;
124
0
        if (l == 35) /* u > pp[35] */
125
0
      continue;
126
0
    }
127
    /* Step C. creation of new poisson
128
       probabilities p[l..] and their cumulatives q =: pp[k] */
129
0
    l++;
130
0
    for (k = l; k <= 35; k++) {
131
0
        p *= mu / k;
132
0
        q += p;
133
0
        pp[k] = q;
134
0
        if (u <= q) {
135
0
      l = k;
136
0
      return (double)k;
137
0
        }
138
0
    }
139
0
    l = 35;
140
0
      } /* end(repeat) */
141
0
  }/* mu < 10 */
142
143
0
    } /* end {initialize persistent vars} */
144
145
/* Only if mu >= 10 : ----------------------- */
146
147
    /* Step N. normal sample */
148
0
    g = mu + s * norm_rand();/* norm_rand() ~ N(0,1), standard normal */
149
150
0
    if (g >= 0.) {
151
0
  pois = floor(g);
152
  /* Step I. immediate acceptance if pois is large enough */
153
0
  if (pois >= big_l)
154
0
      return pois;
155
  /* Step S. squeeze acceptance */
156
0
  fk = pois;
157
0
  difmuk = mu - fk;
158
0
  u = unif_rand(); /* ~ U(0,1) - sample */
159
0
  if (d * u >= difmuk * difmuk * difmuk)
160
0
      return pois;
161
0
    }
162
163
    /* Step P. preparations for steps Q and H.
164
       (recalculations of parameters if necessary) */
165
166
0
    if (new_big_mu || mu != muprev2) {
167
        /* Careful! muprev2 is not always == muprev
168
     because one might have exited in step I or S
169
     */
170
0
        muprev2 = mu;
171
0
  omega = M_1_SQRT_2PI / s;
172
  /* The quantities b1, b2, c3, c2, c1, c0 are for the Hermite
173
   * approximations to the discrete normal probabilities fk. */
174
175
0
  b1 = one_24 / mu;
176
0
  b2 = 0.3 * b1 * b1;
177
0
  c3 = one_7 * b1 * b2;
178
0
  c2 = b2 - 15. * c3;
179
0
  c1 = b1 - 6. * b2 + 45. * c3;
180
0
  c0 = 1. - b1 + 3. * b2 - 15. * c3;
181
0
  c = 0.1069 / mu; /* guarantees majorization by the 'hat'-function. */
182
0
    }
183
184
0
    if (g >= 0.) {
185
  /* 'Subroutine' F is called (kflag=0 for correct return) */
186
0
  kflag = 0;
187
0
  goto Step_F;
188
0
    }
189
190
191
0
    repeat {
192
  /* Step E. Exponential Sample */
193
194
0
  E = exp_rand(); /* ~ Exp(1) (standard exponential) */
195
196
  /*  sample t from the laplace 'hat'
197
      (if t <= -0.6744 then pk < fk for all mu >= 10.) */
198
0
  u = 2 * unif_rand() - 1.;
199
0
  t = 1.8 + fsign(E, u);
200
0
  if (t > -0.6744) {
201
0
      pois = floor(mu + s * t);
202
0
      fk = pois;
203
0
      difmuk = mu - fk;
204
205
      /* 'subroutine' F is called (kflag=1 for correct return) */
206
0
      kflag = 1;
207
208
0
    Step_F: /* 'subroutine' F : calculation of px,py,fx,fy. */
209
210
0
      if (pois < 10) { /* use factorials from table fact[] */
211
0
    px = -mu;
212
0
    py = pow(mu, pois) / fact[(int)pois];
213
0
      }
214
0
      else {
215
    /* Case pois >= 10 uses polynomial approximation
216
       a0-a7 for accuracy when advisable */
217
0
    del = one_12 / fk;
218
0
    del = del * (1. - 4.8 * del * del);
219
0
    v = difmuk / fk;
220
0
    if (fabs(v) <= 0.25)
221
0
        px = fk * v * v * (((((((a7 * v + a6) * v + a5) * v + a4) *
222
0
            v + a3) * v + a2) * v + a1) * v + a0)
223
0
      - del;
224
0
    else /* |v| > 1/4 */
225
0
        px = fk * log(1. + v) - difmuk - del;
226
0
    py = M_1_SQRT_2PI / sqrt(fk);
227
0
      }
228
0
      x = (0.5 - difmuk) / s;
229
0
      x *= x;/* x^2 */
230
0
      fx = -0.5 * x;
231
0
      fy = omega * (((c3 * x + c2) * x + c1) * x + c0);
232
0
      if (kflag > 0) {
233
    /* Step H. Hat acceptance (E is repeated on rejection) */
234
0
    if (c * fabs(u) <= py * exp(px + E) - fy * exp(fx + E))
235
0
        break;
236
0
      } else
237
    /* Step Q. Quotient acceptance (rare case) */
238
0
    if (fy - u * fy <= py * exp(px - fx))
239
0
        break;
240
0
  }/* t > -.67.. */
241
0
    }
242
0
    return pois;
243
0
}