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