1 // Special functions -*- C++ -*- 2 3 // Copyright (C) 2006, 2007, 2008, 2009 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 3, or (at your option) 10 // any later version. 11 // 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 // 17 // Under Section 7 of GPL version 3, you are granted additional 18 // permissions described in the GCC Runtime Library Exception, version 19 // 3.1, as published by the Free Software Foundation. 20 21 // You should have received a copy of the GNU General Public License and 22 // a copy of the GCC Runtime Library Exception along with this program; 23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 // <http://www.gnu.org/licenses/>. 25 26 /** @file tr1/gamma.tcc 27 * This is an internal header file, included by other library headers. 28 * You should not attempt to use it directly. 29 */ 30 31 // 32 // ISO C++ 14882 TR1: 5.2 Special functions 33 // 34 35 // Written by Edward Smith-Rowland based on: 36 // (1) Handbook of Mathematical Functions, 37 // ed. Milton Abramowitz and Irene A. Stegun, 38 // Dover Publications, 39 // Section 6, pp. 253-266 40 // (2) The Gnu Scientific Library, http://www.gnu.org/software/gsl 41 // (3) Numerical Recipes in C, by W. H. Press, S. A. Teukolsky, 42 // W. T. Vetterling, B. P. Flannery, Cambridge University Press (1992), 43 // 2nd ed, pp. 213-216 44 // (4) Gamma, Exploring Euler's Constant, Julian Havil, 45 // Princeton, 2003. 46 47 #ifndef _TR1_GAMMA_TCC 48 #define _TR1_GAMMA_TCC 1 49 50 #include "special_function_util.h" 51 52 namespace std 53 { 54 namespace tr1 55 { 56 // Implementation-space details. 57 namespace __detail 58 { 59 60 /** 61 * @brief This returns Bernoulli numbers from a table or by summation 62 * for larger values. 63 * 64 * Recursion is unstable. 65 * 66 * @param __n the order n of the Bernoulli number. 67 * @return The Bernoulli number of order n. 68 */ 69 template <typename _Tp> 70 _Tp __bernoulli_series(unsigned int __n) 71 { 72 73 static const _Tp __num[28] = { 74 _Tp(1UL), -_Tp(1UL) / _Tp(2UL), 75 _Tp(1UL) / _Tp(6UL), _Tp(0UL), 76 -_Tp(1UL) / _Tp(30UL), _Tp(0UL), 77 _Tp(1UL) / _Tp(42UL), _Tp(0UL), 78 -_Tp(1UL) / _Tp(30UL), _Tp(0UL), 79 _Tp(5UL) / _Tp(66UL), _Tp(0UL), 80 -_Tp(691UL) / _Tp(2730UL), _Tp(0UL), 81 _Tp(7UL) / _Tp(6UL), _Tp(0UL), 82 -_Tp(3617UL) / _Tp(510UL), _Tp(0UL), 83 _Tp(43867UL) / _Tp(798UL), _Tp(0UL), 84 -_Tp(174611) / _Tp(330UL), _Tp(0UL), 85 _Tp(854513UL) / _Tp(138UL), _Tp(0UL), 86 -_Tp(236364091UL) / _Tp(2730UL), _Tp(0UL), 87 _Tp(8553103UL) / _Tp(6UL), _Tp(0UL) 88 }; 89 90 if (__n == 0) 91 return _Tp(1); 92 93 if (__n == 1) 94 return -_Tp(1) / _Tp(2); 95 96 // Take care of the rest of the odd ones. 97 if (__n % 2 == 1) 98 return _Tp(0); 99 100 // Take care of some small evens that are painful for the series. 101 if (__n < 28) 102 return __num[__n]; 103 104 105 _Tp __fact = _Tp(1); 106 if ((__n / 2) % 2 == 0) 107 __fact *= _Tp(-1); 108 for (unsigned int __k = 1; __k <= __n; ++__k) 109 __fact *= __k / (_Tp(2) * __numeric_constants<_Tp>::__pi()); 110 __fact *= _Tp(2); 111 112 _Tp __sum = _Tp(0); 113 for (unsigned int __i = 1; __i < 1000; ++__i) 114 { 115 _Tp __term = std::pow(_Tp(__i), -_Tp(__n)); 116 if (__term < std::numeric_limits<_Tp>::epsilon()) 117 break; 118 __sum += __term; 119 } 120 121 return __fact * __sum; 122 } 123 124 125 /** 126 * @brief This returns Bernoulli number \f$B_n\f$. 127 * 128 * @param __n the order n of the Bernoulli number. 129 * @return The Bernoulli number of order n. 130 */ 131 template<typename _Tp> 132 inline _Tp 133 __bernoulli(const int __n) 134 { 135 return __bernoulli_series<_Tp>(__n); 136 } 137 138 139 /** 140 * @brief Return \f$log(\Gamma(x))\f$ by asymptotic expansion 141 * with Bernoulli number coefficients. This is like 142 * Sterling's approximation. 143 * 144 * @param __x The argument of the log of the gamma function. 145 * @return The logarithm of the gamma function. 146 */ 147 template<typename _Tp> 148 _Tp 149 __log_gamma_bernoulli(const _Tp __x) 150 { 151 _Tp __lg = (__x - _Tp(0.5L)) * std::log(__x) - __x 152 + _Tp(0.5L) * std::log(_Tp(2) 153 * __numeric_constants<_Tp>::__pi()); 154 155 const _Tp __xx = __x * __x; 156 _Tp __help = _Tp(1) / __x; 157 for ( unsigned int __i = 1; __i < 20; ++__i ) 158 { 159 const _Tp __2i = _Tp(2 * __i); 160 __help /= __2i * (__2i - _Tp(1)) * __xx; 161 __lg += __bernoulli<_Tp>(2 * __i) * __help; 162 } 163 164 return __lg; 165 } 166 167 168 /** 169 * @brief Return \f$log(\Gamma(x))\f$ by the Lanczos method. 170 * This method dominates all others on the positive axis I think. 171 * 172 * @param __x The argument of the log of the gamma function. 173 * @return The logarithm of the gamma function. 174 */ 175 template<typename _Tp> 176 _Tp 177 __log_gamma_lanczos(const _Tp __x) 178 { 179 const _Tp __xm1 = __x - _Tp(1); 180 181 static const _Tp __lanczos_cheb_7[9] = { 182 _Tp( 0.99999999999980993227684700473478L), 183 _Tp( 676.520368121885098567009190444019L), 184 _Tp(-1259.13921672240287047156078755283L), 185 _Tp( 771.3234287776530788486528258894L), 186 _Tp(-176.61502916214059906584551354L), 187 _Tp( 12.507343278686904814458936853L), 188 _Tp(-0.13857109526572011689554707L), 189 _Tp( 9.984369578019570859563e-6L), 190 _Tp( 1.50563273514931155834e-7L) 191 }; 192 193 static const _Tp __LOGROOT2PI 194 = _Tp(0.9189385332046727417803297364056176L); 195 196 _Tp __sum = __lanczos_cheb_7[0]; 197 for(unsigned int __k = 1; __k < 9; ++__k) 198 __sum += __lanczos_cheb_7[__k] / (__xm1 + __k); 199 200 const _Tp __term1 = (__xm1 + _Tp(0.5L)) 201 * std::log((__xm1 + _Tp(7.5L)) 202 / __numeric_constants<_Tp>::__euler()); 203 const _Tp __term2 = __LOGROOT2PI + std::log(__sum); 204 const _Tp __result = __term1 + (__term2 - _Tp(7)); 205 206 return __result; 207 } 208 209 210 /** 211 * @brief Return \f$ log(|\Gamma(x)|) \f$. 212 * This will return values even for \f$ x < 0 \f$. 213 * To recover the sign of \f$ \Gamma(x) \f$ for 214 * any argument use @a __log_gamma_sign. 215 * 216 * @param __x The argument of the log of the gamma function. 217 * @return The logarithm of the gamma function. 218 */ 219 template<typename _Tp> 220 _Tp 221 __log_gamma(const _Tp __x) 222 { 223 if (__x > _Tp(0.5L)) 224 return __log_gamma_lanczos(__x); 225 else 226 { 227 const _Tp __sin_fact 228 = std::abs(std::sin(__numeric_constants<_Tp>::__pi() * __x)); 229 if (__sin_fact == _Tp(0)) 230 std::__throw_domain_error(__N("Argument is nonpositive integer " 231 "in __log_gamma")); 232 return __numeric_constants<_Tp>::__lnpi() 233 - std::log(__sin_fact) 234 - __log_gamma_lanczos(_Tp(1) - __x); 235 } 236 } 237 238 239 /** 240 * @brief Return the sign of \f$ \Gamma(x) \f$. 241 * At nonpositive integers zero is returned. 242 * 243 * @param __x The argument of the gamma function. 244 * @return The sign of the gamma function. 245 */ 246 template<typename _Tp> 247 _Tp 248 __log_gamma_sign(const _Tp __x) 249 { 250 if (__x > _Tp(0)) 251 return _Tp(1); 252 else 253 { 254 const _Tp __sin_fact 255 = std::sin(__numeric_constants<_Tp>::__pi() * __x); 256 if (__sin_fact > _Tp(0)) 257 return (1); 258 else if (__sin_fact < _Tp(0)) 259 return -_Tp(1); 260 else 261 return _Tp(0); 262 } 263 } 264 265 266 /** 267 * @brief Return the logarithm of the binomial coefficient. 268 * The binomial coefficient is given by: 269 * @f[ 270 * \left( \right) = \frac{n!}{(n-k)! k!} 271 * @f] 272 * 273 * @param __n The first argument of the binomial coefficient. 274 * @param __k The second argument of the binomial coefficient. 275 * @return The binomial coefficient. 276 */ 277 template<typename _Tp> 278 _Tp 279 __log_bincoef(const unsigned int __n, const unsigned int __k) 280 { 281 // Max e exponent before overflow. 282 static const _Tp __max_bincoeff 283 = std::numeric_limits<_Tp>::max_exponent10 284 * std::log(_Tp(10)) - _Tp(1); 285 #if _GLIBCXX_USE_C99_MATH_TR1 286 _Tp __coeff = std::tr1::lgamma(_Tp(1 + __n)) 287 - std::tr1::lgamma(_Tp(1 + __k)) 288 - std::tr1::lgamma(_Tp(1 + __n - __k)); 289 #else 290 _Tp __coeff = __log_gamma(_Tp(1 + __n)) 291 - __log_gamma(_Tp(1 + __k)) 292 - __log_gamma(_Tp(1 + __n - __k)); 293 #endif 294 } 295 296 297 /** 298 * @brief Return the binomial coefficient. 299 * The binomial coefficient is given by: 300 * @f[ 301 * \left( \right) = \frac{n!}{(n-k)! k!} 302 * @f] 303 * 304 * @param __n The first argument of the binomial coefficient. 305 * @param __k The second argument of the binomial coefficient. 306 * @return The binomial coefficient. 307 */ 308 template<typename _Tp> 309 _Tp 310 __bincoef(const unsigned int __n, const unsigned int __k) 311 { 312 // Max e exponent before overflow. 313 static const _Tp __max_bincoeff 314 = std::numeric_limits<_Tp>::max_exponent10 315 * std::log(_Tp(10)) - _Tp(1); 316 317 const _Tp __log_coeff = __log_bincoef<_Tp>(__n, __k); 318 if (__log_coeff > __max_bincoeff) 319 return std::numeric_limits<_Tp>::quiet_NaN(); 320 else 321 return std::exp(__log_coeff); 322 } 323 324 325 /** 326 * @brief Return \f$ \Gamma(x) \f$. 327 * 328 * @param __x The argument of the gamma function. 329 * @return The gamma function. 330 */ 331 template<typename _Tp> 332 inline _Tp 333 __gamma(const _Tp __x) 334 { 335 return std::exp(__log_gamma(__x)); 336 } 337 338 339 /** 340 * @brief Return the digamma function by series expansion. 341 * The digamma or @f$ \psi(x) @f$ function is defined by 342 * @f[ 343 * \psi(x) = \frac{\Gamma'(x)}{\Gamma(x)} 344 * @f] 345 * 346 * The series is given by: 347 * @f[ 348 * \psi(x) = -\gamma_E - \frac{1}{x} 349 * \sum_{k=1}^{\infty} \frac{x}{k(x + k)} 350 * @f] 351 */ 352 template<typename _Tp> 353 _Tp 354 __psi_series(const _Tp __x) 355 { 356 _Tp __sum = -__numeric_constants<_Tp>::__gamma_e() - _Tp(1) / __x; 357 const unsigned int __max_iter = 100000; 358 for (unsigned int __k = 1; __k < __max_iter; ++__k) 359 { 360 const _Tp __term = __x / (__k * (__k + __x)); 361 __sum += __term; 362 if (std::abs(__term / __sum) < std::numeric_limits<_Tp>::epsilon()) 363 break; 364 } 365 return __sum; 366 } 367 368 369 /** 370 * @brief Return the digamma function for large argument. 371 * The digamma or @f$ \psi(x) @f$ function is defined by 372 * @f[ 373 * \psi(x) = \frac{\Gamma'(x)}{\Gamma(x)} 374 * @f] 375 * 376 * The asymptotic series is given by: 377 * @f[ 378 * \psi(x) = \ln(x) - \frac{1}{2x} 379 * - \sum_{n=1}^{\infty} \frac{B_{2n}}{2 n x^{2n}} 380 * @f] 381 */ 382 template<typename _Tp> 383 _Tp 384 __psi_asymp(const _Tp __x) 385 { 386 _Tp __sum = std::log(__x) - _Tp(0.5L) / __x; 387 const _Tp __xx = __x * __x; 388 _Tp __xp = __xx; 389 const unsigned int __max_iter = 100; 390 for (unsigned int __k = 1; __k < __max_iter; ++__k) 391 { 392 const _Tp __term = __bernoulli<_Tp>(2 * __k) / (2 * __k * __xp); 393 __sum -= __term; 394 if (std::abs(__term / __sum) < std::numeric_limits<_Tp>::epsilon()) 395 break; 396 __xp *= __xx; 397 } 398 return __sum; 399 } 400 401 402 /** 403 * @brief Return the digamma function. 404 * The digamma or @f$ \psi(x) @f$ function is defined by 405 * @f[ 406 * \psi(x) = \frac{\Gamma'(x)}{\Gamma(x)} 407 * @f] 408 * For negative argument the reflection formula is used: 409 * @f[ 410 * \psi(x) = \psi(1-x) - \pi \cot(\pi x) 411 * @f] 412 */ 413 template<typename _Tp> 414 _Tp 415 __psi(const _Tp __x) 416 { 417 const int __n = static_cast<int>(__x + 0.5L); 418 const _Tp __eps = _Tp(4) * std::numeric_limits<_Tp>::epsilon(); 419 if (__n <= 0 && std::abs(__x - _Tp(__n)) < __eps) 420 return std::numeric_limits<_Tp>::quiet_NaN(); 421 else if (__x < _Tp(0)) 422 { 423 const _Tp __pi = __numeric_constants<_Tp>::__pi(); 424 return __psi(_Tp(1) - __x) 425 - __pi * std::cos(__pi * __x) / std::sin(__pi * __x); 426 } 427 else if (__x > _Tp(100)) 428 return __psi_asymp(__x); 429 else 430 return __psi_series(__x); 431 } 432 433 434 /** 435 * @brief Return the polygamma function @f$ \psi^{(n)}(x) @f$. 436 * 437 * The polygamma function is related to the Hurwitz zeta function: 438 * @f[ 439 * \psi^{(n)}(x) = (-1)^{n+1} m! \zeta(m+1,x) 440 * @f] 441 */ 442 template<typename _Tp> 443 _Tp 444 __psi(const unsigned int __n, const _Tp __x) 445 { 446 if (__x <= _Tp(0)) 447 std::__throw_domain_error(__N("Argument out of range " 448 "in __psi")); 449 else if (__n == 0) 450 return __psi(__x); 451 else 452 { 453 const _Tp __hzeta = __hurwitz_zeta(_Tp(__n + 1), __x); 454 #if _GLIBCXX_USE_C99_MATH_TR1 455 const _Tp __ln_nfact = std::tr1::lgamma(_Tp(__n + 1)); 456 #else 457 const _Tp __ln_nfact = __log_gamma(_Tp(__n + 1)); 458 #endif 459 _Tp __result = std::exp(__ln_nfact) * __hzeta; 460 if (__n % 2 == 1) 461 __result = -__result; 462 return __result; 463 } 464 } 465 466 } // namespace std::tr1::__detail 467 } 468 } 469 470 #endif // _TR1_GAMMA_TCC 471 472