]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/include/tr1/legendre_function.tcc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / tr1 / legendre_function.tcc
index ba53fbc4a13d3b2a6b4208c403546763c1e6fb94..126355beb31bc4378fec63452a0685de05e21f3f 100644 (file)
@@ -1,6 +1,6 @@
 // Special functions -*- C++ -*-
 
-// Copyright (C) 2006-2014 Free Software Foundation, Inc.
+// Copyright (C) 2006-2020 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
 #ifndef _GLIBCXX_TR1_LEGENDRE_FUNCTION_TCC
 #define _GLIBCXX_TR1_LEGENDRE_FUNCTION_TCC 1
 
-#include "special_function_util.h"
+#include <tr1/special_function_util.h>
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#if _GLIBCXX_USE_STD_SPEC_FUNCS
+# define _GLIBCXX_MATH_NS ::std
+#elif defined(_GLIBCXX_TR1_CMATH)
 namespace tr1
 {
+# define _GLIBCXX_MATH_NS ::std::tr1
+#else
+# error do not include this header directly, use <cmath> or <tr1/cmath>
+#endif
   // [5.2] Special functions
 
   // Implementation-space details.
   namespace __detail
   {
-  _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
     /**
-     *   @brief  Return the Legendre polynomial by recursion on order
+     *   @brief  Return the Legendre polynomial by recursion on degree
      *           @f$ l @f$.
      * 
      *   The Legendre function of @f$ l @f$ and @f$ x @f$,
@@ -67,7 +74,7 @@ namespace tr1
      *     P_l(x) = \frac{1}{2^l l!}\frac{d^l}{dx^l}(x^2 - 1)^{l}
      *   @f]
      * 
-     *   @param  l  The order of the Legendre polynomial.  @f$l >= 0@f$.
+     *   @param  l  The degree of the Legendre polynomial.  @f$l >= 0@f$.
      *   @param  x  The argument of the Legendre polynomial.  @f$|x| <= 1@f$.
      */
     template<typename _Tp>
@@ -75,10 +82,7 @@ namespace tr1
     __poly_legendre_p(unsigned int __l, _Tp __x)
     {
 
-      if ((__x < _Tp(-1)) || (__x > _Tp(+1)))
-        std::__throw_domain_error(__N("Argument out of range"
-                                      " in __poly_legendre_p."));
-      else if (__isnan(__x))
+      if (__isnan(__x))
         return std::numeric_limits<_Tp>::quiet_NaN();
       else if (__x == +_Tp(1))
         return +_Tp(1);
@@ -119,25 +123,24 @@ namespace tr1
      *   @f[
      *     P_l^m(x) = (1 - x^2)^{m/2}\frac{d^m}{dx^m}P_l(x)
      *   @f]
+     *   @note @f$ P_l^m(x) = 0 @f$ if @f$ m > l @f$.
      * 
-     *   @param  l  The order of the associated Legendre function.
+     *   @param  l  The degree of the associated Legendre function.
      *              @f$ l >= 0 @f$.
      *   @param  m  The order of the associated Legendre function.
-     *              @f$ m <= l @f$.
      *   @param  x  The argument of the associated Legendre function.
      *              @f$ |x| <= 1 @f$.
+     *   @param  phase  The phase of the associated Legendre function.
+     *                  Use -1 for the Condon-Shortley phase convention.
      */
     template<typename _Tp>
     _Tp
-    __assoc_legendre_p(unsigned int __l, unsigned int __m, _Tp __x)
+    __assoc_legendre_p(unsigned int __l, unsigned int __m, _Tp __x,
+                      _Tp __phase = _Tp(+1))
     {
 
-      if (__x < _Tp(-1) || __x > _Tp(+1))
-        std::__throw_domain_error(__N("Argument out of range"
-                                      " in __assoc_legendre_p."));
-      else if (__m > __l)
-        std::__throw_domain_error(__N("Degree out of range"
-                                      " in __assoc_legendre_p."));
+      if (__m > __l)
+        return _Tp(0);
       else if (__isnan(__x))
         return std::numeric_limits<_Tp>::quiet_NaN();
       else if (__m == 0)
@@ -153,7 +156,7 @@ namespace tr1
               _Tp __fact = _Tp(1);
               for (unsigned int __i = 1; __i <= __m; ++__i)
                 {
-                  __p_mm *= -__fact * __root;
+                  __p_mm *= __phase * __fact * __root;
                   __fact += _Tp(2);
                 }
             }
@@ -198,11 +201,13 @@ namespace tr1
      *   but this factor is rather large for large @f$ l @f$ and @f$ m @f$
      *   and so this function is stable for larger differences of @f$ l @f$
      *   and @f$ m @f$.
+     *   @note Unlike the case for __assoc_legendre_p the Condon-Shortley
+     *         phase factor @f$ (-1)^m @f$ is present here.
+     *   @note @f$ Y_l^m(\theta) = 0 @f$ if @f$ m > l @f$.
      * 
-     *   @param  l  The order of the spherical associated Legendre function.
+     *   @param  l  The degree of the spherical associated Legendre function.
      *              @f$ l >= 0 @f$.
      *   @param  m  The order of the spherical associated Legendre function.
-     *              @f$ m <= l @f$.
      *   @param  theta  The radian angle argument of the spherical associated
      *                  Legendre function.
      */
@@ -215,11 +220,8 @@ namespace tr1
 
       const _Tp __x = std::cos(__theta);
 
-      if (__l < __m)
-        {
-          std::__throw_domain_error(__N("Bad argument "
-                                        "in __sph_legendre."));
-        }
+      if (__m > __l)
+        return _Tp(0);
       else if (__m == 0)
         {
           _Tp __P = __poly_legendre_p(__l, __x);
@@ -243,14 +245,14 @@ namespace tr1
           const _Tp __sgn = ( __m % 2 == 1 ? -_Tp(1) : _Tp(1));
           const _Tp __y_mp1m_factor = __x * std::sqrt(_Tp(2 * __m + 3));
 #if _GLIBCXX_USE_C99_MATH_TR1
-          const _Tp __lncirc = std::tr1::log1p(-__x * __x);
+          const _Tp __lncirc = _GLIBCXX_MATH_NS::log1p(-__x * __x);
 #else
           const _Tp __lncirc = std::log(_Tp(1) - __x * __x);
 #endif
           //  Gamma(m+1/2) / Gamma(m)
 #if _GLIBCXX_USE_C99_MATH_TR1
-          const _Tp __lnpoch = std::tr1::lgamma(_Tp(__m + _Tp(0.5L)))
-                             - std::tr1::lgamma(_Tp(__m));
+          const _Tp __lnpoch = _GLIBCXX_MATH_NS::lgamma(_Tp(__m + _Tp(0.5L)))
+                             - _GLIBCXX_MATH_NS::lgamma(_Tp(__m));
 #else
           const _Tp __lnpoch = __log_gamma(_Tp(__m + _Tp(0.5L)))
                              - __log_gamma(_Tp(__m));
@@ -258,25 +260,21 @@ namespace tr1
           const _Tp __lnpre_val =
                     -_Tp(0.25L) * __numeric_constants<_Tp>::__lnpi()
                     + _Tp(0.5L) * (__lnpoch + __m * __lncirc);
-          _Tp __sr = std::sqrt((_Tp(2) + _Tp(1) / __m)
-                   / (_Tp(4) * __numeric_constants<_Tp>::__pi()));
+          const _Tp __sr = std::sqrt((_Tp(2) + _Tp(1) / __m)
+                         / (_Tp(4) * __numeric_constants<_Tp>::__pi()));
           _Tp __y_mm = __sgn * __sr * std::exp(__lnpre_val);
           _Tp __y_mp1m = __y_mp1m_factor * __y_mm;
 
           if (__l == __m)
-            {
-              return __y_mm;
-            }
+            return __y_mm;
           else if (__l == __m + 1)
-            {
-              return __y_mp1m;
-            }
+            return __y_mp1m;
           else
             {
               _Tp __y_lm = _Tp(0);
 
               // Compute Y_l^m, l > m+1, upward recursion on l.
-              for ( int __ll = __m + 2; __ll <= __l; ++__ll)
+              for (int __ll = __m + 2; __ll <= __l; ++__ll)
                 {
                   const _Tp __rat1 = _Tp(__ll - __m) / _Tp(__ll + __m);
                   const _Tp __rat2 = _Tp(__ll - __m - 1) / _Tp(__ll + __m - 1);
@@ -294,10 +292,13 @@ namespace tr1
             }
         }
     }
+  } // namespace __detail
+#undef _GLIBCXX_MATH_NS
+#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
+} // namespace tr1
+#endif
 
-  _GLIBCXX_END_NAMESPACE_VERSION
-  } // namespace std::tr1::__detail
-}
+_GLIBCXX_END_NAMESPACE_VERSION
 }
 
 #endif // _GLIBCXX_TR1_LEGENDRE_FUNCTION_TCC