| 1 | // Special functions -*- C++ -*- | 
|---|
| 2 |  | 
|---|
| 3 | // Copyright (C) 2006-2021 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 |  | 
|---|