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