STK++ 0.9.13
STK_Law_Normal.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 * Purpose: implementation of the Normal Distribution
28 * Author: Serge Iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
29 **/
30
36#ifndef IS_RTKPP_LIB
37
38#include "../include/STK_Law_Normal.h"
40
41const double a1 = -39.69683028665376;
42const double a2 = 220.9460984245205;
43const double a3 = -275.9285104469687;
44const double a4 = 138.3577518672690;
45const double a5 =-30.66479806614716;
46const double a6 = 2.506628277459239;
47
48const double b1 = -54.47609879822406;
49const double b2 = 161.5858368580409;
50const double b3 = -155.6989798598866;
51const double b4 = 66.80131188771972;
52const double b5 = -13.28068155288572;
53
54const double c1 = -0.007784894002430293;
55const double c2 = -0.3223964580411365;
56const double c3 = -2.400758277161838;
57const double c4 = -2.549732539343734;
58const double c5 = 4.374664141464968;
59const double c6 = 2.938163982698783;
60
61const double d1 = 0.007784695709041462;
62const double d2 = 0.3224671290700398;
63const double d3 = 2.445134137142996;
64const double d4 = 3.754408661907416;
65
66#endif
67
68namespace STK
69{
70
71namespace Law
72{
73
74
75#ifndef IS_RTKPP_LIB
76
77/* Generate a pseudo Normal random variate. */
79{ return (sigma_ == 0.) ? mu_ : generator.randGauss(mu_, sigma_);}
80
81/*
82 * Give the value of the pdf at x.
83 */
84Real Normal::pdf(Real const& x) const
85{
86 // check parameter
89 // trivial case
90 if (sigma_ == 0.) return (x==mu_) ? 1. : 0.;
91 // compute pdf
92 const Real y = (x - mu_)/sigma_;
93 return Const::_1_SQRT2PI_ * std::exp(-0.5 * y * y) / sigma_;
94}
95
96/*
97 * Give the value of the log-pdf at x.
98 */
99Real Normal::lpdf(Real const& x) const
100{
101 // check parameter
104 // trivial case
105 if (sigma_ == 0)
106 return (x==mu_) ? 0. : -Arithmetic<Real>::infinity();
107 // compute lpdf
108 const Real y = (x - mu_)/sigma_;
109 return -(Const::_LNSQRT2PI_ + std::log(double(sigma_)) + 0.5 * y * y);
110}
111
112/*
113 * The cumulative distribution function at t.
114 */
115Real Normal::cdf(Real const& t) const
116{
117 // check parameter
120 // trivial case
121 if (sigma_ == 0) return (t < mu_) ? 0. : 1.;
122 // change of variable
123 return (0.5*Funct::erfc_raw(-((t - mu_) / sigma_)*Const::_1_SQRT2_));
124}
125
126/* The inverse cumulative distribution function at p.*/
127Real Normal::icdf(Real const& p) const
128{
129 // check parameter
130 if ( (!Arithmetic<Real>::isFinite(p)) || (p > 1.) || (p < 0.) )
132 // trivial cases
133 if (p == 0.) return -Arithmetic<Real>::infinity();
134 if (p == 1.) return Arithmetic<Real>::infinity();
135 if (p == 0.5) return mu_;
136
137 double p_low = 0.02425, p_high = 1 - p_low;
138 double x = 0.0;
139 //Rational approximation for lower region.
140 if ( p < p_low)
141 {
142 double q = sqrt(-2*log(p));
143 x = (((((c1*q+c2)*q+c3)*q+c4)*q+c5)*q+c6) / ((((d1*q+d2)*q+d3)*q+d4)*q+1);
144 }
145 //Rational approximation for central region.
146 if (p_low <= p && p <= p_high)
147 {
148 double r = (p-0.5)*(p-0.5);
149 x = (((((a1*r+a2)*r+a3)*r+a4)*r+a5)*r+a6)*(p-0.5)/(((((b1*r+b2)*r+b3)*r+b4)*r+b5)*r+1);
150 }
151 //Rational approximation for upper region.
152 if (p_high < p )
153 {
154 double q = sqrt(-2*log(1-p));
155 x = -(((((c1*q+c2)*q+c3)*q+c4)*q+c5)*q+c6) / ((((d1*q+d2)*q+d3)*q+d4)*q+1);
156 }
157
158 /* The relative error of the approximation has absolute value less
159 than 1.15e-9. One iteration of Halley's rational method (third
160 order) gives full machine precision... */
161// if(( 0 < p)&&(p < 1))
162// {
163// double e = cdf(u) - p;
164// double u = e * Const::_SQRT2PI_ * exp(x*x/2);
165// x = x - u/(1 + x*u/2);
166// }
167 return mu_ + sigma_ * x;
168}
169
170/* Generate a pseudo Normal random variate with the specified parameters.
171 * (static)
172 */
173Real Normal::rand(Real const& mu, Real const& sigma)
174{
175#ifdef STK_DEBUG
176 // check parameters
179#endif
180 // return variate
181 return (sigma == 0.) ? mu : generator.randGauss(mu, sigma);
182}
183
184/*
185 * Give the value of the pdf at x.
186 */
187Real Normal::pdf(Real const& x, Real const& mu, Real const& sigma)
188{
189#ifdef STK_DEBUG
190 // check parameters
193#endif
194 // check parameter
197 // trivial case
198 if (sigma == 0.) return (x==mu) ? 1. : 0.;
199 // compute pdf
200 const Real y = (x - mu)/sigma;
201 return Const::_1_SQRT2PI_ * std::exp(-0.5 * y * y) / sigma;
202}
203/*
204 * Give the value of the log-pdf at x.
205 */
206Real Normal::lpdf(Real const& x, Real const& mu, Real const& sigma)
207{
208#ifdef STK_DEBUG
209 // check parameters
212#endif
213 // check parameter
216 // trivial case
217 if (sigma == 0)
218 return (x==mu) ? 0. : -Arithmetic<Real>::infinity();
219 // compute lpdf
220 const Real y = (x - mu)/sigma;
221 return -(Const::_LNSQRT2PI_ + std::log(double(sigma)) + 0.5 * y * y);
222}
223
224/*
225 * The cumulative distribution function at t.
226 */
227Real Normal::cdf(Real const& t, Real const& mu, Real const& sigma)
228{
229 // check parameter
232 // trivial case
233 if (sigma == 0) return (t < mu) ? 0. : 1.;
234 // change of variable
235 return (0.5*Funct::erfc_raw(-((t - mu) / sigma)*Const::_1_SQRT2_));
236}
237
238/* The inverse cumulative distribution function at p.*/
239Real Normal::icdf(Real const& p, Real const& mu, Real const& sigma)
240{
241 // check parameter
242 if ( (!Arithmetic<Real>::isFinite(p)) || (p > 1.) || (p < 0.) )
244 // trivial cases
245 if (p == 0.) return -Arithmetic<Real>::infinity();
246 if (p == 1.) return Arithmetic<Real>::infinity();
247 if (p == 0.5) return mu;
248
249 double p_low = 0.02425, p_high = 1 - p_low;
250 double x = 0.0;
251 //Rational approximation for lower region.
252 if ( p < p_low)
253 {
254 double q = sqrt(-2*log(p));
255 x = (((((c1*q+c2)*q+c3)*q+c4)*q+c5)*q+c6) / ((((d1*q+d2)*q+d3)*q+d4)*q+1);
256 }
257 //Rational approximation for central region.
258 if (p_low <= p && p <= p_high)
259 {
260 double r = (p-0.5)*(p-0.5);
261 x = (((((a1*r+a2)*r+a3)*r+a4)*r+a5)*r+a6)*(p-0.5) / (((((b1*r+b2)*r+b3)*r+b4)*r+b5)*r+1);
262 }
263 //Rational approximation for upper region.
264 if (p_high < p )
265 {
266 double q = sqrt(-2*log(1-p));
267 x = -(((((c1*q+c2)*q+c3)*q+c4)*q+c5)*q+c6) / ((((d1*q+d2)*q+d3)*q+d4)*q+1);
268 }
269
270 /* The relative error of the approximation has absolute value less
271 than 1.15e-9. One iteration of Halley's rational method (third
272 order) gives full machine precision... */
273 //Pseudo-code algorithm for refinement
274 // if(( 0 < p)&&(p < 1))
275 // {
276 // double e = cdf(u) - p;
277 // double u = e * Const::_SQRT2PI_ * exp(x*x/2);
278 // x = x - u/(1 + x*u/2);
279 // }
280 return mu + sigma * x;
281}
282
283#endif
284} // namespace law
285
286} // namespace STK
287
#define d4(z)
#define d2(z)
#define d1(z)
#define d3(z)
In this file we declare raw the functions.
const double b1
const double b4
const double a4
const double c1
const double a3
const double a6
const double b5
const double c4
const double b2
const double c3
const double a5
const double d1
const double a2
const double d2
const double b3
const double d4
const double c2
const double d3
const double c6
const double c5
const double a1
#define STKDOMAIN_ERROR_1ARG(Where, Arg, Error)
Definition STK_Macros.h:165
#define STKDOMAIN_ERROR_2ARG(Where, Arg1, Arg2, Error)
Definition STK_Macros.h:147
virtual Real lpdf(Real const &x) const
virtual Real icdf(Real const &p) const
Compute the inverse cumulative distribution function at p of the standard normal distribution.
Real sigma_
The sigma parameter.
virtual Real pdf(Real const &x) const
virtual Real cdf(Real const &t) const
Compute the cumulative distribution function at t of the standard normal distribution.
Real const & mu() const
Real const & sigma() const
Real mu_
The mu parameter.
Real rand() const
Generate a pseudo Normal random variate.
The MultidimRegression class allows to regress a multidimensional output variable among a multivariat...
Real erfc_raw(Real const &a)
Compute the complementary error function erfc(a) Compute the function.
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.