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
45namespace std _GLIBCXX_VISIBILITY(default)
46{
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
48
49#if _GLIBCXX_USE_STD_SPEC_FUNCS
50#elif defined(_GLIBCXX_TR1_CMATH)
51namespace 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