STK++ 0.9.13
STK_Law_Poisson.cpp
Go to the documentation of this file.
1/*--------------------------------------------------------------------*/
2/* Copyright (C) 2004-2016 Serge Iovleff, Université Lille 1, Inria
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this program; if not, write to the
16 Free Software Foundation, Inc.,
17 59 Temple Place,
18 Suite 330,
19 Boston, MA 02111-1307
20 USA
21
22 Contact : S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
23 */
24
25/*
26 * Project: stkpp::STatistiK::Law
27 * created on: 8 dec. 2014
28 * Author: iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
29 **/
30
31/* @file STK_Law_Poisson.cpp
32 * @brief In this file we implement the Poisson distribution.
33 **/
34
35
36
37#ifndef IS_RTKPP_LIB
38#include "../include/STK_Law_Poisson.h"
44#endif
45
46
47namespace STK
48{
49
50namespace Law
51{
52
53#ifndef IS_RTKPP_LIB
54
55/* The inverse cumulative distribution function at p.*/
56static Real gauss_icdf_fast(Real const& p)
57{
58 // trivial cases
59 if (p == 0.5) return 0.;
60
61 const Real a[6] =
62 {
63 -3.969683028665376e+01
64 , 2.209460984245205e+02
65 , -2.759285104469687e+02
66 , 1.383577518672690e+02
67 , -3.066479806614716e+01
68 , 2.506628277459239e+00
69 };
70 const Real b[5] =
71 {
72 -5.447609879822406e+01
73 , 1.615858368580409e+02
74 , -1.556989798598866e+02
75 , 6.680131188771972e+01
76 , -1.328068155288572e+01
77 };
78 const Real c[6] =
79 {
80 -7.784894002430293e-03
81 , -3.223964580411365e-01
82 , -2.400758277161838e+00
83 , -2.549732539343734e+00
84 , 4.374664141464968e+00
85 , 2.938163982698783e+00
86 };
87 const Real d[4] =
88 {
89 7.784695709041462e-03
90 , 3.224671290700398e-01
91 , 2.445134137142996e+00
92 , 3.754408661907416e+00
93 };
94
95 Real t, u, q = std::min(p, 1-p);
96 if (q > 0.02425)
97 {
98 /* Rational approximation for central region. */
99 u = q-0.5;
100 t = u*u;
101 u = u*(((((a[0]*t+a[1])*t+a[2])*t+a[3])*t+a[4])*t+a[5])
102 /(((((b[0]*t+b[1])*t+b[2])*t+b[3])*t+b[4])*t+1.);
103 }
104 else
105 {
106 /* Rational approximation for tail region. */
107 t = sqrt(-2.*log(q));
108 u = (((((c[0]*t+c[1])*t+c[2])*t+c[3])*t+c[4])*t+c[5])
109 /((((d[0]*t+d[1])*t+d[2])*t+d[3])*t+1);
110 }
111 return (p > 0.5 ? - u : u);
112}
113
114/* @brief inverse cumulative distribution function
115 * The quantile is defined as the smallest value @e x such that
116 * <em> F(x) >= p </em>, where @e F is the cumulative distribution function.
117 * @param p a probability number
118 **/
119static int poisson_icd_raw(Real const& p, Real const& lambda)
120{
121 // check values 0 and 1
122 Real q=1, el = std::exp(-lambda), s = p/el;
123 if (s<q) return 0;
124 q += lambda;
125 if (s<q) return 1;
126 q += lambda*lambda/2;
127 if (s<q) return 2;
128 // otherwise search
129 q = gauss_icdf_fast(p);
130 Real sqlambda = std::sqrt(lambda);
131 int k = round(lambda + q * sqlambda + (q-1.)*(q+1.)*(1.-q/(12.*sqlambda))/6);
132 if (Funct::gammaRatioQ_raw(k, lambda) >= p)
133 {
134 if (k==0) return k;
135 /* decreasing search */
136 while(1)
137 {
138 if ( Funct::gammaRatioQ_raw(k-1, lambda) < p) return k;
139 k--;
140 }
141 }
142 else
143 { /* increasing search */
144 while(1)
145 {
146 k++;
147 if( Funct::gammaRatioQ_raw(k, lambda) >= p) return k;
148 }
149 }
150 return k; // avoid warning at compilation
151}
152
153
154/* @return a Poisson random variate . */
155int Poisson::rand() const
156{
157 return poisson_icd_raw(Law::generator.randUnif(), lambda_);
158}
159/* @brief compute the probability distribution function.
160 * Give the value of the pdf at the point x.
161 * @param x a binary value
162 * @return the value of the pdf
163 **/
164Real Poisson::pdf(int const& x) const
165{
166 // check trivial values
167 if (x<0) return( 0. );
168 // if lambda is 0, we have P(X=0) = 1
169 if (lambda_==0.) return( (x==0) ? 1. : 0. );
170 // special value
171 if (x==0) return( Real(std::exp(-lambda_)) );
172 // stirling approximation and deviance
173 return( std::exp(-Funct::lgammaStirlingError((Real)x)-Funct::dev0((Real)x, lambda_))
174 /(Const::_SQRT2PI_*std::sqrt(x))
175 );
176}
177
178/* @brief compute the log probability distribution function.
179 * Give the value of the log-pdf at the point x.
180 * @param x an integer value
181 * @return the value of the log-pdf
182 **/
183Real Poisson::lpdf(int const& x) const
184{
185 // check trivial values
186 if (x<0) return( -Arithmetic<Real>::infinity() );
187 // if lambda is 0, we have P(X=0) = 1
188 if (lambda_==0.) return( (x==0) ? 0 : -Arithmetic<Real>::infinity() );
189 // special value
190 if (x==0) return( -lambda_ );
191 // stirling approximation and deviance
193 -Const::_LNSQRT2PI_-std::log((Real)x)/2.
194 );
195}
196/* @brief compute the cumulative distribution function
197 * Give the probability that a Poisson random variate is less or equal
198 * to t.
199 * @param t a real value
200 * @return the value of the cdf
201 **/
202Real Poisson::cdf(Real const& t) const
203{
204 // check trivial values
205 if (t < 0) return 0;
206 if (lambda_ == 0.) return( 1. );
207 // use gamma ratio function
208 return Funct::gammaRatioQ(std::floor(t) + 1, lambda_);
209}
210/* @brief inverse cumulative distribution function
211 * The quantile is defined as the smallest value @e x such that
212 * <em> F(x) >= p </em>, where @e F is the cumulative distribution function.
213 * @param p a probability number
214 **/
215int Poisson::icdf(Real const& p) const
216{
217 // check trivial values
218 if (p == 0.) return 0;
219 if (p == 1.) return Arithmetic<int>::max(); // infty does not exists for int
220 // check values 0 and 1
221 Real el = std::exp(-lambda_);
222 if (p<el) return 0;
223 if (p<(1+lambda_)*el) return 1;
224 // othewise search
225 Real q = gauss_icdf_fast(p), sqlambda = std::sqrt(lambda_);
226 int k = std::max(0., round(lambda_ + q * sqlambda + (q-1.)*(q+1.)*(1.-q/(12.*sqlambda))/6));
227 if (cdf(k) >= p)
228 { /* decreasing search */
229 while(1)
230 {
231 if ( cdf(k - 1) < p) return k;
232 k--;
233 }
234 }
235 else
236 { /* increasing search */
237 while(1)
238 {
239 k++;
240 if( cdf(k) >= p) return k;
241 }
242 }
243 return k; // avoid warning at compilation
244}
245
246/* @param lambda the mean
247 * @return a int random variate.
248 **/
249int Poisson::rand(Real const& lambda)
250{ return poisson_icd_raw(Law::generator.randUnif(), lambda);}
251/* @brief compute the probability distribution function
252 * Give the value of the pdf at the point x.
253 * @param x a binary value
254 * @param lambda the mean
255 * @return the value of the pdf
256 **/
257Real Poisson::pdf(int const& x, Real const& lambda)
258{
259 // check trivial values
260 if (x<0) return( 0. );
261 // if lambda is 0, we have P(X=0) = 1
262 if (lambda==0.) return( (x==0) ? 1. : 0. );
263 // special value
264 if (x==0) return( Real(std::exp(-lambda)) );
265 // stirling approximation and deviance
266 return( std::exp(-Funct::lgammaStirlingError((Real)x)-Funct::dev0((Real)x, lambda))
267 /(Const::_SQRT2PI_*std::sqrt(x))
268 );
269}
270
271/* @brief compute the log probability distribution function
272 * Give the value of the log-pdf at the point x.
273 * @param x a binary value
274 * @param lambda the mean
275 * @return the value of the log-pdf
276 **/
277Real Poisson::lpdf(int const& x, Real const& lambda)
278{
279 // check trivial values
280 if (x<0) return( -Arithmetic<Real>::infinity() );
281 // if lambda is 0, we have P(X=0) = 1
282 if (lambda==0.) return( (x==0) ? 0 : -Arithmetic<Real>::infinity() );
283 // special value
284 if (x==0) return( -lambda );
285 // stirling approximation and deviance
287 -Const::_LNSQRT2PI_-std::log((Real)x)/2.
288 );
289}
290
291/* @brief compute the cumulative distribution function
292 * Give the probability that a Poisson random variate is less or equal
293 * to t.
294 * @param t a real value
295 * @return the value of the cdf
296 **/
297Real Poisson::cdf(Real const& t, Real const& lambda)
298{
299 // check trivial values
300 if (t < 0) return 0;
301 if (lambda == 0.) return( 1. );
302 // use gamma ratio function
303 return Funct::gammaRatioQ(std::floor(t) + 1, lambda);
304}
305/* @brief inverse cumulative distribution function
306 * The quantile is defined as the smallest value @e x such that
307 * <em> F(x) >= p </em>, where @e F is the cumulative distribution function.
308 * @param p a probability number
309 **/
310int Poisson::icdf(Real const& p, Real const& lambda)
311{
312 // check trivial values
313 if (p == 0.) return 0;
314 if (p == 1.) return Arithmetic<int>::max();
315 // check values 0 and 1
316 Real el = std::exp(-lambda);
317 if (p<el) return 0;
318 if (p< (1+lambda)*el) return 1;
319 // othewise search
320 Real q = gauss_icdf_fast(p), sqlambda = std::sqrt(lambda);
321 int k = round(lambda + q * sqlambda + (q-1.)*(q+1.)*(1.-q/(12.*sqlambda))/6);
322 if (cdf(k, lambda) >= p)
323 { /* decreasing search */
324 while(1)
325 {
326 if ( cdf(k - 1,lambda) < p) return k;
327 k--;
328 }
329 }
330 else
331 { /* increasing search */
332 while(1)
333 {
334 k++;
335 if( cdf(k, lambda) >= p) return k;
336 }
337 }
338 return k; // avoid warning at compilation
339}
340
341#endif
342
343} // namespace Law
344
345} // namespace STK
346
347
In this file we give the main mathematical constants.
In this file we declare usual Real functions.
In this file we declare functions around the gamma function ratio.
In this file we declare functions around the gamma function.
In this file we declare raw the functions.
virtual Real cdf(Real const &t) const
compute the cumulative distribution function Give the probability that a Poisson random variate is le...
Real lambda_
mean of the Poisson distribution
virtual int rand() const
Real const & lambda() const
virtual int icdf(Real const &p) const
inverse cumulative distribution function The quantile is defined as the smallest value q such that F...
virtual Real lpdf(int const &x) const
compute the log probability distribution function.
virtual Real pdf(int const &x) const
compute the probability distribution function.
The MultidimRegression class allows to regress a multidimensional output variable among a multivariat...
Real dev0(Real const &a, Real const &b)
compute the partial deviance .
Real lgammaStirlingError(Real const &z)
Compute the error when we compute using the Stirling's formula.
Real gammaRatioQ(Real const &a, Real const &x)
Compute the incomplete gamma function ratio Q(a,x).
double Real
STK fundamental type of Real values.
Real gammaRatioQ_raw(Real const &a, Real const &x)
The namespace STK is the main domain space of the Statistical ToolKit project.
Arithmetic properties of STK fundamental types.