aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/bits/sf_gegenbauer.tcc
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include/bits/sf_gegenbauer.tcc')
-rw-r--r--libstdc++-v3/include/bits/sf_gegenbauer.tcc143
1 files changed, 125 insertions, 18 deletions
diff --git a/libstdc++-v3/include/bits/sf_gegenbauer.tcc b/libstdc++-v3/include/bits/sf_gegenbauer.tcc
index ef3be01adec..4c12dc30c06 100644
--- a/libstdc++-v3/include/bits/sf_gegenbauer.tcc
+++ b/libstdc++-v3/include/bits/sf_gegenbauer.tcc
@@ -55,36 +55,143 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @tparam _Talpha The real type of the order
* @tparam _Tp The real type of the argument
* @param __n The non-negative integral degree
- * @param __alpha The real order
+ * @param __alpha1 The real order
* @param __x The real argument
*/
template<typename _Tp>
_Tp
- __gegenbauer_poly(unsigned int __n, _Tp __alpha, _Tp __x)
+ __gegenbauer_poly(unsigned int __n, _Tp __alpha1, _Tp __x)
{
const auto _S_NaN = __gnu_cxx::__quiet_NaN(__x);
- if (__isnan(__alpha) || __isnan(__x))
+ if (__isnan(__alpha1) || __isnan(__x))
return _S_NaN;
- auto _C0 = _Tp{1};
+ auto __C_nm2 = _Tp{1};
if (__n == 0)
- return _C0;
+ return __C_nm2;
- auto _C1 = _Tp{2} * __alpha * __x;
+ auto __C_nm1 = _Tp{2} * __alpha1 * __x;
if (__n == 1)
- return _C1;
-
- auto _Cn = _Tp{0};
- for (unsigned int __nn = 2; __nn <= __n; ++__nn)
- {
- _Cn = (_Tp{2} * (_Tp{__nn} - _Tp{1} + __alpha) * __x * _C1
- - (_Tp{__nn} - _Tp{2} + _Tp{2} * __alpha) * _C0)
- / _Tp(__nn);
- _C0 = _C1;
- _C1 = _Cn;
- }
- return _Cn;
+ return __C_nm1;
+
+ auto __C_n = (_Tp{2} * (_Tp{1} + __alpha1) * __x * __C_nm1
+ - _Tp{2} * __alpha1 * __C_nm2) / _Tp(2);
+ for (unsigned int __nn = 3; __nn <= __n; ++__nn)
+ {
+ __C_nm2 = __C_nm1;
+ __C_nm1 = __C_n;
+ __C_n = (_Tp{2} * (_Tp(__nn) - _Tp{1} + __alpha1) * __x * __C_nm1
+ - (_Tp(__nn) - _Tp{2} + _Tp{2} * __alpha1) * __C_nm2)
+ / _Tp(__nn);
+ }
+ return __C_n;
+ }
+
+ /**
+ * Return a vector containing the zeros of the Gegenbauer or ultraspherical
+ * polynomial @f$ C_n^{(\alpha)}@f$.
+ */
+ template<typename _Tp>
+ std::vector<__gnu_cxx::__quadrature_point_t<_Tp>>
+ __gegenbauer_zeros(unsigned int __n, _Tp __alpha1)
+ {
+ const auto _S_eps = __gnu_cxx::__epsilon(__alpha1);
+ const unsigned int _S_maxit = 1000u;
+ std::vector<__gnu_cxx::__quadrature_point_t<_Tp>> __pt(__n);
+
+ _Tp __z;
+ _Tp __w;
+ for (auto __i = 1u; __i <= __n; ++__i)
+ {
+ if (__i == 1)
+ {
+ auto __an = __alpha1 / __n;
+ auto __an2 = __an * __an;
+ auto __r1 = (1.0 + __alpha1) * (2.78 / (4.0 + __n * __n)
+ + 0.768 * __an / __n);
+ auto __r2 = 1.0 + 1.48 * __an + 0.96 * __an + 1.282 * __an2;
+ __z = 1.0 - __r1 / __r2;
+ }
+ else if (__i == 2)
+ {
+ auto __r1 = (4.1 + __alpha1)
+ / ((1.0 + __alpha1) * (1.0 + 0.156 * __alpha1));
+ auto __r2 = 1.0
+ + 0.06 * (__n - 8.0) * (1.0 + 0.12 * __alpha1) / __n;
+ auto __r3 = 1.0
+ + 0.012 * __alpha1 * (1.0 + 0.25 * std::abs(__alpha1)) / __n;
+ __z -= (1.0 - __z) * __r1 * __r2 * __r3;
+ }
+ else if (__i == 3)
+ {
+ auto __r1 = (1.67 + 0.28 * __alpha1) / (1.0 + 0.37 * __alpha1);
+ auto __r2 = 1.0 + 0.22 * (__n - 8.0) / __n;
+ auto __r3 = 1.0 + 8.0 *__alpha1 / ((6.28 + __alpha1) * __n * __n);
+ __z -= (__pt[0].__zero - __z) * __r1 * __r2 * __r3;
+ }
+ else if (__i == __n - 1)
+ {
+ auto __r1 = (1.0 + 0.235 * __alpha1) / (0.766 + 0.119 * __alpha1);
+ auto __r2 = 1.0 / (1.0 + 0.639 * (__n - 4.0)
+ / (1.0 + 0.71 * (__n - 4.0)));
+ auto __r3 = 1.0 / (1.0 + 20.0 * __alpha1
+ / ((7.5 + __alpha1) * __n * __n));
+ __z += (__z - __pt[__n - 4].__zero) * __r1 * __r2 * __r3;
+ }
+ else if (__i == __n)
+ {
+ auto __r1 = (1.0 + 0.37 * __alpha1) / (1.67 + 0.28 * __alpha1);
+ auto __r2 = 1.0 / (1.0 + 0.22 * (__n - 8.0) / __n);
+ auto __r3 = 1.0 / (1.0 + 8.0 * __alpha1
+ / ((6.28 + __alpha1) * __n * __n));
+ __z += (__z - __pt[__n - 3].__zero) * __r1 * __r2 * __r3;
+ }
+ else
+ __z = 3.0 * __pt[__i - 2].__zero
+ - 3.0 * __pt[__i - 3].__zero + __pt[__i - 4].__zero;
+
+ auto __2alpha = _Tp{2} * __alpha1;
+ for (auto __its = 1u; __its <= _S_maxit; ++__its)
+ {
+ auto __temp = _Tp{2} + __2alpha;
+ auto __C1 = (__temp * __z) / _Tp{2};
+ auto __C2 = _Tp{1};
+ for (auto __j = 2u; __j <= __n; ++__j)
+ {
+ auto __C3 = __C2;
+ __C2 = __C1;
+ __temp = _Tp{2} * __j + __2alpha;
+ auto __a = _Tp{2} * __j * (__j + __2alpha)
+ * (__temp - _Tp{2});
+ auto __b = (__temp - _Tp{1})
+ * __temp * (__temp - _Tp{2}) * __z;
+ auto __c = _Tp{2} * (__j - 1 + __alpha1)
+ * (__j - 1 + __alpha1) * __temp;
+ __C1 = (__b * __C2 - __c * __C3) / __a;
+ }
+ auto __Cp = (__n * (-__temp * __z) * __C1
+ + _Tp{2} * (__n + __alpha1) * (__n + __alpha1) * __C2)
+ / (__temp * (_Tp{1} - __z * __z));
+ auto __z1 = __z;
+ __z = __z1 - __C1 / __Cp;
+ if (std::abs(__z - __z1) <= _S_eps)
+ {
+ __w = std::exp(std::lgamma(__alpha1 + _Tp(__n))
+ + std::lgamma(__alpha1 + _Tp(__n))
+ - std::lgamma(_Tp(__n + 1))
+ - std::lgamma(_Tp(__n + 1) + __2alpha))
+ * __temp * std::pow(_Tp{2}, __2alpha) / (__Cp * __C2);
+ break;
+ }
+ if (__its > _S_maxit)
+ std::__throw_logic_error("__jacobi_zeros: Too many iterations");
+ }
+ __pt[__i - 1].__zero = __z;
+ __pt[__i - 1].__weight = __w;
+ }
+
+ return __pt;
}
} // namespace __detail