1*e4b17023SJohn Marino // Special functions -*- C++ -*- 2*e4b17023SJohn Marino 3*e4b17023SJohn Marino // Copyright (C) 2006, 2007, 2008, 2009, 2010 4*e4b17023SJohn Marino // Free Software Foundation, Inc. 5*e4b17023SJohn Marino // 6*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library. This library is free 7*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the 8*e4b17023SJohn Marino // terms of the GNU General Public License as published by the 9*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option) 10*e4b17023SJohn Marino // any later version. 11*e4b17023SJohn Marino // 12*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful, 13*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of 14*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*e4b17023SJohn Marino // GNU General Public License for more details. 16*e4b17023SJohn Marino // 17*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional 18*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version 19*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation. 20*e4b17023SJohn Marino 21*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and 22*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program; 23*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>. 25*e4b17023SJohn Marino 26*e4b17023SJohn Marino /** @file tr1/hypergeometric.tcc 27*e4b17023SJohn Marino * This is an internal header file, included by other library headers. 28*e4b17023SJohn Marino * Do not attempt to use it directly. @headername{tr1/cmath} 29*e4b17023SJohn Marino */ 30*e4b17023SJohn Marino 31*e4b17023SJohn Marino // 32*e4b17023SJohn Marino // ISO C++ 14882 TR1: 5.2 Special functions 33*e4b17023SJohn Marino // 34*e4b17023SJohn Marino 35*e4b17023SJohn Marino // Written by Edward Smith-Rowland based: 36*e4b17023SJohn Marino // (1) Handbook of Mathematical Functions, 37*e4b17023SJohn Marino // ed. Milton Abramowitz and Irene A. Stegun, 38*e4b17023SJohn Marino // Dover Publications, 39*e4b17023SJohn Marino // Section 6, pp. 555-566 40*e4b17023SJohn Marino // (2) The Gnu Scientific Library, http://www.gnu.org/software/gsl 41*e4b17023SJohn Marino 42*e4b17023SJohn Marino #ifndef _GLIBCXX_TR1_HYPERGEOMETRIC_TCC 43*e4b17023SJohn Marino #define _GLIBCXX_TR1_HYPERGEOMETRIC_TCC 1 44*e4b17023SJohn Marino 45*e4b17023SJohn Marino namespace std _GLIBCXX_VISIBILITY(default) 46*e4b17023SJohn Marino { 47*e4b17023SJohn Marino namespace tr1 48*e4b17023SJohn Marino { 49*e4b17023SJohn Marino // [5.2] Special functions 50*e4b17023SJohn Marino 51*e4b17023SJohn Marino // Implementation-space details. 52*e4b17023SJohn Marino namespace __detail 53*e4b17023SJohn Marino { 54*e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION 55*e4b17023SJohn Marino 56*e4b17023SJohn Marino /** 57*e4b17023SJohn Marino * @brief This routine returns the confluent hypergeometric function 58*e4b17023SJohn Marino * by series expansion. 59*e4b17023SJohn Marino * 60*e4b17023SJohn Marino * @f[ 61*e4b17023SJohn Marino * _1F_1(a;c;x) = \frac{\Gamma(c)}{\Gamma(a)} 62*e4b17023SJohn Marino * \sum_{n=0}^{\infty} 63*e4b17023SJohn Marino * \frac{\Gamma(a+n)}{\Gamma(c+n)} 64*e4b17023SJohn Marino * \frac{x^n}{n!} 65*e4b17023SJohn Marino * @f] 66*e4b17023SJohn Marino * 67*e4b17023SJohn Marino * If a and b are integers and a < 0 and either b > 0 or b < a 68*e4b17023SJohn Marino * then the series is a polynomial with a finite number of 69*e4b17023SJohn Marino * terms. If b is an integer and b <= 0 the confluent 70*e4b17023SJohn Marino * hypergeometric function is undefined. 71*e4b17023SJohn Marino * 72*e4b17023SJohn Marino * @param __a The "numerator" parameter. 73*e4b17023SJohn Marino * @param __c The "denominator" parameter. 74*e4b17023SJohn Marino * @param __x The argument of the confluent hypergeometric function. 75*e4b17023SJohn Marino * @return The confluent hypergeometric function. 76*e4b17023SJohn Marino */ 77*e4b17023SJohn Marino template<typename _Tp> 78*e4b17023SJohn Marino _Tp __conf_hyperg_series(const _Tp __a,const _Tp __c,const _Tp __x)79*e4b17023SJohn Marino __conf_hyperg_series(const _Tp __a, const _Tp __c, const _Tp __x) 80*e4b17023SJohn Marino { 81*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 82*e4b17023SJohn Marino 83*e4b17023SJohn Marino _Tp __term = _Tp(1); 84*e4b17023SJohn Marino _Tp __Fac = _Tp(1); 85*e4b17023SJohn Marino const unsigned int __max_iter = 100000; 86*e4b17023SJohn Marino unsigned int __i; 87*e4b17023SJohn Marino for (__i = 0; __i < __max_iter; ++__i) 88*e4b17023SJohn Marino { 89*e4b17023SJohn Marino __term *= (__a + _Tp(__i)) * __x 90*e4b17023SJohn Marino / ((__c + _Tp(__i)) * _Tp(1 + __i)); 91*e4b17023SJohn Marino if (std::abs(__term) < __eps) 92*e4b17023SJohn Marino { 93*e4b17023SJohn Marino break; 94*e4b17023SJohn Marino } 95*e4b17023SJohn Marino __Fac += __term; 96*e4b17023SJohn Marino } 97*e4b17023SJohn Marino if (__i == __max_iter) 98*e4b17023SJohn Marino std::__throw_runtime_error(__N("Series failed to converge " 99*e4b17023SJohn Marino "in __conf_hyperg_series.")); 100*e4b17023SJohn Marino 101*e4b17023SJohn Marino return __Fac; 102*e4b17023SJohn Marino } 103*e4b17023SJohn Marino 104*e4b17023SJohn Marino 105*e4b17023SJohn Marino /** 106*e4b17023SJohn Marino * @brief Return the hypogeometric function @f$ _2F_1(a,b;c;x) @f$ 107*e4b17023SJohn Marino * by an iterative procedure described in 108*e4b17023SJohn Marino * Luke, Algorithms for the Computation of Mathematical Functions. 109*e4b17023SJohn Marino * 110*e4b17023SJohn Marino * Like the case of the 2F1 rational approximations, these are 111*e4b17023SJohn Marino * probably guaranteed to converge for x < 0, barring gross 112*e4b17023SJohn Marino * numerical instability in the pre-asymptotic regime. 113*e4b17023SJohn Marino */ 114*e4b17023SJohn Marino template<typename _Tp> 115*e4b17023SJohn Marino _Tp __conf_hyperg_luke(const _Tp __a,const _Tp __c,const _Tp __xin)116*e4b17023SJohn Marino __conf_hyperg_luke(const _Tp __a, const _Tp __c, const _Tp __xin) 117*e4b17023SJohn Marino { 118*e4b17023SJohn Marino const _Tp __big = std::pow(std::numeric_limits<_Tp>::max(), _Tp(0.16L)); 119*e4b17023SJohn Marino const int __nmax = 20000; 120*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 121*e4b17023SJohn Marino const _Tp __x = -__xin; 122*e4b17023SJohn Marino const _Tp __x3 = __x * __x * __x; 123*e4b17023SJohn Marino const _Tp __t0 = __a / __c; 124*e4b17023SJohn Marino const _Tp __t1 = (__a + _Tp(1)) / (_Tp(2) * __c); 125*e4b17023SJohn Marino const _Tp __t2 = (__a + _Tp(2)) / (_Tp(2) * (__c + _Tp(1))); 126*e4b17023SJohn Marino _Tp __F = _Tp(1); 127*e4b17023SJohn Marino _Tp __prec; 128*e4b17023SJohn Marino 129*e4b17023SJohn Marino _Tp __Bnm3 = _Tp(1); 130*e4b17023SJohn Marino _Tp __Bnm2 = _Tp(1) + __t1 * __x; 131*e4b17023SJohn Marino _Tp __Bnm1 = _Tp(1) + __t2 * __x * (_Tp(1) + __t1 / _Tp(3) * __x); 132*e4b17023SJohn Marino 133*e4b17023SJohn Marino _Tp __Anm3 = _Tp(1); 134*e4b17023SJohn Marino _Tp __Anm2 = __Bnm2 - __t0 * __x; 135*e4b17023SJohn Marino _Tp __Anm1 = __Bnm1 - __t0 * (_Tp(1) + __t2 * __x) * __x 136*e4b17023SJohn Marino + __t0 * __t1 * (__c / (__c + _Tp(1))) * __x * __x; 137*e4b17023SJohn Marino 138*e4b17023SJohn Marino int __n = 3; 139*e4b17023SJohn Marino while(1) 140*e4b17023SJohn Marino { 141*e4b17023SJohn Marino _Tp __npam1 = _Tp(__n - 1) + __a; 142*e4b17023SJohn Marino _Tp __npcm1 = _Tp(__n - 1) + __c; 143*e4b17023SJohn Marino _Tp __npam2 = _Tp(__n - 2) + __a; 144*e4b17023SJohn Marino _Tp __npcm2 = _Tp(__n - 2) + __c; 145*e4b17023SJohn Marino _Tp __tnm1 = _Tp(2 * __n - 1); 146*e4b17023SJohn Marino _Tp __tnm3 = _Tp(2 * __n - 3); 147*e4b17023SJohn Marino _Tp __tnm5 = _Tp(2 * __n - 5); 148*e4b17023SJohn Marino _Tp __F1 = (_Tp(__n - 2) - __a) / (_Tp(2) * __tnm3 * __npcm1); 149*e4b17023SJohn Marino _Tp __F2 = (_Tp(__n) + __a) * __npam1 150*e4b17023SJohn Marino / (_Tp(4) * __tnm1 * __tnm3 * __npcm2 * __npcm1); 151*e4b17023SJohn Marino _Tp __F3 = -__npam2 * __npam1 * (_Tp(__n - 2) - __a) 152*e4b17023SJohn Marino / (_Tp(8) * __tnm3 * __tnm3 * __tnm5 153*e4b17023SJohn Marino * (_Tp(__n - 3) + __c) * __npcm2 * __npcm1); 154*e4b17023SJohn Marino _Tp __E = -__npam1 * (_Tp(__n - 1) - __c) 155*e4b17023SJohn Marino / (_Tp(2) * __tnm3 * __npcm2 * __npcm1); 156*e4b17023SJohn Marino 157*e4b17023SJohn Marino _Tp __An = (_Tp(1) + __F1 * __x) * __Anm1 158*e4b17023SJohn Marino + (__E + __F2 * __x) * __x * __Anm2 + __F3 * __x3 * __Anm3; 159*e4b17023SJohn Marino _Tp __Bn = (_Tp(1) + __F1 * __x) * __Bnm1 160*e4b17023SJohn Marino + (__E + __F2 * __x) * __x * __Bnm2 + __F3 * __x3 * __Bnm3; 161*e4b17023SJohn Marino _Tp __r = __An / __Bn; 162*e4b17023SJohn Marino 163*e4b17023SJohn Marino __prec = std::abs((__F - __r) / __F); 164*e4b17023SJohn Marino __F = __r; 165*e4b17023SJohn Marino 166*e4b17023SJohn Marino if (__prec < __eps || __n > __nmax) 167*e4b17023SJohn Marino break; 168*e4b17023SJohn Marino 169*e4b17023SJohn Marino if (std::abs(__An) > __big || std::abs(__Bn) > __big) 170*e4b17023SJohn Marino { 171*e4b17023SJohn Marino __An /= __big; 172*e4b17023SJohn Marino __Bn /= __big; 173*e4b17023SJohn Marino __Anm1 /= __big; 174*e4b17023SJohn Marino __Bnm1 /= __big; 175*e4b17023SJohn Marino __Anm2 /= __big; 176*e4b17023SJohn Marino __Bnm2 /= __big; 177*e4b17023SJohn Marino __Anm3 /= __big; 178*e4b17023SJohn Marino __Bnm3 /= __big; 179*e4b17023SJohn Marino } 180*e4b17023SJohn Marino else if (std::abs(__An) < _Tp(1) / __big 181*e4b17023SJohn Marino || std::abs(__Bn) < _Tp(1) / __big) 182*e4b17023SJohn Marino { 183*e4b17023SJohn Marino __An *= __big; 184*e4b17023SJohn Marino __Bn *= __big; 185*e4b17023SJohn Marino __Anm1 *= __big; 186*e4b17023SJohn Marino __Bnm1 *= __big; 187*e4b17023SJohn Marino __Anm2 *= __big; 188*e4b17023SJohn Marino __Bnm2 *= __big; 189*e4b17023SJohn Marino __Anm3 *= __big; 190*e4b17023SJohn Marino __Bnm3 *= __big; 191*e4b17023SJohn Marino } 192*e4b17023SJohn Marino 193*e4b17023SJohn Marino ++__n; 194*e4b17023SJohn Marino __Bnm3 = __Bnm2; 195*e4b17023SJohn Marino __Bnm2 = __Bnm1; 196*e4b17023SJohn Marino __Bnm1 = __Bn; 197*e4b17023SJohn Marino __Anm3 = __Anm2; 198*e4b17023SJohn Marino __Anm2 = __Anm1; 199*e4b17023SJohn Marino __Anm1 = __An; 200*e4b17023SJohn Marino } 201*e4b17023SJohn Marino 202*e4b17023SJohn Marino if (__n >= __nmax) 203*e4b17023SJohn Marino std::__throw_runtime_error(__N("Iteration failed to converge " 204*e4b17023SJohn Marino "in __conf_hyperg_luke.")); 205*e4b17023SJohn Marino 206*e4b17023SJohn Marino return __F; 207*e4b17023SJohn Marino } 208*e4b17023SJohn Marino 209*e4b17023SJohn Marino 210*e4b17023SJohn Marino /** 211*e4b17023SJohn Marino * @brief Return the confluent hypogeometric function 212*e4b17023SJohn Marino * @f$ _1F_1(a;c;x) @f$. 213*e4b17023SJohn Marino * 214*e4b17023SJohn Marino * @todo Handle b == nonpositive integer blowup - return NaN. 215*e4b17023SJohn Marino * 216*e4b17023SJohn Marino * @param __a The @a numerator parameter. 217*e4b17023SJohn Marino * @param __c The @a denominator parameter. 218*e4b17023SJohn Marino * @param __x The argument of the confluent hypergeometric function. 219*e4b17023SJohn Marino * @return The confluent hypergeometric function. 220*e4b17023SJohn Marino */ 221*e4b17023SJohn Marino template<typename _Tp> 222*e4b17023SJohn Marino inline _Tp __conf_hyperg(const _Tp __a,const _Tp __c,const _Tp __x)223*e4b17023SJohn Marino __conf_hyperg(const _Tp __a, const _Tp __c, const _Tp __x) 224*e4b17023SJohn Marino { 225*e4b17023SJohn Marino #if _GLIBCXX_USE_C99_MATH_TR1 226*e4b17023SJohn Marino const _Tp __c_nint = std::tr1::nearbyint(__c); 227*e4b17023SJohn Marino #else 228*e4b17023SJohn Marino const _Tp __c_nint = static_cast<int>(__c + _Tp(0.5L)); 229*e4b17023SJohn Marino #endif 230*e4b17023SJohn Marino if (__isnan(__a) || __isnan(__c) || __isnan(__x)) 231*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 232*e4b17023SJohn Marino else if (__c_nint == __c && __c_nint <= 0) 233*e4b17023SJohn Marino return std::numeric_limits<_Tp>::infinity(); 234*e4b17023SJohn Marino else if (__a == _Tp(0)) 235*e4b17023SJohn Marino return _Tp(1); 236*e4b17023SJohn Marino else if (__c == __a) 237*e4b17023SJohn Marino return std::exp(__x); 238*e4b17023SJohn Marino else if (__x < _Tp(0)) 239*e4b17023SJohn Marino return __conf_hyperg_luke(__a, __c, __x); 240*e4b17023SJohn Marino else 241*e4b17023SJohn Marino return __conf_hyperg_series(__a, __c, __x); 242*e4b17023SJohn Marino } 243*e4b17023SJohn Marino 244*e4b17023SJohn Marino 245*e4b17023SJohn Marino /** 246*e4b17023SJohn Marino * @brief Return the hypogeometric function @f$ _2F_1(a,b;c;x) @f$ 247*e4b17023SJohn Marino * by series expansion. 248*e4b17023SJohn Marino * 249*e4b17023SJohn Marino * The hypogeometric function is defined by 250*e4b17023SJohn Marino * @f[ 251*e4b17023SJohn Marino * _2F_1(a,b;c;x) = \frac{\Gamma(c)}{\Gamma(a)\Gamma(b)} 252*e4b17023SJohn Marino * \sum_{n=0}^{\infty} 253*e4b17023SJohn Marino * \frac{\Gamma(a+n)\Gamma(b+n)}{\Gamma(c+n)} 254*e4b17023SJohn Marino * \frac{x^n}{n!} 255*e4b17023SJohn Marino * @f] 256*e4b17023SJohn Marino * 257*e4b17023SJohn Marino * This works and it's pretty fast. 258*e4b17023SJohn Marino * 259*e4b17023SJohn Marino * @param __a The first @a numerator parameter. 260*e4b17023SJohn Marino * @param __a The second @a numerator parameter. 261*e4b17023SJohn Marino * @param __c The @a denominator parameter. 262*e4b17023SJohn Marino * @param __x The argument of the confluent hypergeometric function. 263*e4b17023SJohn Marino * @return The confluent hypergeometric function. 264*e4b17023SJohn Marino */ 265*e4b17023SJohn Marino template<typename _Tp> 266*e4b17023SJohn Marino _Tp __hyperg_series(const _Tp __a,const _Tp __b,const _Tp __c,const _Tp __x)267*e4b17023SJohn Marino __hyperg_series(const _Tp __a, const _Tp __b, 268*e4b17023SJohn Marino const _Tp __c, const _Tp __x) 269*e4b17023SJohn Marino { 270*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 271*e4b17023SJohn Marino 272*e4b17023SJohn Marino _Tp __term = _Tp(1); 273*e4b17023SJohn Marino _Tp __Fabc = _Tp(1); 274*e4b17023SJohn Marino const unsigned int __max_iter = 100000; 275*e4b17023SJohn Marino unsigned int __i; 276*e4b17023SJohn Marino for (__i = 0; __i < __max_iter; ++__i) 277*e4b17023SJohn Marino { 278*e4b17023SJohn Marino __term *= (__a + _Tp(__i)) * (__b + _Tp(__i)) * __x 279*e4b17023SJohn Marino / ((__c + _Tp(__i)) * _Tp(1 + __i)); 280*e4b17023SJohn Marino if (std::abs(__term) < __eps) 281*e4b17023SJohn Marino { 282*e4b17023SJohn Marino break; 283*e4b17023SJohn Marino } 284*e4b17023SJohn Marino __Fabc += __term; 285*e4b17023SJohn Marino } 286*e4b17023SJohn Marino if (__i == __max_iter) 287*e4b17023SJohn Marino std::__throw_runtime_error(__N("Series failed to converge " 288*e4b17023SJohn Marino "in __hyperg_series.")); 289*e4b17023SJohn Marino 290*e4b17023SJohn Marino return __Fabc; 291*e4b17023SJohn Marino } 292*e4b17023SJohn Marino 293*e4b17023SJohn Marino 294*e4b17023SJohn Marino /** 295*e4b17023SJohn Marino * @brief Return the hypogeometric function @f$ _2F_1(a,b;c;x) @f$ 296*e4b17023SJohn Marino * by an iterative procedure described in 297*e4b17023SJohn Marino * Luke, Algorithms for the Computation of Mathematical Functions. 298*e4b17023SJohn Marino */ 299*e4b17023SJohn Marino template<typename _Tp> 300*e4b17023SJohn Marino _Tp __hyperg_luke(const _Tp __a,const _Tp __b,const _Tp __c,const _Tp __xin)301*e4b17023SJohn Marino __hyperg_luke(const _Tp __a, const _Tp __b, const _Tp __c, 302*e4b17023SJohn Marino const _Tp __xin) 303*e4b17023SJohn Marino { 304*e4b17023SJohn Marino const _Tp __big = std::pow(std::numeric_limits<_Tp>::max(), _Tp(0.16L)); 305*e4b17023SJohn Marino const int __nmax = 20000; 306*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 307*e4b17023SJohn Marino const _Tp __x = -__xin; 308*e4b17023SJohn Marino const _Tp __x3 = __x * __x * __x; 309*e4b17023SJohn Marino const _Tp __t0 = __a * __b / __c; 310*e4b17023SJohn Marino const _Tp __t1 = (__a + _Tp(1)) * (__b + _Tp(1)) / (_Tp(2) * __c); 311*e4b17023SJohn Marino const _Tp __t2 = (__a + _Tp(2)) * (__b + _Tp(2)) 312*e4b17023SJohn Marino / (_Tp(2) * (__c + _Tp(1))); 313*e4b17023SJohn Marino 314*e4b17023SJohn Marino _Tp __F = _Tp(1); 315*e4b17023SJohn Marino 316*e4b17023SJohn Marino _Tp __Bnm3 = _Tp(1); 317*e4b17023SJohn Marino _Tp __Bnm2 = _Tp(1) + __t1 * __x; 318*e4b17023SJohn Marino _Tp __Bnm1 = _Tp(1) + __t2 * __x * (_Tp(1) + __t1 / _Tp(3) * __x); 319*e4b17023SJohn Marino 320*e4b17023SJohn Marino _Tp __Anm3 = _Tp(1); 321*e4b17023SJohn Marino _Tp __Anm2 = __Bnm2 - __t0 * __x; 322*e4b17023SJohn Marino _Tp __Anm1 = __Bnm1 - __t0 * (_Tp(1) + __t2 * __x) * __x 323*e4b17023SJohn Marino + __t0 * __t1 * (__c / (__c + _Tp(1))) * __x * __x; 324*e4b17023SJohn Marino 325*e4b17023SJohn Marino int __n = 3; 326*e4b17023SJohn Marino while (1) 327*e4b17023SJohn Marino { 328*e4b17023SJohn Marino const _Tp __npam1 = _Tp(__n - 1) + __a; 329*e4b17023SJohn Marino const _Tp __npbm1 = _Tp(__n - 1) + __b; 330*e4b17023SJohn Marino const _Tp __npcm1 = _Tp(__n - 1) + __c; 331*e4b17023SJohn Marino const _Tp __npam2 = _Tp(__n - 2) + __a; 332*e4b17023SJohn Marino const _Tp __npbm2 = _Tp(__n - 2) + __b; 333*e4b17023SJohn Marino const _Tp __npcm2 = _Tp(__n - 2) + __c; 334*e4b17023SJohn Marino const _Tp __tnm1 = _Tp(2 * __n - 1); 335*e4b17023SJohn Marino const _Tp __tnm3 = _Tp(2 * __n - 3); 336*e4b17023SJohn Marino const _Tp __tnm5 = _Tp(2 * __n - 5); 337*e4b17023SJohn Marino const _Tp __n2 = __n * __n; 338*e4b17023SJohn Marino const _Tp __F1 = (_Tp(3) * __n2 + (__a + __b - _Tp(6)) * __n 339*e4b17023SJohn Marino + _Tp(2) - __a * __b - _Tp(2) * (__a + __b)) 340*e4b17023SJohn Marino / (_Tp(2) * __tnm3 * __npcm1); 341*e4b17023SJohn Marino const _Tp __F2 = -(_Tp(3) * __n2 - (__a + __b + _Tp(6)) * __n 342*e4b17023SJohn Marino + _Tp(2) - __a * __b) * __npam1 * __npbm1 343*e4b17023SJohn Marino / (_Tp(4) * __tnm1 * __tnm3 * __npcm2 * __npcm1); 344*e4b17023SJohn Marino const _Tp __F3 = (__npam2 * __npam1 * __npbm2 * __npbm1 345*e4b17023SJohn Marino * (_Tp(__n - 2) - __a) * (_Tp(__n - 2) - __b)) 346*e4b17023SJohn Marino / (_Tp(8) * __tnm3 * __tnm3 * __tnm5 347*e4b17023SJohn Marino * (_Tp(__n - 3) + __c) * __npcm2 * __npcm1); 348*e4b17023SJohn Marino const _Tp __E = -__npam1 * __npbm1 * (_Tp(__n - 1) - __c) 349*e4b17023SJohn Marino / (_Tp(2) * __tnm3 * __npcm2 * __npcm1); 350*e4b17023SJohn Marino 351*e4b17023SJohn Marino _Tp __An = (_Tp(1) + __F1 * __x) * __Anm1 352*e4b17023SJohn Marino + (__E + __F2 * __x) * __x * __Anm2 + __F3 * __x3 * __Anm3; 353*e4b17023SJohn Marino _Tp __Bn = (_Tp(1) + __F1 * __x) * __Bnm1 354*e4b17023SJohn Marino + (__E + __F2 * __x) * __x * __Bnm2 + __F3 * __x3 * __Bnm3; 355*e4b17023SJohn Marino const _Tp __r = __An / __Bn; 356*e4b17023SJohn Marino 357*e4b17023SJohn Marino const _Tp __prec = std::abs((__F - __r) / __F); 358*e4b17023SJohn Marino __F = __r; 359*e4b17023SJohn Marino 360*e4b17023SJohn Marino if (__prec < __eps || __n > __nmax) 361*e4b17023SJohn Marino break; 362*e4b17023SJohn Marino 363*e4b17023SJohn Marino if (std::abs(__An) > __big || std::abs(__Bn) > __big) 364*e4b17023SJohn Marino { 365*e4b17023SJohn Marino __An /= __big; 366*e4b17023SJohn Marino __Bn /= __big; 367*e4b17023SJohn Marino __Anm1 /= __big; 368*e4b17023SJohn Marino __Bnm1 /= __big; 369*e4b17023SJohn Marino __Anm2 /= __big; 370*e4b17023SJohn Marino __Bnm2 /= __big; 371*e4b17023SJohn Marino __Anm3 /= __big; 372*e4b17023SJohn Marino __Bnm3 /= __big; 373*e4b17023SJohn Marino } 374*e4b17023SJohn Marino else if (std::abs(__An) < _Tp(1) / __big 375*e4b17023SJohn Marino || std::abs(__Bn) < _Tp(1) / __big) 376*e4b17023SJohn Marino { 377*e4b17023SJohn Marino __An *= __big; 378*e4b17023SJohn Marino __Bn *= __big; 379*e4b17023SJohn Marino __Anm1 *= __big; 380*e4b17023SJohn Marino __Bnm1 *= __big; 381*e4b17023SJohn Marino __Anm2 *= __big; 382*e4b17023SJohn Marino __Bnm2 *= __big; 383*e4b17023SJohn Marino __Anm3 *= __big; 384*e4b17023SJohn Marino __Bnm3 *= __big; 385*e4b17023SJohn Marino } 386*e4b17023SJohn Marino 387*e4b17023SJohn Marino ++__n; 388*e4b17023SJohn Marino __Bnm3 = __Bnm2; 389*e4b17023SJohn Marino __Bnm2 = __Bnm1; 390*e4b17023SJohn Marino __Bnm1 = __Bn; 391*e4b17023SJohn Marino __Anm3 = __Anm2; 392*e4b17023SJohn Marino __Anm2 = __Anm1; 393*e4b17023SJohn Marino __Anm1 = __An; 394*e4b17023SJohn Marino } 395*e4b17023SJohn Marino 396*e4b17023SJohn Marino if (__n >= __nmax) 397*e4b17023SJohn Marino std::__throw_runtime_error(__N("Iteration failed to converge " 398*e4b17023SJohn Marino "in __hyperg_luke.")); 399*e4b17023SJohn Marino 400*e4b17023SJohn Marino return __F; 401*e4b17023SJohn Marino } 402*e4b17023SJohn Marino 403*e4b17023SJohn Marino 404*e4b17023SJohn Marino /** 405*e4b17023SJohn Marino * @brief Return the hypogeometric function @f$ _2F_1(a,b;c;x) @f$ 406*e4b17023SJohn Marino * by the reflection formulae in Abramowitz & Stegun formula 407*e4b17023SJohn Marino * 15.3.6 for d = c - a - b not integral and formula 15.3.11 for 408*e4b17023SJohn Marino * d = c - a - b integral. This assumes a, b, c != negative 409*e4b17023SJohn Marino * integer. 410*e4b17023SJohn Marino * 411*e4b17023SJohn Marino * The hypogeometric function is defined by 412*e4b17023SJohn Marino * @f[ 413*e4b17023SJohn Marino * _2F_1(a,b;c;x) = \frac{\Gamma(c)}{\Gamma(a)\Gamma(b)} 414*e4b17023SJohn Marino * \sum_{n=0}^{\infty} 415*e4b17023SJohn Marino * \frac{\Gamma(a+n)\Gamma(b+n)}{\Gamma(c+n)} 416*e4b17023SJohn Marino * \frac{x^n}{n!} 417*e4b17023SJohn Marino * @f] 418*e4b17023SJohn Marino * 419*e4b17023SJohn Marino * The reflection formula for nonintegral @f$ d = c - a - b @f$ is: 420*e4b17023SJohn Marino * @f[ 421*e4b17023SJohn Marino * _2F_1(a,b;c;x) = \frac{\Gamma(c)\Gamma(d)}{\Gamma(c-a)\Gamma(c-b)} 422*e4b17023SJohn Marino * _2F_1(a,b;1-d;1-x) 423*e4b17023SJohn Marino * + \frac{\Gamma(c)\Gamma(-d)}{\Gamma(a)\Gamma(b)} 424*e4b17023SJohn Marino * _2F_1(c-a,c-b;1+d;1-x) 425*e4b17023SJohn Marino * @f] 426*e4b17023SJohn Marino * 427*e4b17023SJohn Marino * The reflection formula for integral @f$ m = c - a - b @f$ is: 428*e4b17023SJohn Marino * @f[ 429*e4b17023SJohn Marino * _2F_1(a,b;a+b+m;x) = \frac{\Gamma(m)\Gamma(a+b+m)}{\Gamma(a+m)\Gamma(b+m)} 430*e4b17023SJohn Marino * \sum_{k=0}^{m-1} \frac{(m+a)_k(m+b)_k}{k!(1-m)_k} 431*e4b17023SJohn Marino * - 432*e4b17023SJohn Marino * @f] 433*e4b17023SJohn Marino */ 434*e4b17023SJohn Marino template<typename _Tp> 435*e4b17023SJohn Marino _Tp __hyperg_reflect(const _Tp __a,const _Tp __b,const _Tp __c,const _Tp __x)436*e4b17023SJohn Marino __hyperg_reflect(const _Tp __a, const _Tp __b, const _Tp __c, 437*e4b17023SJohn Marino const _Tp __x) 438*e4b17023SJohn Marino { 439*e4b17023SJohn Marino const _Tp __d = __c - __a - __b; 440*e4b17023SJohn Marino const int __intd = std::floor(__d + _Tp(0.5L)); 441*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 442*e4b17023SJohn Marino const _Tp __toler = _Tp(1000) * __eps; 443*e4b17023SJohn Marino const _Tp __log_max = std::log(std::numeric_limits<_Tp>::max()); 444*e4b17023SJohn Marino const bool __d_integer = (std::abs(__d - __intd) < __toler); 445*e4b17023SJohn Marino 446*e4b17023SJohn Marino if (__d_integer) 447*e4b17023SJohn Marino { 448*e4b17023SJohn Marino const _Tp __ln_omx = std::log(_Tp(1) - __x); 449*e4b17023SJohn Marino const _Tp __ad = std::abs(__d); 450*e4b17023SJohn Marino _Tp __F1, __F2; 451*e4b17023SJohn Marino 452*e4b17023SJohn Marino _Tp __d1, __d2; 453*e4b17023SJohn Marino if (__d >= _Tp(0)) 454*e4b17023SJohn Marino { 455*e4b17023SJohn Marino __d1 = __d; 456*e4b17023SJohn Marino __d2 = _Tp(0); 457*e4b17023SJohn Marino } 458*e4b17023SJohn Marino else 459*e4b17023SJohn Marino { 460*e4b17023SJohn Marino __d1 = _Tp(0); 461*e4b17023SJohn Marino __d2 = __d; 462*e4b17023SJohn Marino } 463*e4b17023SJohn Marino 464*e4b17023SJohn Marino const _Tp __lng_c = __log_gamma(__c); 465*e4b17023SJohn Marino 466*e4b17023SJohn Marino // Evaluate F1. 467*e4b17023SJohn Marino if (__ad < __eps) 468*e4b17023SJohn Marino { 469*e4b17023SJohn Marino // d = c - a - b = 0. 470*e4b17023SJohn Marino __F1 = _Tp(0); 471*e4b17023SJohn Marino } 472*e4b17023SJohn Marino else 473*e4b17023SJohn Marino { 474*e4b17023SJohn Marino 475*e4b17023SJohn Marino bool __ok_d1 = true; 476*e4b17023SJohn Marino _Tp __lng_ad, __lng_ad1, __lng_bd1; 477*e4b17023SJohn Marino __try 478*e4b17023SJohn Marino { 479*e4b17023SJohn Marino __lng_ad = __log_gamma(__ad); 480*e4b17023SJohn Marino __lng_ad1 = __log_gamma(__a + __d1); 481*e4b17023SJohn Marino __lng_bd1 = __log_gamma(__b + __d1); 482*e4b17023SJohn Marino } 483*e4b17023SJohn Marino __catch(...) 484*e4b17023SJohn Marino { 485*e4b17023SJohn Marino __ok_d1 = false; 486*e4b17023SJohn Marino } 487*e4b17023SJohn Marino 488*e4b17023SJohn Marino if (__ok_d1) 489*e4b17023SJohn Marino { 490*e4b17023SJohn Marino /* Gamma functions in the denominator are ok. 491*e4b17023SJohn Marino * Proceed with evaluation. 492*e4b17023SJohn Marino */ 493*e4b17023SJohn Marino _Tp __sum1 = _Tp(1); 494*e4b17023SJohn Marino _Tp __term = _Tp(1); 495*e4b17023SJohn Marino _Tp __ln_pre1 = __lng_ad + __lng_c + __d2 * __ln_omx 496*e4b17023SJohn Marino - __lng_ad1 - __lng_bd1; 497*e4b17023SJohn Marino 498*e4b17023SJohn Marino /* Do F1 sum. 499*e4b17023SJohn Marino */ 500*e4b17023SJohn Marino for (int __i = 1; __i < __ad; ++__i) 501*e4b17023SJohn Marino { 502*e4b17023SJohn Marino const int __j = __i - 1; 503*e4b17023SJohn Marino __term *= (__a + __d2 + __j) * (__b + __d2 + __j) 504*e4b17023SJohn Marino / (_Tp(1) + __d2 + __j) / __i * (_Tp(1) - __x); 505*e4b17023SJohn Marino __sum1 += __term; 506*e4b17023SJohn Marino } 507*e4b17023SJohn Marino 508*e4b17023SJohn Marino if (__ln_pre1 > __log_max) 509*e4b17023SJohn Marino std::__throw_runtime_error(__N("Overflow of gamma functions" 510*e4b17023SJohn Marino " in __hyperg_luke.")); 511*e4b17023SJohn Marino else 512*e4b17023SJohn Marino __F1 = std::exp(__ln_pre1) * __sum1; 513*e4b17023SJohn Marino } 514*e4b17023SJohn Marino else 515*e4b17023SJohn Marino { 516*e4b17023SJohn Marino // Gamma functions in the denominator were not ok. 517*e4b17023SJohn Marino // So the F1 term is zero. 518*e4b17023SJohn Marino __F1 = _Tp(0); 519*e4b17023SJohn Marino } 520*e4b17023SJohn Marino } // end F1 evaluation 521*e4b17023SJohn Marino 522*e4b17023SJohn Marino // Evaluate F2. 523*e4b17023SJohn Marino bool __ok_d2 = true; 524*e4b17023SJohn Marino _Tp __lng_ad2, __lng_bd2; 525*e4b17023SJohn Marino __try 526*e4b17023SJohn Marino { 527*e4b17023SJohn Marino __lng_ad2 = __log_gamma(__a + __d2); 528*e4b17023SJohn Marino __lng_bd2 = __log_gamma(__b + __d2); 529*e4b17023SJohn Marino } 530*e4b17023SJohn Marino __catch(...) 531*e4b17023SJohn Marino { 532*e4b17023SJohn Marino __ok_d2 = false; 533*e4b17023SJohn Marino } 534*e4b17023SJohn Marino 535*e4b17023SJohn Marino if (__ok_d2) 536*e4b17023SJohn Marino { 537*e4b17023SJohn Marino // Gamma functions in the denominator are ok. 538*e4b17023SJohn Marino // Proceed with evaluation. 539*e4b17023SJohn Marino const int __maxiter = 2000; 540*e4b17023SJohn Marino const _Tp __psi_1 = -__numeric_constants<_Tp>::__gamma_e(); 541*e4b17023SJohn Marino const _Tp __psi_1pd = __psi(_Tp(1) + __ad); 542*e4b17023SJohn Marino const _Tp __psi_apd1 = __psi(__a + __d1); 543*e4b17023SJohn Marino const _Tp __psi_bpd1 = __psi(__b + __d1); 544*e4b17023SJohn Marino 545*e4b17023SJohn Marino _Tp __psi_term = __psi_1 + __psi_1pd - __psi_apd1 546*e4b17023SJohn Marino - __psi_bpd1 - __ln_omx; 547*e4b17023SJohn Marino _Tp __fact = _Tp(1); 548*e4b17023SJohn Marino _Tp __sum2 = __psi_term; 549*e4b17023SJohn Marino _Tp __ln_pre2 = __lng_c + __d1 * __ln_omx 550*e4b17023SJohn Marino - __lng_ad2 - __lng_bd2; 551*e4b17023SJohn Marino 552*e4b17023SJohn Marino // Do F2 sum. 553*e4b17023SJohn Marino int __j; 554*e4b17023SJohn Marino for (__j = 1; __j < __maxiter; ++__j) 555*e4b17023SJohn Marino { 556*e4b17023SJohn Marino // Values for psi functions use recurrence; 557*e4b17023SJohn Marino // Abramowitz & Stegun 6.3.5 558*e4b17023SJohn Marino const _Tp __term1 = _Tp(1) / _Tp(__j) 559*e4b17023SJohn Marino + _Tp(1) / (__ad + __j); 560*e4b17023SJohn Marino const _Tp __term2 = _Tp(1) / (__a + __d1 + _Tp(__j - 1)) 561*e4b17023SJohn Marino + _Tp(1) / (__b + __d1 + _Tp(__j - 1)); 562*e4b17023SJohn Marino __psi_term += __term1 - __term2; 563*e4b17023SJohn Marino __fact *= (__a + __d1 + _Tp(__j - 1)) 564*e4b17023SJohn Marino * (__b + __d1 + _Tp(__j - 1)) 565*e4b17023SJohn Marino / ((__ad + __j) * __j) * (_Tp(1) - __x); 566*e4b17023SJohn Marino const _Tp __delta = __fact * __psi_term; 567*e4b17023SJohn Marino __sum2 += __delta; 568*e4b17023SJohn Marino if (std::abs(__delta) < __eps * std::abs(__sum2)) 569*e4b17023SJohn Marino break; 570*e4b17023SJohn Marino } 571*e4b17023SJohn Marino if (__j == __maxiter) 572*e4b17023SJohn Marino std::__throw_runtime_error(__N("Sum F2 failed to converge " 573*e4b17023SJohn Marino "in __hyperg_reflect")); 574*e4b17023SJohn Marino 575*e4b17023SJohn Marino if (__sum2 == _Tp(0)) 576*e4b17023SJohn Marino __F2 = _Tp(0); 577*e4b17023SJohn Marino else 578*e4b17023SJohn Marino __F2 = std::exp(__ln_pre2) * __sum2; 579*e4b17023SJohn Marino } 580*e4b17023SJohn Marino else 581*e4b17023SJohn Marino { 582*e4b17023SJohn Marino // Gamma functions in the denominator not ok. 583*e4b17023SJohn Marino // So the F2 term is zero. 584*e4b17023SJohn Marino __F2 = _Tp(0); 585*e4b17023SJohn Marino } // end F2 evaluation 586*e4b17023SJohn Marino 587*e4b17023SJohn Marino const _Tp __sgn_2 = (__intd % 2 == 1 ? -_Tp(1) : _Tp(1)); 588*e4b17023SJohn Marino const _Tp __F = __F1 + __sgn_2 * __F2; 589*e4b17023SJohn Marino 590*e4b17023SJohn Marino return __F; 591*e4b17023SJohn Marino } 592*e4b17023SJohn Marino else 593*e4b17023SJohn Marino { 594*e4b17023SJohn Marino // d = c - a - b not an integer. 595*e4b17023SJohn Marino 596*e4b17023SJohn Marino // These gamma functions appear in the denominator, so we 597*e4b17023SJohn Marino // catch their harmless domain errors and set the terms to zero. 598*e4b17023SJohn Marino bool __ok1 = true; 599*e4b17023SJohn Marino _Tp __sgn_g1ca = _Tp(0), __ln_g1ca = _Tp(0); 600*e4b17023SJohn Marino _Tp __sgn_g1cb = _Tp(0), __ln_g1cb = _Tp(0); 601*e4b17023SJohn Marino __try 602*e4b17023SJohn Marino { 603*e4b17023SJohn Marino __sgn_g1ca = __log_gamma_sign(__c - __a); 604*e4b17023SJohn Marino __ln_g1ca = __log_gamma(__c - __a); 605*e4b17023SJohn Marino __sgn_g1cb = __log_gamma_sign(__c - __b); 606*e4b17023SJohn Marino __ln_g1cb = __log_gamma(__c - __b); 607*e4b17023SJohn Marino } 608*e4b17023SJohn Marino __catch(...) 609*e4b17023SJohn Marino { 610*e4b17023SJohn Marino __ok1 = false; 611*e4b17023SJohn Marino } 612*e4b17023SJohn Marino 613*e4b17023SJohn Marino bool __ok2 = true; 614*e4b17023SJohn Marino _Tp __sgn_g2a = _Tp(0), __ln_g2a = _Tp(0); 615*e4b17023SJohn Marino _Tp __sgn_g2b = _Tp(0), __ln_g2b = _Tp(0); 616*e4b17023SJohn Marino __try 617*e4b17023SJohn Marino { 618*e4b17023SJohn Marino __sgn_g2a = __log_gamma_sign(__a); 619*e4b17023SJohn Marino __ln_g2a = __log_gamma(__a); 620*e4b17023SJohn Marino __sgn_g2b = __log_gamma_sign(__b); 621*e4b17023SJohn Marino __ln_g2b = __log_gamma(__b); 622*e4b17023SJohn Marino } 623*e4b17023SJohn Marino __catch(...) 624*e4b17023SJohn Marino { 625*e4b17023SJohn Marino __ok2 = false; 626*e4b17023SJohn Marino } 627*e4b17023SJohn Marino 628*e4b17023SJohn Marino const _Tp __sgn_gc = __log_gamma_sign(__c); 629*e4b17023SJohn Marino const _Tp __ln_gc = __log_gamma(__c); 630*e4b17023SJohn Marino const _Tp __sgn_gd = __log_gamma_sign(__d); 631*e4b17023SJohn Marino const _Tp __ln_gd = __log_gamma(__d); 632*e4b17023SJohn Marino const _Tp __sgn_gmd = __log_gamma_sign(-__d); 633*e4b17023SJohn Marino const _Tp __ln_gmd = __log_gamma(-__d); 634*e4b17023SJohn Marino 635*e4b17023SJohn Marino const _Tp __sgn1 = __sgn_gc * __sgn_gd * __sgn_g1ca * __sgn_g1cb; 636*e4b17023SJohn Marino const _Tp __sgn2 = __sgn_gc * __sgn_gmd * __sgn_g2a * __sgn_g2b; 637*e4b17023SJohn Marino 638*e4b17023SJohn Marino _Tp __pre1, __pre2; 639*e4b17023SJohn Marino if (__ok1 && __ok2) 640*e4b17023SJohn Marino { 641*e4b17023SJohn Marino _Tp __ln_pre1 = __ln_gc + __ln_gd - __ln_g1ca - __ln_g1cb; 642*e4b17023SJohn Marino _Tp __ln_pre2 = __ln_gc + __ln_gmd - __ln_g2a - __ln_g2b 643*e4b17023SJohn Marino + __d * std::log(_Tp(1) - __x); 644*e4b17023SJohn Marino if (__ln_pre1 < __log_max && __ln_pre2 < __log_max) 645*e4b17023SJohn Marino { 646*e4b17023SJohn Marino __pre1 = std::exp(__ln_pre1); 647*e4b17023SJohn Marino __pre2 = std::exp(__ln_pre2); 648*e4b17023SJohn Marino __pre1 *= __sgn1; 649*e4b17023SJohn Marino __pre2 *= __sgn2; 650*e4b17023SJohn Marino } 651*e4b17023SJohn Marino else 652*e4b17023SJohn Marino { 653*e4b17023SJohn Marino std::__throw_runtime_error(__N("Overflow of gamma functions " 654*e4b17023SJohn Marino "in __hyperg_reflect")); 655*e4b17023SJohn Marino } 656*e4b17023SJohn Marino } 657*e4b17023SJohn Marino else if (__ok1 && !__ok2) 658*e4b17023SJohn Marino { 659*e4b17023SJohn Marino _Tp __ln_pre1 = __ln_gc + __ln_gd - __ln_g1ca - __ln_g1cb; 660*e4b17023SJohn Marino if (__ln_pre1 < __log_max) 661*e4b17023SJohn Marino { 662*e4b17023SJohn Marino __pre1 = std::exp(__ln_pre1); 663*e4b17023SJohn Marino __pre1 *= __sgn1; 664*e4b17023SJohn Marino __pre2 = _Tp(0); 665*e4b17023SJohn Marino } 666*e4b17023SJohn Marino else 667*e4b17023SJohn Marino { 668*e4b17023SJohn Marino std::__throw_runtime_error(__N("Overflow of gamma functions " 669*e4b17023SJohn Marino "in __hyperg_reflect")); 670*e4b17023SJohn Marino } 671*e4b17023SJohn Marino } 672*e4b17023SJohn Marino else if (!__ok1 && __ok2) 673*e4b17023SJohn Marino { 674*e4b17023SJohn Marino _Tp __ln_pre2 = __ln_gc + __ln_gmd - __ln_g2a - __ln_g2b 675*e4b17023SJohn Marino + __d * std::log(_Tp(1) - __x); 676*e4b17023SJohn Marino if (__ln_pre2 < __log_max) 677*e4b17023SJohn Marino { 678*e4b17023SJohn Marino __pre1 = _Tp(0); 679*e4b17023SJohn Marino __pre2 = std::exp(__ln_pre2); 680*e4b17023SJohn Marino __pre2 *= __sgn2; 681*e4b17023SJohn Marino } 682*e4b17023SJohn Marino else 683*e4b17023SJohn Marino { 684*e4b17023SJohn Marino std::__throw_runtime_error(__N("Overflow of gamma functions " 685*e4b17023SJohn Marino "in __hyperg_reflect")); 686*e4b17023SJohn Marino } 687*e4b17023SJohn Marino } 688*e4b17023SJohn Marino else 689*e4b17023SJohn Marino { 690*e4b17023SJohn Marino __pre1 = _Tp(0); 691*e4b17023SJohn Marino __pre2 = _Tp(0); 692*e4b17023SJohn Marino std::__throw_runtime_error(__N("Underflow of gamma functions " 693*e4b17023SJohn Marino "in __hyperg_reflect")); 694*e4b17023SJohn Marino } 695*e4b17023SJohn Marino 696*e4b17023SJohn Marino const _Tp __F1 = __hyperg_series(__a, __b, _Tp(1) - __d, 697*e4b17023SJohn Marino _Tp(1) - __x); 698*e4b17023SJohn Marino const _Tp __F2 = __hyperg_series(__c - __a, __c - __b, _Tp(1) + __d, 699*e4b17023SJohn Marino _Tp(1) - __x); 700*e4b17023SJohn Marino 701*e4b17023SJohn Marino const _Tp __F = __pre1 * __F1 + __pre2 * __F2; 702*e4b17023SJohn Marino 703*e4b17023SJohn Marino return __F; 704*e4b17023SJohn Marino } 705*e4b17023SJohn Marino } 706*e4b17023SJohn Marino 707*e4b17023SJohn Marino 708*e4b17023SJohn Marino /** 709*e4b17023SJohn Marino * @brief Return the hypogeometric function @f$ _2F_1(a,b;c;x) @f$. 710*e4b17023SJohn Marino * 711*e4b17023SJohn Marino * The hypogeometric function is defined by 712*e4b17023SJohn Marino * @f[ 713*e4b17023SJohn Marino * _2F_1(a,b;c;x) = \frac{\Gamma(c)}{\Gamma(a)\Gamma(b)} 714*e4b17023SJohn Marino * \sum_{n=0}^{\infty} 715*e4b17023SJohn Marino * \frac{\Gamma(a+n)\Gamma(b+n)}{\Gamma(c+n)} 716*e4b17023SJohn Marino * \frac{x^n}{n!} 717*e4b17023SJohn Marino * @f] 718*e4b17023SJohn Marino * 719*e4b17023SJohn Marino * @param __a The first @a numerator parameter. 720*e4b17023SJohn Marino * @param __a The second @a numerator parameter. 721*e4b17023SJohn Marino * @param __c The @a denominator parameter. 722*e4b17023SJohn Marino * @param __x The argument of the confluent hypergeometric function. 723*e4b17023SJohn Marino * @return The confluent hypergeometric function. 724*e4b17023SJohn Marino */ 725*e4b17023SJohn Marino template<typename _Tp> 726*e4b17023SJohn Marino inline _Tp __hyperg(const _Tp __a,const _Tp __b,const _Tp __c,const _Tp __x)727*e4b17023SJohn Marino __hyperg(const _Tp __a, const _Tp __b, const _Tp __c, const _Tp __x) 728*e4b17023SJohn Marino { 729*e4b17023SJohn Marino #if _GLIBCXX_USE_C99_MATH_TR1 730*e4b17023SJohn Marino const _Tp __a_nint = std::tr1::nearbyint(__a); 731*e4b17023SJohn Marino const _Tp __b_nint = std::tr1::nearbyint(__b); 732*e4b17023SJohn Marino const _Tp __c_nint = std::tr1::nearbyint(__c); 733*e4b17023SJohn Marino #else 734*e4b17023SJohn Marino const _Tp __a_nint = static_cast<int>(__a + _Tp(0.5L)); 735*e4b17023SJohn Marino const _Tp __b_nint = static_cast<int>(__b + _Tp(0.5L)); 736*e4b17023SJohn Marino const _Tp __c_nint = static_cast<int>(__c + _Tp(0.5L)); 737*e4b17023SJohn Marino #endif 738*e4b17023SJohn Marino const _Tp __toler = _Tp(1000) * std::numeric_limits<_Tp>::epsilon(); 739*e4b17023SJohn Marino if (std::abs(__x) >= _Tp(1)) 740*e4b17023SJohn Marino std::__throw_domain_error(__N("Argument outside unit circle " 741*e4b17023SJohn Marino "in __hyperg.")); 742*e4b17023SJohn Marino else if (__isnan(__a) || __isnan(__b) 743*e4b17023SJohn Marino || __isnan(__c) || __isnan(__x)) 744*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 745*e4b17023SJohn Marino else if (__c_nint == __c && __c_nint <= _Tp(0)) 746*e4b17023SJohn Marino return std::numeric_limits<_Tp>::infinity(); 747*e4b17023SJohn Marino else if (std::abs(__c - __b) < __toler || std::abs(__c - __a) < __toler) 748*e4b17023SJohn Marino return std::pow(_Tp(1) - __x, __c - __a - __b); 749*e4b17023SJohn Marino else if (__a >= _Tp(0) && __b >= _Tp(0) && __c >= _Tp(0) 750*e4b17023SJohn Marino && __x >= _Tp(0) && __x < _Tp(0.995L)) 751*e4b17023SJohn Marino return __hyperg_series(__a, __b, __c, __x); 752*e4b17023SJohn Marino else if (std::abs(__a) < _Tp(10) && std::abs(__b) < _Tp(10)) 753*e4b17023SJohn Marino { 754*e4b17023SJohn Marino // For integer a and b the hypergeometric function is a 755*e4b17023SJohn Marino // finite polynomial. 756*e4b17023SJohn Marino if (__a < _Tp(0) && std::abs(__a - __a_nint) < __toler) 757*e4b17023SJohn Marino return __hyperg_series(__a_nint, __b, __c, __x); 758*e4b17023SJohn Marino else if (__b < _Tp(0) && std::abs(__b - __b_nint) < __toler) 759*e4b17023SJohn Marino return __hyperg_series(__a, __b_nint, __c, __x); 760*e4b17023SJohn Marino else if (__x < -_Tp(0.25L)) 761*e4b17023SJohn Marino return __hyperg_luke(__a, __b, __c, __x); 762*e4b17023SJohn Marino else if (__x < _Tp(0.5L)) 763*e4b17023SJohn Marino return __hyperg_series(__a, __b, __c, __x); 764*e4b17023SJohn Marino else 765*e4b17023SJohn Marino if (std::abs(__c) > _Tp(10)) 766*e4b17023SJohn Marino return __hyperg_series(__a, __b, __c, __x); 767*e4b17023SJohn Marino else 768*e4b17023SJohn Marino return __hyperg_reflect(__a, __b, __c, __x); 769*e4b17023SJohn Marino } 770*e4b17023SJohn Marino else 771*e4b17023SJohn Marino return __hyperg_luke(__a, __b, __c, __x); 772*e4b17023SJohn Marino } 773*e4b17023SJohn Marino 774*e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION 775*e4b17023SJohn Marino } // namespace std::tr1::__detail 776*e4b17023SJohn Marino } 777*e4b17023SJohn Marino } 778*e4b17023SJohn Marino 779*e4b17023SJohn Marino #endif // _GLIBCXX_TR1_HYPERGEOMETRIC_TCC 780