Return the spherical associated Legendre function.
58 _GLIBCXX_BEGIN_NAMESPACE_VERSION
73 template<
typename _Tp>
75 __poly_legendre_p(
unsigned int __l, _Tp __x)
78 if ((__x < _Tp(-1)) || (__x > _Tp(+1)))
79 std::__throw_domain_error(__N(
"Argument out of range"
80 " in __poly_legendre_p."));
81 else if (__isnan(__x))
82 return std::numeric_limits<_Tp>::quiet_NaN();
83 else if (__x == +_Tp(1))
85 else if (__x == -_Tp(1))
86 return (__l % 2 == 1 ? -_Tp(1) : +_Tp(1));
98 for (
unsigned int __ll = 2; __ll <= __l; ++__ll)
102 __p_l = _Tp(2) * __x * __p_lm1 - __p_lm2
103 - (__x * __p_lm1 - __p_lm2) / _Tp(__ll);
130 template<
typename _Tp>
132 __assoc_legendre_p(
unsigned int __l,
unsigned int __m, _Tp __x)
135 if (__x < _Tp(-1) || __x > _Tp(+1))
136 std::__throw_domain_error(__N(
"Argument out of range"
137 " in __assoc_legendre_p."));
139 std::__throw_domain_error(__N(
"Degree out of range"
140 " in __assoc_legendre_p."));
141 else if (__isnan(__x))
142 return std::numeric_limits<_Tp>::quiet_NaN();
144 return __poly_legendre_p(__l, __x);
152 _Tp __root = std::sqrt(_Tp(1) - __x) * std::sqrt(_Tp(1) + __x);
154 for (
unsigned int __i = 1; __i <= __m; ++__i)
156 __p_mm *= -__fact * __root;
163 _Tp __p_mp1m = _Tp(2 * __m + 1) * __x * __p_mm;
167 _Tp __p_lm2m = __p_mm;
168 _Tp __P_lm1m = __p_mp1m;
170 for (
unsigned int __j = __m + 2; __j <= __l; ++__j)
172 __p_lm = (_Tp(2 * __j - 1) * __x * __P_lm1m
173 - _Tp(__j + __m - 1) * __p_lm2m) / _Tp(__j - __m);
209 template <
typename _Tp>
211 __sph_legendre(
unsigned int __l,
unsigned int __m, _Tp __theta)
213 if (__isnan(__theta))
214 return std::numeric_limits<_Tp>::quiet_NaN();
216 const _Tp __x = std::cos(__theta);
220 std::__throw_domain_error(__N(
"Bad argument "
221 "in __sph_legendre."));
225 _Tp
__P = __poly_legendre_p(__l, __x);
226 _Tp __fact = std::sqrt(_Tp(2 * __l + 1)
227 / (_Tp(4) * __numeric_constants<_Tp>::__pi()));
231 else if (__x == _Tp(1) || __x == -_Tp(1))
243 const _Tp __sgn = ( __m % 2 == 1 ? -_Tp(1) : _Tp(1));
244 const _Tp __y_mp1m_factor = __x * std::sqrt(_Tp(2 * __m + 3));
245 #if _GLIBCXX_USE_C99_MATH_TR1
246 const _Tp __lncirc = std::tr1::log1p(-__x * __x);
248 const _Tp __lncirc = std::log(_Tp(1) - __x * __x);
251 #if _GLIBCXX_USE_C99_MATH_TR1
252 const _Tp __lnpoch = std::tr1::lgamma(_Tp(__m + _Tp(0.5L)))
253 - std::tr1::lgamma(_Tp(__m));
255 const _Tp __lnpoch = __log_gamma(_Tp(__m + _Tp(0.5L)))
256 - __log_gamma(_Tp(__m));
258 const _Tp __lnpre_val =
259 -_Tp(0.25L) * __numeric_constants<_Tp>::__lnpi()
260 + _Tp(0.5L) * (__lnpoch + __m * __lncirc);
261 _Tp __sr = std::sqrt((_Tp(2) + _Tp(1) / __m)
262 / (_Tp(4) * __numeric_constants<_Tp>::__pi()));
263 _Tp __y_mm = __sgn * __sr * std::exp(__lnpre_val);
264 _Tp __y_mp1m = __y_mp1m_factor * __y_mm;
270 else if (__l == __m + 1)
279 for (
int __ll = __m + 2; __ll <= __l; ++__ll)
281 const _Tp __rat1 = _Tp(__ll - __m) / _Tp(__ll + __m);
282 const _Tp __rat2 = _Tp(__ll - __m - 1) / _Tp(__ll + __m - 1);
283 const _Tp __fact1 = std::sqrt(__rat1 * _Tp(2 * __ll + 1)
284 * _Tp(2 * __ll - 1));
285 const _Tp __fact2 = std::sqrt(__rat1 * __rat2 * _Tp(2 * __ll + 1)
286 / _Tp(2 * __ll - 3));
287 __y_lm = (__x * __y_mp1m * __fact1
288 - (__ll + __m - 1) * __y_mm * __fact2) / _Tp(__ll - __m);
298 _GLIBCXX_END_NAMESPACE_VERSION
__inline unsigned char unsigned int unsigned int unsigned int * __P
Definition: adxintrin.h:35