STK++ 0.9.13
STK_Funct_raw.h
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: Analysis
27 * Purpose: raw mathematical functions
28 * Author: Serge Iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
29 **/
30
38#ifndef STK_FUNCT_RAW_H
39#define STK_FUNCT_RAW_H
40
41#include "STK_Funct_gamma.h"
42#include "STK_Algo.h"
43#include "STK_Funct_Util.h"
44
45namespace STK
46{
47
48namespace Funct
49{
50// forward declaration
51Real beta_pdf_raw(Real const& x, Real const& a, Real const& b);
52
53Real binomial_pdf_raw(Real const& x, Real const& n, Real const& p);
54Real binomial_pdf_raw(int x, int n, Real const& p);
55Real binomial_lpdf_raw(Real const& x, Real const& n, Real const& p);
56Real binomial_lpdf_raw(int x, int n, Real const& p);
57
58Real poisson_pdf_raw(Real const& x, Real const& lambda);
59Real poisson_pdf_raw(int x, Real const& lambda);
60Real poisson_lpdf_raw(Real const& x, Real const& lambda);
61Real poisson_lpdf_raw(int x, Real const& lambda);
62
63Real erf_raw(Real const& a);
64Real erfc_raw(Real const& a);
65Real normal_cdf_raw(Real const& x);
66Real normal_pdf_raw(Real const& x);
67
69
74inline Real dev0(Real const& a, Real const& b)
75{
76 // special values
77 if (a == 0.) return b;
78 if (b == a) return 0.;
79 // ratio
80 Real v = (a-b)/(a+b);
81 // small v -> use dl
82 if (std::abs(v)<0.125)
83 {
84 Real sum = (a-b)*v, ej = 2*a*v, term;
85 v = v*v;
86 int n =0;
87 do
88 { sum += (term = ((ej *= v) / ( ((++n)<<1) +1 ) ));}
89 while (std::abs(term) > std::abs(sum) * Arithmetic<Real>::epsilon());
90 return sum;
91 }
92 // else compute directly the result
93 return (a*log(double(a/b))+b-a);
94}
95
103inline Real b1(Real const& a, Real const& b, Real const& x, bool xm1)
104{
105 if (x == 0) return 0;
106 if (x == 1) return 0;
107 Real s = a+b, sx = s*x, sy = s*(1.-x);
108 return ( std::exp(- Const::_LNSQRT2PI_
109 + 0.5 * ( a<b ? std::log(a) + log1p(-a/s) : std::log(b) + log1p(-b/s))
111 - (xm1 ? dev0(a, sy)+dev0(b, sx) : dev0(a, sx)+dev0(b, sy))
112 )
113 );
114}
115
119inline Real g0(Real const& x)
120{
121 // special values
122 if (x == 0.) return 1.;
123 if (x == 1.) return 0.;
124 // general case
125 Real v = (x-1.)/(x+1.);
126 // if 7/9 < x < 9/7 use Taylor serie of log((1+v)/(1-v))
127 if (v < 0.125)
128 {
129 Real sum = (x-1)*v, ej = 2*x*v, term;
130 v = v*v;
131 int n =0;
132 do
133 { sum += (term = ( (ej *= v) /( ((++n)<<1) +1)));}
134 while (std::abs(term) > std::abs(sum) * Arithmetic<Real>::epsilon());
135 return sum;
136 }
137 // else compute directly
138 return x*Real(log(double(x)))-x + 1.;
139}
140
145inline Real log1p(Real const& x)
146{
147 // trivial values
148 if (x == 0.) return 0.;
149 if (x == -1.) return(-Arithmetic<Real>::infinity());
150 // small values
151 if (std::abs(x) < .375)
152 {
153 // create functor and compute the alternate serie
154 Serielog1p f(x);
155 return x * (1. - x * sumAlternateSerie(f));
156 }
157 // large values : compute directly the result
158 return log(1. + x);
159}
160
164inline Real expm1(Real const& x)
165{
166 // small values of x
167 if (std::abs(x) < Const::_LN2_)
168 {
169 // a + 1 != 1 -> use compute Taylor serie else use first order
170 // Taylor expansion S = x + (1/2!) x^2 + (1/3!) x^3 + ...
171 if (std::abs(x) > Arithmetic<Real>::epsilon())
172 {
173 Real term = x, sum =x, n =1.;
174 do
175 { sum += (term *= x/(++n));}
176 while (std::abs(term) > std::abs(sum) * Arithmetic<Real>::epsilon()) ;
177 return sum ;
178 }
179 else return (x / 2. + 1.) * x;
180 }
181 return exp(double(x))-1.;
182}
183
191inline Real beta_pdf_raw(Real const& x, Real const& a, Real const& b)
192{
193 // trivial cases
194 if (x < 0 || x > 1) return(0);
195 if (x == 0)
196 {
197 if(a > 1) return(0);
198 if(a < 1) return(Arithmetic<Real>::infinity());
199 return(b); // a == 1
200 }
201 if (x == 1)
202 {
203 if(b > 1) return(0);
204 if(b < 1) return(Arithmetic<Real>::infinity());
205 return(a); // b == 1
206 }
207 // limit cases with x \in (0,1)
208 if (a == 0 || b == 0) { return(0);}
209 // general case
210 Real s = a+b, sx = s*x, sy = s*(1.-x);
211 return ( std::exp(- Const::_LNSQRT2PI_
212 + 0.5 *( a<b ? std::log(a) + log1p(-a/s) : std::log(b) + log1p(-b/s))
214 - dev0(a, sx) - dev0(b, sy)
215 - std::log(x) - log1p(-x)
216 )
217 );
218}
219
228inline Real binomial_pdf_raw(Real const& x, Real const& n, Real const& p)
229{
230 // trivial and limit cases
231 if (p == 0) return ((x == 0) ? 1 : 0);
232 if (p == 1) return ((x == n) ? 1 : 0);
233 if (x == 0) return ((n == 0) ? 1 : std::exp(n*log1p(-p)) );
234 if (x == n) return std::pow(p,n);
235 // other cases
236 Real y = n-x;
237 return ( std::exp(- Const::_LNSQRT2PI_ - 0.5 *( std::log(x) + log1p(-x/n))
239 - dev0(x, n*p) - dev0(y, n- n*p)
240 )
241 );
242}
243
253inline Real binomial_pdf_raw(int x, int n, Real const& p)
254{ return binomial_pdf_raw(Real(x), Real(n), p);}
255
266inline Real binomial_lpdf_raw(Real const& x, Real const& n, Real const& p)
267{
268 // trivial and limit cases
269 if (p == 0) return((x == 0) ? 0 : -Arithmetic<Real>::infinity());
270 if (p == 1) return((x == n) ? 0 : -Arithmetic<Real>::infinity());
271 if (x == 0) return((n == 0) ? 0 : n*log1p(-p));
272 if (x == n) return(n*std::log(p));
273 // other cases
274 Real y = n-x;
275 return ( - Const::_LNSQRT2PI_ - 0.5 *( std::log(x) + log1p(-x/n))
277 - dev0(x, n*p) - dev0(y, n- n*p)
278 );
279}
280
292inline Real binomial_lpdf_raw(int x, int n, Real const& p)
293{
294 // trivial and limit cases
295 if (p == 0) return((x == 0) ? 0 : -Arithmetic<Real>::infinity());
296 if (p == 1) return((x == n) ? 0 : -Arithmetic<Real>::infinity());
297 if (x == 0) return((n == 0) ? 0 : n*log1p(-p));
298 if (x == n) return(n*std::log(p));
299 // other cases
300 int y = n-x;
301 return( - Const::_LNSQRT2PI_ - 0.5 *( std::log(x) + log1p(-x/(Real)n))
303 - dev0(x, n*p) - dev0(y, n - n*p)
304 );
305}
306
321inline Real poisson_pdf_raw(Real const& x, Real const& lambda)
322{
323 // check trivial values
324 if (x<0.) return( 0. );
325 // if lambda is 0, we have P(X=0) = 1
326 if (lambda==0.) return( (x==0.) ? 1. : 0. );
327 // special value
328 if (x==0.) return( Real(std::exp(-lambda)) );
329 // stirling approximation and deviance
330 return( std::exp(-lgammaStirlingError(x)-dev0(x, lambda))/(Const::_SQRT2PI_*std::sqrt(x)));
331}
332
347inline Real poisson_pdf_raw(int x, Real const& lambda)
348{ return poisson_pdf_raw(Real(x), lambda);}
349
364inline Real poisson_lpdf_raw(Real const& x, Real const& lambda)
365{
366 // check trivial values
367 if (x<0.) return( -Arithmetic<Real>::infinity() );
368 // if lambda is 0, we have P(X=0) = 1
369 if (lambda==0.) return( (x==0.) ? 0 : -Arithmetic<Real>::infinity() );
370 // special value
371 if (x==0.) return( -lambda );
372 // stirling approximation and deviance
373 return( -lgammaStirlingError(x)-dev0(x, lambda)-Const::_LNSQRT2PI_-std::log(x)/2.);
374}
375
390inline Real poisson_lpdf_raw(int x, Real const& lambda)
391{ return poisson_lpdf_raw(Real(x), lambda);}
392
401inline Real erf_raw(Real const& a)
402{
403 Real T[5] =
404 { 9.60497373987051638749E0,
405 9.00260197203842689217E1,
406 2.23200534594684319226E3,
407 7.00332514112805075473E3,
408 5.55923013010394962768E4
409 };
410 Real U[5] =
411 {
412 /* 1.00000000000000000000E0,*/
413 3.35617141647503099647E1,
414 5.21357949780152679795E2,
415 4.59432382970980127987E3,
416 2.26290000613890934246E4,
417 4.92673942608635921086E4
418 };
419 if ( std::abs(a)> 1.0) return ( 1.0 - erfc(a) );
420 Real z = a * a;
421 return a * evalPolynomial<4>( z, T)
422 / evalPolynomial1<5>( z, U);
423}
424
433inline Real erfc_raw(Real const& a)
434{
435 Real P[9] =
436 { 2.46196981473530512524E-10,
437 5.64189564831068821977E-1,
438 7.46321056442269912687E0,
439 4.86371970985681366614E1,
440 1.96520832956077098242E2,
441 5.26445194995477358631E2,
442 9.34528527171957607540E2,
443 1.02755188689515710272E3,
444 5.57535335369399327526E2
445 };
446 Real Q[8] =
447 {
448 /* 1.00000000000000000000E0,*/
449 1.32281951154744992508E1,
450 8.67072140885989742329E1,
451 3.54937778887819891062E2,
452 9.75708501743205489753E2,
453 1.82390916687909736289E3,
454 2.24633760818710981792E3,
455 1.65666309194161350182E3,
456 5.57535340817727675546E2
457 };
458 Real R[6] =
459 { 5.64189583547755073984E-1,
460 1.27536670759978104416E0,
461 5.01905042251180477414E0,
462 6.16021097993053585195E0,
463 7.40974269950448939160E0,
464 2.97886665372100240670E0
465 };
466 Real S[6] =
467 {
468 /* 1.00000000000000000000E0,*/
469 2.26052863220117276590E0,
470 9.39603524938001434673E0,
471 1.20489539808096656605E1,
472 1.70814450747565897222E1,
473 9.60896809063285878198E0,
474 3.36907645100081516050E0
475 };
476 Real x = std::abs(a);
477 if ( x < 1.0) return ( 1.0 - erf_raw(a) );
478 Real z = exp(-a * a);
479 Real y = ( x < 8.0) ? (z * evalPolynomial<8>(x, P))/evalPolynomial1<8>(x, Q)
480 : (z * evalPolynomial<5>(x, R))/evalPolynomial1<6>(x, S);
481 return (a < 0) ? 2.0 - y : y;
482}
483
498inline Real normal_cdf_raw(Real const& x)
499{
500 Real t = x * Const::_1_SQRT2_, z = std::abs(t);
501 if ( z < Const::_1_SQRT2_) return 0.5 + 0.5 * erf(t);
502 Real y = 0.5 * erfc(z);
503 return ( t > 0) ? 1. - y : y;
504}
505
514inline Real normal_pdf_raw(Real const& x)
515{ return Const::_1_SQRT2PI_ * exp(-0.5 * x * x);}
516
542inline Real psi_raw( Real x)
543{
544 // special value
545 if (x==1.) return -Const::_EULER_;
546 Real y, nz = 0.0, p = std::floor(x);
547 bool negative = false;
548 if( x < 0.0 ) // use reflection formula
549 {
550 negative = true;
551 // Remove the zeros of tan(pi x) by subtracting the nearest integer from x
552 if( (nz = x - p) != 0.5 )
553 {
554 if( nz > 0.5 ) { nz = x - p - 1.;}
555 nz = Const::_PI_/std::tan(Const::_PI_*nz);
556 }
557 x = 1.0 - x;
558 }
559 // check for positive integer up to 20
560 if( (x <= 20.0) && (x == p) )
561 {
562 y = 0.0;
563 for( int i=int(x)-1; i>1; i-- ) { y += 1.0/(Real)i; }
564 y += -Const::_EULER_ + 1.;
565 }
566 else // not integer or greater than 20
567 {
568 Real w = 0.0;
569 while( x < 10.0 ) // shift to
570 {
571 w += 1.0/x;
572 x += 1.0;
573 }
574 Real z = 1.0/(x * x);
575 y = std::log(x) - (0.5/x)
577 }
578 return (negative) ? y - nz : y;
579}
580
581} // namespace Funct
582
583} // namespace STK
584
585#endif // STK_FUNCT_RAW_H
In this file we give some template generic algorithms.
In this file we declare usual Real functions.
In this file we declare functions around the gamma function.
const double b1
This Series computes.
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 binomial_pdf_raw(Real const &x, Real const &n, Real const &p)
Compute the generalized binomial probability mass function.
Real log1p(Real const &x)
compute the function .
Real expm1(Real const &x)
compute the function .
Real beta_pdf_raw(Real const &x, Real const &a, Real const &b)
Compute the beta density function.
Real erf_raw(Real const &a)
Compute the error function erf(a) Compute the function.
Real normal_pdf_raw(Real const &x)
compute the probability distribution function of the normal density.
Real sumAlternateSerie(const ISerie< Serie > &f, int const &n=0)
Sum an alternating series using the Chebichev polynomials.
Definition STK_Algo.h:65
Real poisson_pdf_raw(Real const &x, Real const &lambda)
Compute the Poisson density.
Real lgammaStirlingError(Real const &z)
Compute the error when we compute using the Stirling's formula.
Real normal_cdf_raw(Real const &x)
Compute the cumulative distribution function of the normal density.
Real binomial_lpdf_raw(Real const &x, Real const &n, Real const &p)
Compute the generalized binomial log-probability mass function.
Real psi_raw(Real x)
Compute the psi function.
Real erfc_raw(Real const &a)
Compute the complementary error function erfc(a) Compute the function.
Real g0(Real const &x)
compute the partial deviance .
Real poisson_lpdf_raw(Real const &x, Real const &lambda)
Compute the log-poisson density.
Arrays::SumOp< Lhs, Rhs >::result_type sum(Lhs const &lhs, Rhs const &rhs)
convenience function for summing two arrays
double Real
STK fundamental type of Real values.
const Real bernouilliNumbersArrayDivBy2K[7]
The Bernouilli numbers divided by 2k.
The namespace STK is the main domain space of the Statistical ToolKit project.
Arithmetic properties of STK fundamental types.