STK++ 0.9.13
STK_Law_Gamma.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: STatistiK
27 * Purpose: Implementation of the Cauchy Distribution
28 * Author: Serge Iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
29 **/
30
35#ifndef IS_RTKPP_LIB
36#include "../include/STK_Law_Gamma.h"
37#include "../include/STK_Law_Exponential.h"
40#endif
41
42
43namespace STK
44{
45
46namespace Law
47{
48
49#ifndef IS_RTKPP_LIB
50
51/* @brief generate a gamma random variate using the G.S algorithm */
53{
54 // GS algorithm for parameter a_ < 1.
55 if (a_ < 1.)
56 {
57 if(a_ == 0.) return 0.;
58 Real x;
59 do
60 {
61 Real p = c_ * generator.randUnif();
62 if (p >= 1.)
63 {
64 x = -std::log((c_ - p) / a_);
65 if (generator.randExp() >= (1. - a_) * std::log(x)) break;
66 }
67 else
68 {
69 x = std::exp(std::log(p) / a_);
70 if (generator.randExp() >= x) break;
71 }
72 }
73 while(1);
74 return(x*b_);
75 }
76 // Exponential law for parameter a_ = 1
77 if (a_ == 1.0) return b_*generator.randExp();
78 // Marsaglia fast Gamma generator with enhanced squeeze step for a>1
79 // initialize constants
80 Real v;
81 while(1)
82 {
83 Real x,u;
84 // generate gaussian rv in the range (-1/c, infty)
85 while( (v = 1. + c_* ( x = generator.randGauss() ) ) <= 0. );
86 // cubic normal variate
87 v = v*v*v;
88 // squeeze step
89 if ( (u = generator.randUnif()) < 1.-(x*x)*(x*x)/(108. * d_) ) break;
90 // rejection step
91 if ( std::log(u) < 0.5*x*x+d_*(1.-v+std::log(v)) ) break;
92 }
93 return b_*d_*v;
94}
95
96/*
97 * compute
98 * \f[
99 * f(x;\alpha,\beta) = \left(\frac{x}{\beta}\right)^{\alpha-1}
100 * \frac{e^{-x/\beta}}{\beta \, \Gamma(\alpha)}
101 * \ \mathrm{for}\ x > 0
102 * \f]
103 * where \f$ \alpha > 0 \f$ is the shape parameter
104 * and \f$ \beta > 0 \f$ is the scale parameter.
105 */
106Real Gamma::pdf( Real const& x) const
107{
108 // check NA value
109 if (isNA(x)) return x;
110 // trivial cases
111 if (x < 0.) return 0.;
112 if (Arithmetic<Real>::isInfinite(x)) return 0.;
113 if (x == 0.) return (a_<1) ? Arithmetic<Real>::infinity()
114 : (a_>1.) ? 0. : 1./b_;
115 // general case
116 return (a_ < 1) ? Funct::poisson_pdf_raw(a_, x/b_) * a_/x
118}
119
120/*
121 * Give
122 * \f[
123 * \ln(f(x;k,\theta)) = - x/\theta + (k-1) \ln(x)
124 * - k \ln(\theta) + \ln(\Gamma(k))
125 * \f]
126 */
127Real Gamma::lpdf( Real const& x) const
128{
129 // check NA value
130 if (isNA(x)) return x;
131 // trivial cases
132 if (x < 0.) return -Arithmetic<Real>::infinity();
134 if (x == 0.) return (a_<1) ? Arithmetic<Real>::infinity()
135 : (a_>1.) ? -Arithmetic<Real>::infinity() : -std::log(b_);
136 // general case
137 return (a_ < 1) ? Funct::poisson_lpdf_raw(a_, x/b_) +std::log(a_/x)
138 : Funct::poisson_lpdf_raw(a_-1, x/b_) - std::log(b_);
139}
140
141/*
142 * The cumulative distribution function can be expressed in terms of
143 * the incomplete gamma function
144 * \f[
145 * F(x;k,\theta) = \int_0^x f(u;k,\theta)\,du
146 * = \frac{\gamma(k, x/\theta)}{\Gamma(k)}.
147 * \f]
148 */
149Real Gamma::cdf( Real const& t) const
150{
151 // check NA value
152 if (isNA(t)) return t;
153 // trivial cases
154 if (t <= 0.) return 0.;
155 if (Arithmetic<Real>::isInfinite(t)) return 1.;
156 // general case
157 return Funct::gammaRatioP(a_, t/b_);
158}
159
160/*
161 * Give the quantile t such that the probability of a random variate
162 * is less to t is equal to p.
163 */
164Real Gamma::icdf( Real const& p) const
165{
167 return 0.0;
168}
169
170Real Gamma::rand( Real const& a, Real const& b)
171{
172 // check parameters
174 || a <= 0 || b <= 0
175 )
177 // GS algorithm for parameter a_ < 1.
178 if (a < 1.)
179 {
180 Real c = 1. + a/Const::_E_;
181 Real x;
182 if(a == 0.) return 0.;
183 do
184 {
185 Real p = c * generator.randUnif();
186 if (p >= 1.)
187 {
188 x = -std::log((c - p) / a);
189 if (generator.randExp() >= (1. - a) * std::log(x)) break;
190 }
191 else
192 {
193 x = std::exp(std::log(p) / a);
194 if (generator.randExp() >= x) break;
195 }
196 } while(1);
197 return b *x;
198 }
199 // special case
200 if (a == 1.0) return Exponential::rand(b);
201 // Marsaglia fast Gamma generator with enhanced squeeze step for alpha>1
202 // initialize constants
203 const Real d = a-1./3.;
204 const Real c = 1./sqrt(9.*d);
205 // rejection method : main loop
206 Real v;
207 while(1)
208 {
209 // auxiliary variables
210 Real x,u;
211 // generate gaussian rv in the range (-1/c, infty)
212 while( (v = 1. + c * ( x = generator.randGauss() ) ) <= 0. ) {}
213 // cubic normal variate
214 v = v*v*v;
215 // squeeze step
216 if ( (u = generator.randUnif()) < 1.-(x*x)*(x*x)/(108. * d) ) break;
217 // rejection step
218 if ( std::log(double(u)) < 0.5*x*x+d*(1.-v+log(v)) ) break;
219 }
220 return (b*d*v);
221}
222
223/*
224 * Give
225 * \f[
226 * \ln(f(x;k,\theta)) = - x/\theta + (k-1) \ln(x)
227 * - k \ln(\theta) + \ln(\Gamma(k))
228 * \f]
229 */
230Real Gamma::pdf( Real const& x, Real const& a, Real const& b)
231{
232 // check NA value
233 if (isNA(x)) return x;
234 // trivial cases
235 if (x < 0.) return 0.;
236 if (Arithmetic<Real>::isInfinite(x)) return 0.;
237 if (x == 0.) return (a<1) ? Arithmetic<Real>::infinity()
238 : (a>1.) ? 0. : 1./b;
239 // general case
240 return (a < 1) ? Funct::poisson_pdf_raw(a, x/b) * a/x
241 : Funct::poisson_pdf_raw(a-1, x/b)/b;
242}
243
244/*
245 * Give
246 * \f[
247 * \ln(f(x;k,\theta)) = - x/\theta + (k-1) \ln(x)
248 * - k \ln(\theta) + \ln(\Gamma(k))
249 * \f]
250 */
251Real Gamma::lpdf( Real const& x, Real const& a, Real const& b)
252{
253 // check NA value
254 if (isNA(x)) return x;
255 // trivial cases
256 if (x < 0.) return -Arithmetic<Real>::infinity();
258 if (x == 0.) return (a<1) ? Arithmetic<Real>::infinity()
259 : (a>1.) ? -Arithmetic<Real>::infinity() : -std::log(b);
260 // general case
261 return (a < 1) ? Funct::poisson_lpdf_raw(a, x/b) + std::log(a/x)
262 : Funct::poisson_lpdf_raw(a-1, x/b) - std::log(b);
263}
264
265/* @return the cumulative distribution function
266 * @param t a positive real value
267 * @param shape shape parameter
268 * @param scale scale (dispersion) parameter
269 **/
270Real Gamma::cdf(Real const& t, Real const& a, Real const& b)
271{
272 // check NA value
273 if (isNA(t)) return t;
274 // trivial cases
275 if (t <= 0.) return 0.;
276 if (Arithmetic<Real>::isInfinite(t)) return 1.;
277 // general case
278 return Funct::gammaRatioP(a, t/b);
279}
280
281/* @return the inverse cumulative distribution function
282 * @param p a probability number
283 * @param df1, df2 degree of freedom parameters
284 **/
285Real Gamma::icdf(Real const& p, Real const& a, Real const& b)
286{
287 return 0;
288}
289
291{
292 if (a_ < 1.)
293 {
294 c_ = 1. + a_/Const::_E_;
295 d_ = c_ * generator.randUnif();
296 }
297 else
298 {
299 d_ = a_-1./3.;
300 c_ = 1./std::sqrt(9.*d_);
301 }
302}
303
304#endif
305
306} // namespace Law
307
308} // namespace STK
In this file we declare functions around the gamma function ratio.
In this file we declare raw the functions.
#define STKRUNTIME_ERROR_1ARG(Where, Arg, Error)
Definition STK_Macros.h:129
#define STKDOMAIN_ERROR_2ARG(Where, Arg1, Arg2, Error)
Definition STK_Macros.h:147
virtual Real rand() const
Generate a pseudo Exponential random variate.
Real a_
The shape parameter.
Real b_
The scale parameter.
virtual Real pdf(Real const &x) const
compute
virtual Real lpdf(Real const &x) const
Compute.
virtual Real rand() const
generate a gamma random variate using the G.S algorithm of Ahrens and Dieter (1974) for 0<a_<1 and Ma...
Real c_
First and second constants for rand.
virtual Real icdf(Real const &p) const
virtual Real cdf(Real const &t) const
void computeCtes() const
compute c_ and d_
The MultidimRegression class allows to regress a multidimensional output variable among a multivariat...
Real poisson_pdf_raw(Real const &x, Real const &lambda)
Compute the Poisson density.
Real gammaRatioP(Real const &a, Real const &x)
Compute the incomplete gamma function ratio P(a,x).
Real poisson_lpdf_raw(Real const &x, Real const &lambda)
Compute the log-poisson density.
bool isNA(Type const &x)
utility method allowing to know if a value is a NA (Not Available) value
double Real
STK fundamental type of Real values.
The namespace STK is the main domain space of the Statistical ToolKit project.
Arithmetic properties of STK fundamental types.