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/ell_integral.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 on: 36*e4b17023SJohn Marino // (1) B. C. Carlson Numer. Math. 33, 1 (1979) 37*e4b17023SJohn Marino // (2) B. C. Carlson, Special Functions of Applied Mathematics (1977) 38*e4b17023SJohn Marino // (3) The Gnu Scientific Library, http://www.gnu.org/software/gsl 39*e4b17023SJohn Marino // (4) Numerical Recipes in C, 2nd ed, by W. H. Press, S. A. Teukolsky, 40*e4b17023SJohn Marino // W. T. Vetterling, B. P. Flannery, Cambridge University Press 41*e4b17023SJohn Marino // (1992), pp. 261-269 42*e4b17023SJohn Marino 43*e4b17023SJohn Marino #ifndef _GLIBCXX_TR1_ELL_INTEGRAL_TCC 44*e4b17023SJohn Marino #define _GLIBCXX_TR1_ELL_INTEGRAL_TCC 1 45*e4b17023SJohn Marino 46*e4b17023SJohn Marino namespace std _GLIBCXX_VISIBILITY(default) 47*e4b17023SJohn Marino { 48*e4b17023SJohn Marino namespace tr1 49*e4b17023SJohn Marino { 50*e4b17023SJohn Marino // [5.2] Special functions 51*e4b17023SJohn Marino 52*e4b17023SJohn Marino // Implementation-space details. 53*e4b17023SJohn Marino namespace __detail 54*e4b17023SJohn Marino { 55*e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION 56*e4b17023SJohn Marino 57*e4b17023SJohn Marino /** 58*e4b17023SJohn Marino * @brief Return the Carlson elliptic function @f$ R_F(x,y,z) @f$ 59*e4b17023SJohn Marino * of the first kind. 60*e4b17023SJohn Marino * 61*e4b17023SJohn Marino * The Carlson elliptic function of the first kind is defined by: 62*e4b17023SJohn Marino * @f[ 63*e4b17023SJohn Marino * R_F(x,y,z) = \frac{1}{2} \int_0^\infty 64*e4b17023SJohn Marino * \frac{dt}{(t + x)^{1/2}(t + y)^{1/2}(t + z)^{1/2}} 65*e4b17023SJohn Marino * @f] 66*e4b17023SJohn Marino * 67*e4b17023SJohn Marino * @param __x The first of three symmetric arguments. 68*e4b17023SJohn Marino * @param __y The second of three symmetric arguments. 69*e4b17023SJohn Marino * @param __z The third of three symmetric arguments. 70*e4b17023SJohn Marino * @return The Carlson elliptic function of the first kind. 71*e4b17023SJohn Marino */ 72*e4b17023SJohn Marino template<typename _Tp> 73*e4b17023SJohn Marino _Tp __ellint_rf(const _Tp __x,const _Tp __y,const _Tp __z)74*e4b17023SJohn Marino __ellint_rf(const _Tp __x, const _Tp __y, const _Tp __z) 75*e4b17023SJohn Marino { 76*e4b17023SJohn Marino const _Tp __min = std::numeric_limits<_Tp>::min(); 77*e4b17023SJohn Marino const _Tp __max = std::numeric_limits<_Tp>::max(); 78*e4b17023SJohn Marino const _Tp __lolim = _Tp(5) * __min; 79*e4b17023SJohn Marino const _Tp __uplim = __max / _Tp(5); 80*e4b17023SJohn Marino 81*e4b17023SJohn Marino if (__x < _Tp(0) || __y < _Tp(0) || __z < _Tp(0)) 82*e4b17023SJohn Marino std::__throw_domain_error(__N("Argument less than zero " 83*e4b17023SJohn Marino "in __ellint_rf.")); 84*e4b17023SJohn Marino else if (__x + __y < __lolim || __x + __z < __lolim 85*e4b17023SJohn Marino || __y + __z < __lolim) 86*e4b17023SJohn Marino std::__throw_domain_error(__N("Argument too small in __ellint_rf")); 87*e4b17023SJohn Marino else 88*e4b17023SJohn Marino { 89*e4b17023SJohn Marino const _Tp __c0 = _Tp(1) / _Tp(4); 90*e4b17023SJohn Marino const _Tp __c1 = _Tp(1) / _Tp(24); 91*e4b17023SJohn Marino const _Tp __c2 = _Tp(1) / _Tp(10); 92*e4b17023SJohn Marino const _Tp __c3 = _Tp(3) / _Tp(44); 93*e4b17023SJohn Marino const _Tp __c4 = _Tp(1) / _Tp(14); 94*e4b17023SJohn Marino 95*e4b17023SJohn Marino _Tp __xn = __x; 96*e4b17023SJohn Marino _Tp __yn = __y; 97*e4b17023SJohn Marino _Tp __zn = __z; 98*e4b17023SJohn Marino 99*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 100*e4b17023SJohn Marino const _Tp __errtol = std::pow(__eps, _Tp(1) / _Tp(6)); 101*e4b17023SJohn Marino _Tp __mu; 102*e4b17023SJohn Marino _Tp __xndev, __yndev, __zndev; 103*e4b17023SJohn Marino 104*e4b17023SJohn Marino const unsigned int __max_iter = 100; 105*e4b17023SJohn Marino for (unsigned int __iter = 0; __iter < __max_iter; ++__iter) 106*e4b17023SJohn Marino { 107*e4b17023SJohn Marino __mu = (__xn + __yn + __zn) / _Tp(3); 108*e4b17023SJohn Marino __xndev = 2 - (__mu + __xn) / __mu; 109*e4b17023SJohn Marino __yndev = 2 - (__mu + __yn) / __mu; 110*e4b17023SJohn Marino __zndev = 2 - (__mu + __zn) / __mu; 111*e4b17023SJohn Marino _Tp __epsilon = std::max(std::abs(__xndev), std::abs(__yndev)); 112*e4b17023SJohn Marino __epsilon = std::max(__epsilon, std::abs(__zndev)); 113*e4b17023SJohn Marino if (__epsilon < __errtol) 114*e4b17023SJohn Marino break; 115*e4b17023SJohn Marino const _Tp __xnroot = std::sqrt(__xn); 116*e4b17023SJohn Marino const _Tp __ynroot = std::sqrt(__yn); 117*e4b17023SJohn Marino const _Tp __znroot = std::sqrt(__zn); 118*e4b17023SJohn Marino const _Tp __lambda = __xnroot * (__ynroot + __znroot) 119*e4b17023SJohn Marino + __ynroot * __znroot; 120*e4b17023SJohn Marino __xn = __c0 * (__xn + __lambda); 121*e4b17023SJohn Marino __yn = __c0 * (__yn + __lambda); 122*e4b17023SJohn Marino __zn = __c0 * (__zn + __lambda); 123*e4b17023SJohn Marino } 124*e4b17023SJohn Marino 125*e4b17023SJohn Marino const _Tp __e2 = __xndev * __yndev - __zndev * __zndev; 126*e4b17023SJohn Marino const _Tp __e3 = __xndev * __yndev * __zndev; 127*e4b17023SJohn Marino const _Tp __s = _Tp(1) + (__c1 * __e2 - __c2 - __c3 * __e3) * __e2 128*e4b17023SJohn Marino + __c4 * __e3; 129*e4b17023SJohn Marino 130*e4b17023SJohn Marino return __s / std::sqrt(__mu); 131*e4b17023SJohn Marino } 132*e4b17023SJohn Marino } 133*e4b17023SJohn Marino 134*e4b17023SJohn Marino 135*e4b17023SJohn Marino /** 136*e4b17023SJohn Marino * @brief Return the complete elliptic integral of the first kind 137*e4b17023SJohn Marino * @f$ K(k) @f$ by series expansion. 138*e4b17023SJohn Marino * 139*e4b17023SJohn Marino * The complete elliptic integral of the first kind is defined as 140*e4b17023SJohn Marino * @f[ 141*e4b17023SJohn Marino * K(k) = F(k,\pi/2) = \int_0^{\pi/2}\frac{d\theta} 142*e4b17023SJohn Marino * {\sqrt{1 - k^2sin^2\theta}} 143*e4b17023SJohn Marino * @f] 144*e4b17023SJohn Marino * 145*e4b17023SJohn Marino * This routine is not bad as long as |k| is somewhat smaller than 1 146*e4b17023SJohn Marino * but is not is good as the Carlson elliptic integral formulation. 147*e4b17023SJohn Marino * 148*e4b17023SJohn Marino * @param __k The argument of the complete elliptic function. 149*e4b17023SJohn Marino * @return The complete elliptic function of the first kind. 150*e4b17023SJohn Marino */ 151*e4b17023SJohn Marino template<typename _Tp> 152*e4b17023SJohn Marino _Tp __comp_ellint_1_series(const _Tp __k)153*e4b17023SJohn Marino __comp_ellint_1_series(const _Tp __k) 154*e4b17023SJohn Marino { 155*e4b17023SJohn Marino 156*e4b17023SJohn Marino const _Tp __kk = __k * __k; 157*e4b17023SJohn Marino 158*e4b17023SJohn Marino _Tp __term = __kk / _Tp(4); 159*e4b17023SJohn Marino _Tp __sum = _Tp(1) + __term; 160*e4b17023SJohn Marino 161*e4b17023SJohn Marino const unsigned int __max_iter = 1000; 162*e4b17023SJohn Marino for (unsigned int __i = 2; __i < __max_iter; ++__i) 163*e4b17023SJohn Marino { 164*e4b17023SJohn Marino __term *= (2 * __i - 1) * __kk / (2 * __i); 165*e4b17023SJohn Marino if (__term < std::numeric_limits<_Tp>::epsilon()) 166*e4b17023SJohn Marino break; 167*e4b17023SJohn Marino __sum += __term; 168*e4b17023SJohn Marino } 169*e4b17023SJohn Marino 170*e4b17023SJohn Marino return __numeric_constants<_Tp>::__pi_2() * __sum; 171*e4b17023SJohn Marino } 172*e4b17023SJohn Marino 173*e4b17023SJohn Marino 174*e4b17023SJohn Marino /** 175*e4b17023SJohn Marino * @brief Return the complete elliptic integral of the first kind 176*e4b17023SJohn Marino * @f$ K(k) @f$ using the Carlson formulation. 177*e4b17023SJohn Marino * 178*e4b17023SJohn Marino * The complete elliptic integral of the first kind is defined as 179*e4b17023SJohn Marino * @f[ 180*e4b17023SJohn Marino * K(k) = F(k,\pi/2) = \int_0^{\pi/2}\frac{d\theta} 181*e4b17023SJohn Marino * {\sqrt{1 - k^2 sin^2\theta}} 182*e4b17023SJohn Marino * @f] 183*e4b17023SJohn Marino * where @f$ F(k,\phi) @f$ is the incomplete elliptic integral of the 184*e4b17023SJohn Marino * first kind. 185*e4b17023SJohn Marino * 186*e4b17023SJohn Marino * @param __k The argument of the complete elliptic function. 187*e4b17023SJohn Marino * @return The complete elliptic function of the first kind. 188*e4b17023SJohn Marino */ 189*e4b17023SJohn Marino template<typename _Tp> 190*e4b17023SJohn Marino _Tp __comp_ellint_1(const _Tp __k)191*e4b17023SJohn Marino __comp_ellint_1(const _Tp __k) 192*e4b17023SJohn Marino { 193*e4b17023SJohn Marino 194*e4b17023SJohn Marino if (__isnan(__k)) 195*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 196*e4b17023SJohn Marino else if (std::abs(__k) >= _Tp(1)) 197*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 198*e4b17023SJohn Marino else 199*e4b17023SJohn Marino return __ellint_rf(_Tp(0), _Tp(1) - __k * __k, _Tp(1)); 200*e4b17023SJohn Marino } 201*e4b17023SJohn Marino 202*e4b17023SJohn Marino 203*e4b17023SJohn Marino /** 204*e4b17023SJohn Marino * @brief Return the incomplete elliptic integral of the first kind 205*e4b17023SJohn Marino * @f$ F(k,\phi) @f$ using the Carlson formulation. 206*e4b17023SJohn Marino * 207*e4b17023SJohn Marino * The incomplete elliptic integral of the first kind is defined as 208*e4b17023SJohn Marino * @f[ 209*e4b17023SJohn Marino * F(k,\phi) = \int_0^{\phi}\frac{d\theta} 210*e4b17023SJohn Marino * {\sqrt{1 - k^2 sin^2\theta}} 211*e4b17023SJohn Marino * @f] 212*e4b17023SJohn Marino * 213*e4b17023SJohn Marino * @param __k The argument of the elliptic function. 214*e4b17023SJohn Marino * @param __phi The integral limit argument of the elliptic function. 215*e4b17023SJohn Marino * @return The elliptic function of the first kind. 216*e4b17023SJohn Marino */ 217*e4b17023SJohn Marino template<typename _Tp> 218*e4b17023SJohn Marino _Tp __ellint_1(const _Tp __k,const _Tp __phi)219*e4b17023SJohn Marino __ellint_1(const _Tp __k, const _Tp __phi) 220*e4b17023SJohn Marino { 221*e4b17023SJohn Marino 222*e4b17023SJohn Marino if (__isnan(__k) || __isnan(__phi)) 223*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 224*e4b17023SJohn Marino else if (std::abs(__k) > _Tp(1)) 225*e4b17023SJohn Marino std::__throw_domain_error(__N("Bad argument in __ellint_1.")); 226*e4b17023SJohn Marino else 227*e4b17023SJohn Marino { 228*e4b17023SJohn Marino // Reduce phi to -pi/2 < phi < +pi/2. 229*e4b17023SJohn Marino const int __n = std::floor(__phi / __numeric_constants<_Tp>::__pi() 230*e4b17023SJohn Marino + _Tp(0.5L)); 231*e4b17023SJohn Marino const _Tp __phi_red = __phi 232*e4b17023SJohn Marino - __n * __numeric_constants<_Tp>::__pi(); 233*e4b17023SJohn Marino 234*e4b17023SJohn Marino const _Tp __s = std::sin(__phi_red); 235*e4b17023SJohn Marino const _Tp __c = std::cos(__phi_red); 236*e4b17023SJohn Marino 237*e4b17023SJohn Marino const _Tp __F = __s 238*e4b17023SJohn Marino * __ellint_rf(__c * __c, 239*e4b17023SJohn Marino _Tp(1) - __k * __k * __s * __s, _Tp(1)); 240*e4b17023SJohn Marino 241*e4b17023SJohn Marino if (__n == 0) 242*e4b17023SJohn Marino return __F; 243*e4b17023SJohn Marino else 244*e4b17023SJohn Marino return __F + _Tp(2) * __n * __comp_ellint_1(__k); 245*e4b17023SJohn Marino } 246*e4b17023SJohn Marino } 247*e4b17023SJohn Marino 248*e4b17023SJohn Marino 249*e4b17023SJohn Marino /** 250*e4b17023SJohn Marino * @brief Return the complete elliptic integral of the second kind 251*e4b17023SJohn Marino * @f$ E(k) @f$ by series expansion. 252*e4b17023SJohn Marino * 253*e4b17023SJohn Marino * The complete elliptic integral of the second kind is defined as 254*e4b17023SJohn Marino * @f[ 255*e4b17023SJohn Marino * E(k,\pi/2) = \int_0^{\pi/2}\sqrt{1 - k^2 sin^2\theta} 256*e4b17023SJohn Marino * @f] 257*e4b17023SJohn Marino * 258*e4b17023SJohn Marino * This routine is not bad as long as |k| is somewhat smaller than 1 259*e4b17023SJohn Marino * but is not is good as the Carlson elliptic integral formulation. 260*e4b17023SJohn Marino * 261*e4b17023SJohn Marino * @param __k The argument of the complete elliptic function. 262*e4b17023SJohn Marino * @return The complete elliptic function of the second kind. 263*e4b17023SJohn Marino */ 264*e4b17023SJohn Marino template<typename _Tp> 265*e4b17023SJohn Marino _Tp __comp_ellint_2_series(const _Tp __k)266*e4b17023SJohn Marino __comp_ellint_2_series(const _Tp __k) 267*e4b17023SJohn Marino { 268*e4b17023SJohn Marino 269*e4b17023SJohn Marino const _Tp __kk = __k * __k; 270*e4b17023SJohn Marino 271*e4b17023SJohn Marino _Tp __term = __kk; 272*e4b17023SJohn Marino _Tp __sum = __term; 273*e4b17023SJohn Marino 274*e4b17023SJohn Marino const unsigned int __max_iter = 1000; 275*e4b17023SJohn Marino for (unsigned int __i = 2; __i < __max_iter; ++__i) 276*e4b17023SJohn Marino { 277*e4b17023SJohn Marino const _Tp __i2m = 2 * __i - 1; 278*e4b17023SJohn Marino const _Tp __i2 = 2 * __i; 279*e4b17023SJohn Marino __term *= __i2m * __i2m * __kk / (__i2 * __i2); 280*e4b17023SJohn Marino if (__term < std::numeric_limits<_Tp>::epsilon()) 281*e4b17023SJohn Marino break; 282*e4b17023SJohn Marino __sum += __term / __i2m; 283*e4b17023SJohn Marino } 284*e4b17023SJohn Marino 285*e4b17023SJohn Marino return __numeric_constants<_Tp>::__pi_2() * (_Tp(1) - __sum); 286*e4b17023SJohn Marino } 287*e4b17023SJohn Marino 288*e4b17023SJohn Marino 289*e4b17023SJohn Marino /** 290*e4b17023SJohn Marino * @brief Return the Carlson elliptic function of the second kind 291*e4b17023SJohn Marino * @f$ R_D(x,y,z) = R_J(x,y,z,z) @f$ where 292*e4b17023SJohn Marino * @f$ R_J(x,y,z,p) @f$ is the Carlson elliptic function 293*e4b17023SJohn Marino * of the third kind. 294*e4b17023SJohn Marino * 295*e4b17023SJohn Marino * The Carlson elliptic function of the second kind is defined by: 296*e4b17023SJohn Marino * @f[ 297*e4b17023SJohn Marino * R_D(x,y,z) = \frac{3}{2} \int_0^\infty 298*e4b17023SJohn Marino * \frac{dt}{(t + x)^{1/2}(t + y)^{1/2}(t + z)^{3/2}} 299*e4b17023SJohn Marino * @f] 300*e4b17023SJohn Marino * 301*e4b17023SJohn Marino * Based on Carlson's algorithms: 302*e4b17023SJohn Marino * - B. C. Carlson Numer. Math. 33, 1 (1979) 303*e4b17023SJohn Marino * - B. C. Carlson, Special Functions of Applied Mathematics (1977) 304*e4b17023SJohn Marino * - Numerical Recipes in C, 2nd ed, pp. 261-269, 305*e4b17023SJohn Marino * by Press, Teukolsky, Vetterling, Flannery (1992) 306*e4b17023SJohn Marino * 307*e4b17023SJohn Marino * @param __x The first of two symmetric arguments. 308*e4b17023SJohn Marino * @param __y The second of two symmetric arguments. 309*e4b17023SJohn Marino * @param __z The third argument. 310*e4b17023SJohn Marino * @return The Carlson elliptic function of the second kind. 311*e4b17023SJohn Marino */ 312*e4b17023SJohn Marino template<typename _Tp> 313*e4b17023SJohn Marino _Tp __ellint_rd(const _Tp __x,const _Tp __y,const _Tp __z)314*e4b17023SJohn Marino __ellint_rd(const _Tp __x, const _Tp __y, const _Tp __z) 315*e4b17023SJohn Marino { 316*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 317*e4b17023SJohn Marino const _Tp __errtol = std::pow(__eps / _Tp(8), _Tp(1) / _Tp(6)); 318*e4b17023SJohn Marino const _Tp __min = std::numeric_limits<_Tp>::min(); 319*e4b17023SJohn Marino const _Tp __max = std::numeric_limits<_Tp>::max(); 320*e4b17023SJohn Marino const _Tp __lolim = _Tp(2) / std::pow(__max, _Tp(2) / _Tp(3)); 321*e4b17023SJohn Marino const _Tp __uplim = std::pow(_Tp(0.1L) * __errtol / __min, _Tp(2) / _Tp(3)); 322*e4b17023SJohn Marino 323*e4b17023SJohn Marino if (__x < _Tp(0) || __y < _Tp(0)) 324*e4b17023SJohn Marino std::__throw_domain_error(__N("Argument less than zero " 325*e4b17023SJohn Marino "in __ellint_rd.")); 326*e4b17023SJohn Marino else if (__x + __y < __lolim || __z < __lolim) 327*e4b17023SJohn Marino std::__throw_domain_error(__N("Argument too small " 328*e4b17023SJohn Marino "in __ellint_rd.")); 329*e4b17023SJohn Marino else 330*e4b17023SJohn Marino { 331*e4b17023SJohn Marino const _Tp __c0 = _Tp(1) / _Tp(4); 332*e4b17023SJohn Marino const _Tp __c1 = _Tp(3) / _Tp(14); 333*e4b17023SJohn Marino const _Tp __c2 = _Tp(1) / _Tp(6); 334*e4b17023SJohn Marino const _Tp __c3 = _Tp(9) / _Tp(22); 335*e4b17023SJohn Marino const _Tp __c4 = _Tp(3) / _Tp(26); 336*e4b17023SJohn Marino 337*e4b17023SJohn Marino _Tp __xn = __x; 338*e4b17023SJohn Marino _Tp __yn = __y; 339*e4b17023SJohn Marino _Tp __zn = __z; 340*e4b17023SJohn Marino _Tp __sigma = _Tp(0); 341*e4b17023SJohn Marino _Tp __power4 = _Tp(1); 342*e4b17023SJohn Marino 343*e4b17023SJohn Marino _Tp __mu; 344*e4b17023SJohn Marino _Tp __xndev, __yndev, __zndev; 345*e4b17023SJohn Marino 346*e4b17023SJohn Marino const unsigned int __max_iter = 100; 347*e4b17023SJohn Marino for (unsigned int __iter = 0; __iter < __max_iter; ++__iter) 348*e4b17023SJohn Marino { 349*e4b17023SJohn Marino __mu = (__xn + __yn + _Tp(3) * __zn) / _Tp(5); 350*e4b17023SJohn Marino __xndev = (__mu - __xn) / __mu; 351*e4b17023SJohn Marino __yndev = (__mu - __yn) / __mu; 352*e4b17023SJohn Marino __zndev = (__mu - __zn) / __mu; 353*e4b17023SJohn Marino _Tp __epsilon = std::max(std::abs(__xndev), std::abs(__yndev)); 354*e4b17023SJohn Marino __epsilon = std::max(__epsilon, std::abs(__zndev)); 355*e4b17023SJohn Marino if (__epsilon < __errtol) 356*e4b17023SJohn Marino break; 357*e4b17023SJohn Marino _Tp __xnroot = std::sqrt(__xn); 358*e4b17023SJohn Marino _Tp __ynroot = std::sqrt(__yn); 359*e4b17023SJohn Marino _Tp __znroot = std::sqrt(__zn); 360*e4b17023SJohn Marino _Tp __lambda = __xnroot * (__ynroot + __znroot) 361*e4b17023SJohn Marino + __ynroot * __znroot; 362*e4b17023SJohn Marino __sigma += __power4 / (__znroot * (__zn + __lambda)); 363*e4b17023SJohn Marino __power4 *= __c0; 364*e4b17023SJohn Marino __xn = __c0 * (__xn + __lambda); 365*e4b17023SJohn Marino __yn = __c0 * (__yn + __lambda); 366*e4b17023SJohn Marino __zn = __c0 * (__zn + __lambda); 367*e4b17023SJohn Marino } 368*e4b17023SJohn Marino 369*e4b17023SJohn Marino // Note: __ea is an SPU badname. 370*e4b17023SJohn Marino _Tp __eaa = __xndev * __yndev; 371*e4b17023SJohn Marino _Tp __eb = __zndev * __zndev; 372*e4b17023SJohn Marino _Tp __ec = __eaa - __eb; 373*e4b17023SJohn Marino _Tp __ed = __eaa - _Tp(6) * __eb; 374*e4b17023SJohn Marino _Tp __ef = __ed + __ec + __ec; 375*e4b17023SJohn Marino _Tp __s1 = __ed * (-__c1 + __c3 * __ed 376*e4b17023SJohn Marino / _Tp(3) - _Tp(3) * __c4 * __zndev * __ef 377*e4b17023SJohn Marino / _Tp(2)); 378*e4b17023SJohn Marino _Tp __s2 = __zndev 379*e4b17023SJohn Marino * (__c2 * __ef 380*e4b17023SJohn Marino + __zndev * (-__c3 * __ec - __zndev * __c4 - __eaa)); 381*e4b17023SJohn Marino 382*e4b17023SJohn Marino return _Tp(3) * __sigma + __power4 * (_Tp(1) + __s1 + __s2) 383*e4b17023SJohn Marino / (__mu * std::sqrt(__mu)); 384*e4b17023SJohn Marino } 385*e4b17023SJohn Marino } 386*e4b17023SJohn Marino 387*e4b17023SJohn Marino 388*e4b17023SJohn Marino /** 389*e4b17023SJohn Marino * @brief Return the complete elliptic integral of the second kind 390*e4b17023SJohn Marino * @f$ E(k) @f$ using the Carlson formulation. 391*e4b17023SJohn Marino * 392*e4b17023SJohn Marino * The complete elliptic integral of the second kind is defined as 393*e4b17023SJohn Marino * @f[ 394*e4b17023SJohn Marino * E(k,\pi/2) = \int_0^{\pi/2}\sqrt{1 - k^2 sin^2\theta} 395*e4b17023SJohn Marino * @f] 396*e4b17023SJohn Marino * 397*e4b17023SJohn Marino * @param __k The argument of the complete elliptic function. 398*e4b17023SJohn Marino * @return The complete elliptic function of the second kind. 399*e4b17023SJohn Marino */ 400*e4b17023SJohn Marino template<typename _Tp> 401*e4b17023SJohn Marino _Tp __comp_ellint_2(const _Tp __k)402*e4b17023SJohn Marino __comp_ellint_2(const _Tp __k) 403*e4b17023SJohn Marino { 404*e4b17023SJohn Marino 405*e4b17023SJohn Marino if (__isnan(__k)) 406*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 407*e4b17023SJohn Marino else if (std::abs(__k) == 1) 408*e4b17023SJohn Marino return _Tp(1); 409*e4b17023SJohn Marino else if (std::abs(__k) > _Tp(1)) 410*e4b17023SJohn Marino std::__throw_domain_error(__N("Bad argument in __comp_ellint_2.")); 411*e4b17023SJohn Marino else 412*e4b17023SJohn Marino { 413*e4b17023SJohn Marino const _Tp __kk = __k * __k; 414*e4b17023SJohn Marino 415*e4b17023SJohn Marino return __ellint_rf(_Tp(0), _Tp(1) - __kk, _Tp(1)) 416*e4b17023SJohn Marino - __kk * __ellint_rd(_Tp(0), _Tp(1) - __kk, _Tp(1)) / _Tp(3); 417*e4b17023SJohn Marino } 418*e4b17023SJohn Marino } 419*e4b17023SJohn Marino 420*e4b17023SJohn Marino 421*e4b17023SJohn Marino /** 422*e4b17023SJohn Marino * @brief Return the incomplete elliptic integral of the second kind 423*e4b17023SJohn Marino * @f$ E(k,\phi) @f$ using the Carlson formulation. 424*e4b17023SJohn Marino * 425*e4b17023SJohn Marino * The incomplete elliptic integral of the second kind is defined as 426*e4b17023SJohn Marino * @f[ 427*e4b17023SJohn Marino * E(k,\phi) = \int_0^{\phi} \sqrt{1 - k^2 sin^2\theta} 428*e4b17023SJohn Marino * @f] 429*e4b17023SJohn Marino * 430*e4b17023SJohn Marino * @param __k The argument of the elliptic function. 431*e4b17023SJohn Marino * @param __phi The integral limit argument of the elliptic function. 432*e4b17023SJohn Marino * @return The elliptic function of the second kind. 433*e4b17023SJohn Marino */ 434*e4b17023SJohn Marino template<typename _Tp> 435*e4b17023SJohn Marino _Tp __ellint_2(const _Tp __k,const _Tp __phi)436*e4b17023SJohn Marino __ellint_2(const _Tp __k, const _Tp __phi) 437*e4b17023SJohn Marino { 438*e4b17023SJohn Marino 439*e4b17023SJohn Marino if (__isnan(__k) || __isnan(__phi)) 440*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 441*e4b17023SJohn Marino else if (std::abs(__k) > _Tp(1)) 442*e4b17023SJohn Marino std::__throw_domain_error(__N("Bad argument in __ellint_2.")); 443*e4b17023SJohn Marino else 444*e4b17023SJohn Marino { 445*e4b17023SJohn Marino // Reduce phi to -pi/2 < phi < +pi/2. 446*e4b17023SJohn Marino const int __n = std::floor(__phi / __numeric_constants<_Tp>::__pi() 447*e4b17023SJohn Marino + _Tp(0.5L)); 448*e4b17023SJohn Marino const _Tp __phi_red = __phi 449*e4b17023SJohn Marino - __n * __numeric_constants<_Tp>::__pi(); 450*e4b17023SJohn Marino 451*e4b17023SJohn Marino const _Tp __kk = __k * __k; 452*e4b17023SJohn Marino const _Tp __s = std::sin(__phi_red); 453*e4b17023SJohn Marino const _Tp __ss = __s * __s; 454*e4b17023SJohn Marino const _Tp __sss = __ss * __s; 455*e4b17023SJohn Marino const _Tp __c = std::cos(__phi_red); 456*e4b17023SJohn Marino const _Tp __cc = __c * __c; 457*e4b17023SJohn Marino 458*e4b17023SJohn Marino const _Tp __E = __s 459*e4b17023SJohn Marino * __ellint_rf(__cc, _Tp(1) - __kk * __ss, _Tp(1)) 460*e4b17023SJohn Marino - __kk * __sss 461*e4b17023SJohn Marino * __ellint_rd(__cc, _Tp(1) - __kk * __ss, _Tp(1)) 462*e4b17023SJohn Marino / _Tp(3); 463*e4b17023SJohn Marino 464*e4b17023SJohn Marino if (__n == 0) 465*e4b17023SJohn Marino return __E; 466*e4b17023SJohn Marino else 467*e4b17023SJohn Marino return __E + _Tp(2) * __n * __comp_ellint_2(__k); 468*e4b17023SJohn Marino } 469*e4b17023SJohn Marino } 470*e4b17023SJohn Marino 471*e4b17023SJohn Marino 472*e4b17023SJohn Marino /** 473*e4b17023SJohn Marino * @brief Return the Carlson elliptic function 474*e4b17023SJohn Marino * @f$ R_C(x,y) = R_F(x,y,y) @f$ where @f$ R_F(x,y,z) @f$ 475*e4b17023SJohn Marino * is the Carlson elliptic function of the first kind. 476*e4b17023SJohn Marino * 477*e4b17023SJohn Marino * The Carlson elliptic function is defined by: 478*e4b17023SJohn Marino * @f[ 479*e4b17023SJohn Marino * R_C(x,y) = \frac{1}{2} \int_0^\infty 480*e4b17023SJohn Marino * \frac{dt}{(t + x)^{1/2}(t + y)} 481*e4b17023SJohn Marino * @f] 482*e4b17023SJohn Marino * 483*e4b17023SJohn Marino * Based on Carlson's algorithms: 484*e4b17023SJohn Marino * - B. C. Carlson Numer. Math. 33, 1 (1979) 485*e4b17023SJohn Marino * - B. C. Carlson, Special Functions of Applied Mathematics (1977) 486*e4b17023SJohn Marino * - Numerical Recipes in C, 2nd ed, pp. 261-269, 487*e4b17023SJohn Marino * by Press, Teukolsky, Vetterling, Flannery (1992) 488*e4b17023SJohn Marino * 489*e4b17023SJohn Marino * @param __x The first argument. 490*e4b17023SJohn Marino * @param __y The second argument. 491*e4b17023SJohn Marino * @return The Carlson elliptic function. 492*e4b17023SJohn Marino */ 493*e4b17023SJohn Marino template<typename _Tp> 494*e4b17023SJohn Marino _Tp __ellint_rc(const _Tp __x,const _Tp __y)495*e4b17023SJohn Marino __ellint_rc(const _Tp __x, const _Tp __y) 496*e4b17023SJohn Marino { 497*e4b17023SJohn Marino const _Tp __min = std::numeric_limits<_Tp>::min(); 498*e4b17023SJohn Marino const _Tp __max = std::numeric_limits<_Tp>::max(); 499*e4b17023SJohn Marino const _Tp __lolim = _Tp(5) * __min; 500*e4b17023SJohn Marino const _Tp __uplim = __max / _Tp(5); 501*e4b17023SJohn Marino 502*e4b17023SJohn Marino if (__x < _Tp(0) || __y < _Tp(0) || __x + __y < __lolim) 503*e4b17023SJohn Marino std::__throw_domain_error(__N("Argument less than zero " 504*e4b17023SJohn Marino "in __ellint_rc.")); 505*e4b17023SJohn Marino else 506*e4b17023SJohn Marino { 507*e4b17023SJohn Marino const _Tp __c0 = _Tp(1) / _Tp(4); 508*e4b17023SJohn Marino const _Tp __c1 = _Tp(1) / _Tp(7); 509*e4b17023SJohn Marino const _Tp __c2 = _Tp(9) / _Tp(22); 510*e4b17023SJohn Marino const _Tp __c3 = _Tp(3) / _Tp(10); 511*e4b17023SJohn Marino const _Tp __c4 = _Tp(3) / _Tp(8); 512*e4b17023SJohn Marino 513*e4b17023SJohn Marino _Tp __xn = __x; 514*e4b17023SJohn Marino _Tp __yn = __y; 515*e4b17023SJohn Marino 516*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 517*e4b17023SJohn Marino const _Tp __errtol = std::pow(__eps / _Tp(30), _Tp(1) / _Tp(6)); 518*e4b17023SJohn Marino _Tp __mu; 519*e4b17023SJohn Marino _Tp __sn; 520*e4b17023SJohn Marino 521*e4b17023SJohn Marino const unsigned int __max_iter = 100; 522*e4b17023SJohn Marino for (unsigned int __iter = 0; __iter < __max_iter; ++__iter) 523*e4b17023SJohn Marino { 524*e4b17023SJohn Marino __mu = (__xn + _Tp(2) * __yn) / _Tp(3); 525*e4b17023SJohn Marino __sn = (__yn + __mu) / __mu - _Tp(2); 526*e4b17023SJohn Marino if (std::abs(__sn) < __errtol) 527*e4b17023SJohn Marino break; 528*e4b17023SJohn Marino const _Tp __lambda = _Tp(2) * std::sqrt(__xn) * std::sqrt(__yn) 529*e4b17023SJohn Marino + __yn; 530*e4b17023SJohn Marino __xn = __c0 * (__xn + __lambda); 531*e4b17023SJohn Marino __yn = __c0 * (__yn + __lambda); 532*e4b17023SJohn Marino } 533*e4b17023SJohn Marino 534*e4b17023SJohn Marino _Tp __s = __sn * __sn 535*e4b17023SJohn Marino * (__c3 + __sn*(__c1 + __sn * (__c4 + __sn * __c2))); 536*e4b17023SJohn Marino 537*e4b17023SJohn Marino return (_Tp(1) + __s) / std::sqrt(__mu); 538*e4b17023SJohn Marino } 539*e4b17023SJohn Marino } 540*e4b17023SJohn Marino 541*e4b17023SJohn Marino 542*e4b17023SJohn Marino /** 543*e4b17023SJohn Marino * @brief Return the Carlson elliptic function @f$ R_J(x,y,z,p) @f$ 544*e4b17023SJohn Marino * of the third kind. 545*e4b17023SJohn Marino * 546*e4b17023SJohn Marino * The Carlson elliptic function of the third kind is defined by: 547*e4b17023SJohn Marino * @f[ 548*e4b17023SJohn Marino * R_J(x,y,z,p) = \frac{3}{2} \int_0^\infty 549*e4b17023SJohn Marino * \frac{dt}{(t + x)^{1/2}(t + y)^{1/2}(t + z)^{1/2}(t + p)} 550*e4b17023SJohn Marino * @f] 551*e4b17023SJohn Marino * 552*e4b17023SJohn Marino * Based on Carlson's algorithms: 553*e4b17023SJohn Marino * - B. C. Carlson Numer. Math. 33, 1 (1979) 554*e4b17023SJohn Marino * - B. C. Carlson, Special Functions of Applied Mathematics (1977) 555*e4b17023SJohn Marino * - Numerical Recipes in C, 2nd ed, pp. 261-269, 556*e4b17023SJohn Marino * by Press, Teukolsky, Vetterling, Flannery (1992) 557*e4b17023SJohn Marino * 558*e4b17023SJohn Marino * @param __x The first of three symmetric arguments. 559*e4b17023SJohn Marino * @param __y The second of three symmetric arguments. 560*e4b17023SJohn Marino * @param __z The third of three symmetric arguments. 561*e4b17023SJohn Marino * @param __p The fourth argument. 562*e4b17023SJohn Marino * @return The Carlson elliptic function of the fourth kind. 563*e4b17023SJohn Marino */ 564*e4b17023SJohn Marino template<typename _Tp> 565*e4b17023SJohn Marino _Tp __ellint_rj(const _Tp __x,const _Tp __y,const _Tp __z,const _Tp __p)566*e4b17023SJohn Marino __ellint_rj(const _Tp __x, const _Tp __y, const _Tp __z, const _Tp __p) 567*e4b17023SJohn Marino { 568*e4b17023SJohn Marino const _Tp __min = std::numeric_limits<_Tp>::min(); 569*e4b17023SJohn Marino const _Tp __max = std::numeric_limits<_Tp>::max(); 570*e4b17023SJohn Marino const _Tp __lolim = std::pow(_Tp(5) * __min, _Tp(1)/_Tp(3)); 571*e4b17023SJohn Marino const _Tp __uplim = _Tp(0.3L) 572*e4b17023SJohn Marino * std::pow(_Tp(0.2L) * __max, _Tp(1)/_Tp(3)); 573*e4b17023SJohn Marino 574*e4b17023SJohn Marino if (__x < _Tp(0) || __y < _Tp(0) || __z < _Tp(0)) 575*e4b17023SJohn Marino std::__throw_domain_error(__N("Argument less than zero " 576*e4b17023SJohn Marino "in __ellint_rj.")); 577*e4b17023SJohn Marino else if (__x + __y < __lolim || __x + __z < __lolim 578*e4b17023SJohn Marino || __y + __z < __lolim || __p < __lolim) 579*e4b17023SJohn Marino std::__throw_domain_error(__N("Argument too small " 580*e4b17023SJohn Marino "in __ellint_rj")); 581*e4b17023SJohn Marino else 582*e4b17023SJohn Marino { 583*e4b17023SJohn Marino const _Tp __c0 = _Tp(1) / _Tp(4); 584*e4b17023SJohn Marino const _Tp __c1 = _Tp(3) / _Tp(14); 585*e4b17023SJohn Marino const _Tp __c2 = _Tp(1) / _Tp(3); 586*e4b17023SJohn Marino const _Tp __c3 = _Tp(3) / _Tp(22); 587*e4b17023SJohn Marino const _Tp __c4 = _Tp(3) / _Tp(26); 588*e4b17023SJohn Marino 589*e4b17023SJohn Marino _Tp __xn = __x; 590*e4b17023SJohn Marino _Tp __yn = __y; 591*e4b17023SJohn Marino _Tp __zn = __z; 592*e4b17023SJohn Marino _Tp __pn = __p; 593*e4b17023SJohn Marino _Tp __sigma = _Tp(0); 594*e4b17023SJohn Marino _Tp __power4 = _Tp(1); 595*e4b17023SJohn Marino 596*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 597*e4b17023SJohn Marino const _Tp __errtol = std::pow(__eps / _Tp(8), _Tp(1) / _Tp(6)); 598*e4b17023SJohn Marino 599*e4b17023SJohn Marino _Tp __lambda, __mu; 600*e4b17023SJohn Marino _Tp __xndev, __yndev, __zndev, __pndev; 601*e4b17023SJohn Marino 602*e4b17023SJohn Marino const unsigned int __max_iter = 100; 603*e4b17023SJohn Marino for (unsigned int __iter = 0; __iter < __max_iter; ++__iter) 604*e4b17023SJohn Marino { 605*e4b17023SJohn Marino __mu = (__xn + __yn + __zn + _Tp(2) * __pn) / _Tp(5); 606*e4b17023SJohn Marino __xndev = (__mu - __xn) / __mu; 607*e4b17023SJohn Marino __yndev = (__mu - __yn) / __mu; 608*e4b17023SJohn Marino __zndev = (__mu - __zn) / __mu; 609*e4b17023SJohn Marino __pndev = (__mu - __pn) / __mu; 610*e4b17023SJohn Marino _Tp __epsilon = std::max(std::abs(__xndev), std::abs(__yndev)); 611*e4b17023SJohn Marino __epsilon = std::max(__epsilon, std::abs(__zndev)); 612*e4b17023SJohn Marino __epsilon = std::max(__epsilon, std::abs(__pndev)); 613*e4b17023SJohn Marino if (__epsilon < __errtol) 614*e4b17023SJohn Marino break; 615*e4b17023SJohn Marino const _Tp __xnroot = std::sqrt(__xn); 616*e4b17023SJohn Marino const _Tp __ynroot = std::sqrt(__yn); 617*e4b17023SJohn Marino const _Tp __znroot = std::sqrt(__zn); 618*e4b17023SJohn Marino const _Tp __lambda = __xnroot * (__ynroot + __znroot) 619*e4b17023SJohn Marino + __ynroot * __znroot; 620*e4b17023SJohn Marino const _Tp __alpha1 = __pn * (__xnroot + __ynroot + __znroot) 621*e4b17023SJohn Marino + __xnroot * __ynroot * __znroot; 622*e4b17023SJohn Marino const _Tp __alpha2 = __alpha1 * __alpha1; 623*e4b17023SJohn Marino const _Tp __beta = __pn * (__pn + __lambda) 624*e4b17023SJohn Marino * (__pn + __lambda); 625*e4b17023SJohn Marino __sigma += __power4 * __ellint_rc(__alpha2, __beta); 626*e4b17023SJohn Marino __power4 *= __c0; 627*e4b17023SJohn Marino __xn = __c0 * (__xn + __lambda); 628*e4b17023SJohn Marino __yn = __c0 * (__yn + __lambda); 629*e4b17023SJohn Marino __zn = __c0 * (__zn + __lambda); 630*e4b17023SJohn Marino __pn = __c0 * (__pn + __lambda); 631*e4b17023SJohn Marino } 632*e4b17023SJohn Marino 633*e4b17023SJohn Marino // Note: __ea is an SPU badname. 634*e4b17023SJohn Marino _Tp __eaa = __xndev * (__yndev + __zndev) + __yndev * __zndev; 635*e4b17023SJohn Marino _Tp __eb = __xndev * __yndev * __zndev; 636*e4b17023SJohn Marino _Tp __ec = __pndev * __pndev; 637*e4b17023SJohn Marino _Tp __e2 = __eaa - _Tp(3) * __ec; 638*e4b17023SJohn Marino _Tp __e3 = __eb + _Tp(2) * __pndev * (__eaa - __ec); 639*e4b17023SJohn Marino _Tp __s1 = _Tp(1) + __e2 * (-__c1 + _Tp(3) * __c3 * __e2 / _Tp(4) 640*e4b17023SJohn Marino - _Tp(3) * __c4 * __e3 / _Tp(2)); 641*e4b17023SJohn Marino _Tp __s2 = __eb * (__c2 / _Tp(2) 642*e4b17023SJohn Marino + __pndev * (-__c3 - __c3 + __pndev * __c4)); 643*e4b17023SJohn Marino _Tp __s3 = __pndev * __eaa * (__c2 - __pndev * __c3) 644*e4b17023SJohn Marino - __c2 * __pndev * __ec; 645*e4b17023SJohn Marino 646*e4b17023SJohn Marino return _Tp(3) * __sigma + __power4 * (__s1 + __s2 + __s3) 647*e4b17023SJohn Marino / (__mu * std::sqrt(__mu)); 648*e4b17023SJohn Marino } 649*e4b17023SJohn Marino } 650*e4b17023SJohn Marino 651*e4b17023SJohn Marino 652*e4b17023SJohn Marino /** 653*e4b17023SJohn Marino * @brief Return the complete elliptic integral of the third kind 654*e4b17023SJohn Marino * @f$ \Pi(k,\nu) = \Pi(k,\nu,\pi/2) @f$ using the 655*e4b17023SJohn Marino * Carlson formulation. 656*e4b17023SJohn Marino * 657*e4b17023SJohn Marino * The complete elliptic integral of the third kind is defined as 658*e4b17023SJohn Marino * @f[ 659*e4b17023SJohn Marino * \Pi(k,\nu) = \int_0^{\pi/2} 660*e4b17023SJohn Marino * \frac{d\theta} 661*e4b17023SJohn Marino * {(1 - \nu \sin^2\theta)\sqrt{1 - k^2 \sin^2\theta}} 662*e4b17023SJohn Marino * @f] 663*e4b17023SJohn Marino * 664*e4b17023SJohn Marino * @param __k The argument of the elliptic function. 665*e4b17023SJohn Marino * @param __nu The second argument of the elliptic function. 666*e4b17023SJohn Marino * @return The complete elliptic function of the third kind. 667*e4b17023SJohn Marino */ 668*e4b17023SJohn Marino template<typename _Tp> 669*e4b17023SJohn Marino _Tp __comp_ellint_3(const _Tp __k,const _Tp __nu)670*e4b17023SJohn Marino __comp_ellint_3(const _Tp __k, const _Tp __nu) 671*e4b17023SJohn Marino { 672*e4b17023SJohn Marino 673*e4b17023SJohn Marino if (__isnan(__k) || __isnan(__nu)) 674*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 675*e4b17023SJohn Marino else if (__nu == _Tp(1)) 676*e4b17023SJohn Marino return std::numeric_limits<_Tp>::infinity(); 677*e4b17023SJohn Marino else if (std::abs(__k) > _Tp(1)) 678*e4b17023SJohn Marino std::__throw_domain_error(__N("Bad argument in __comp_ellint_3.")); 679*e4b17023SJohn Marino else 680*e4b17023SJohn Marino { 681*e4b17023SJohn Marino const _Tp __kk = __k * __k; 682*e4b17023SJohn Marino 683*e4b17023SJohn Marino return __ellint_rf(_Tp(0), _Tp(1) - __kk, _Tp(1)) 684*e4b17023SJohn Marino - __nu 685*e4b17023SJohn Marino * __ellint_rj(_Tp(0), _Tp(1) - __kk, _Tp(1), _Tp(1) + __nu) 686*e4b17023SJohn Marino / _Tp(3); 687*e4b17023SJohn Marino } 688*e4b17023SJohn Marino } 689*e4b17023SJohn Marino 690*e4b17023SJohn Marino 691*e4b17023SJohn Marino /** 692*e4b17023SJohn Marino * @brief Return the incomplete elliptic integral of the third kind 693*e4b17023SJohn Marino * @f$ \Pi(k,\nu,\phi) @f$ using the Carlson formulation. 694*e4b17023SJohn Marino * 695*e4b17023SJohn Marino * The incomplete elliptic integral of the third kind is defined as 696*e4b17023SJohn Marino * @f[ 697*e4b17023SJohn Marino * \Pi(k,\nu,\phi) = \int_0^{\phi} 698*e4b17023SJohn Marino * \frac{d\theta} 699*e4b17023SJohn Marino * {(1 - \nu \sin^2\theta) 700*e4b17023SJohn Marino * \sqrt{1 - k^2 \sin^2\theta}} 701*e4b17023SJohn Marino * @f] 702*e4b17023SJohn Marino * 703*e4b17023SJohn Marino * @param __k The argument of the elliptic function. 704*e4b17023SJohn Marino * @param __nu The second argument of the elliptic function. 705*e4b17023SJohn Marino * @param __phi The integral limit argument of the elliptic function. 706*e4b17023SJohn Marino * @return The elliptic function of the third kind. 707*e4b17023SJohn Marino */ 708*e4b17023SJohn Marino template<typename _Tp> 709*e4b17023SJohn Marino _Tp __ellint_3(const _Tp __k,const _Tp __nu,const _Tp __phi)710*e4b17023SJohn Marino __ellint_3(const _Tp __k, const _Tp __nu, const _Tp __phi) 711*e4b17023SJohn Marino { 712*e4b17023SJohn Marino 713*e4b17023SJohn Marino if (__isnan(__k) || __isnan(__nu) || __isnan(__phi)) 714*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 715*e4b17023SJohn Marino else if (std::abs(__k) > _Tp(1)) 716*e4b17023SJohn Marino std::__throw_domain_error(__N("Bad argument in __ellint_3.")); 717*e4b17023SJohn Marino else 718*e4b17023SJohn Marino { 719*e4b17023SJohn Marino // Reduce phi to -pi/2 < phi < +pi/2. 720*e4b17023SJohn Marino const int __n = std::floor(__phi / __numeric_constants<_Tp>::__pi() 721*e4b17023SJohn Marino + _Tp(0.5L)); 722*e4b17023SJohn Marino const _Tp __phi_red = __phi 723*e4b17023SJohn Marino - __n * __numeric_constants<_Tp>::__pi(); 724*e4b17023SJohn Marino 725*e4b17023SJohn Marino const _Tp __kk = __k * __k; 726*e4b17023SJohn Marino const _Tp __s = std::sin(__phi_red); 727*e4b17023SJohn Marino const _Tp __ss = __s * __s; 728*e4b17023SJohn Marino const _Tp __sss = __ss * __s; 729*e4b17023SJohn Marino const _Tp __c = std::cos(__phi_red); 730*e4b17023SJohn Marino const _Tp __cc = __c * __c; 731*e4b17023SJohn Marino 732*e4b17023SJohn Marino const _Tp __Pi = __s 733*e4b17023SJohn Marino * __ellint_rf(__cc, _Tp(1) - __kk * __ss, _Tp(1)) 734*e4b17023SJohn Marino - __nu * __sss 735*e4b17023SJohn Marino * __ellint_rj(__cc, _Tp(1) - __kk * __ss, _Tp(1), 736*e4b17023SJohn Marino _Tp(1) + __nu * __ss) / _Tp(3); 737*e4b17023SJohn Marino 738*e4b17023SJohn Marino if (__n == 0) 739*e4b17023SJohn Marino return __Pi; 740*e4b17023SJohn Marino else 741*e4b17023SJohn Marino return __Pi + _Tp(2) * __n * __comp_ellint_3(__k, __nu); 742*e4b17023SJohn Marino } 743*e4b17023SJohn Marino } 744*e4b17023SJohn Marino 745*e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION 746*e4b17023SJohn Marino } // namespace std::tr1::__detail 747*e4b17023SJohn Marino } 748*e4b17023SJohn Marino } 749*e4b17023SJohn Marino 750*e4b17023SJohn Marino #endif // _GLIBCXX_TR1_ELL_INTEGRAL_TCC 751*e4b17023SJohn Marino 752