mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-26 19:56:05 +08:00
PR libstdc++/86655 - std::assoc_legendre should not constrain
2019-03-06 Edward Smith-Rowland <3dw4rd@verizon.net> PR libstdc++/86655 - std::assoc_legendre should not constrain the value of m (or x). * include/tr1/legendre_function.tcc (__assoc_legendre_p, __sph_legendre): If degree > order Don't throw, return 0. (__legendre_p, __assoc_legendre_p): Don't constrain x either. * testsuite/special_functions/02_assoc_legendre/pr86655.cc: New test. * testsuite/special_functions/20_sph_legendre/pr86655.cc: New test. * testsuite/tr1/5_numerical_facilities/special_functions/ 02_assoc_legendre/pr86655.cc: New test. * testsuite/tr1/5_numerical_facilities/special_functions/ 22_sph_legendre/pr86655.cc: New test. From-SVN: r269423
This commit is contained in:
parent
669a6fdcb4
commit
f29a1ef2d8
@ -1,3 +1,17 @@
|
||||
2019-03-06 Edward Smith-Rowland <3dw4rd@verizon.net>
|
||||
|
||||
PR libstdc++/86655 - std::assoc_legendre should not constrain
|
||||
the value of m (or x).
|
||||
* include/tr1/legendre_function.tcc (__assoc_legendre_p,
|
||||
__sph_legendre): If degree > order Don't throw, return 0.
|
||||
(__legendre_p, __assoc_legendre_p): Don't constrain x either.
|
||||
* testsuite/special_functions/02_assoc_legendre/pr86655.cc: New test.
|
||||
* testsuite/special_functions/20_sph_legendre/pr86655.cc: New test.
|
||||
* testsuite/tr1/5_numerical_facilities/special_functions/
|
||||
02_assoc_legendre/pr86655.cc: New test.
|
||||
* testsuite/tr1/5_numerical_facilities/special_functions/
|
||||
22_sph_legendre/pr86655.cc: New test.
|
||||
|
||||
2019-03-06 Ville Voutilainen <ville.voutilainen@gmail.com>
|
||||
|
||||
Rewrite variant.
|
||||
|
@ -82,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);
|
||||
@ -126,11 +123,11 @@ 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 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.
|
||||
@ -142,12 +139,8 @@ namespace tr1
|
||||
_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)
|
||||
@ -209,12 +202,12 @@ namespace tr1
|
||||
* 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.
|
||||
* 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 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.
|
||||
*/
|
||||
@ -227,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);
|
||||
@ -284,7 +274,7 @@ namespace tr1
|
||||
_Tp __y_lm = _Tp(0);
|
||||
|
||||
// Compute Y_l^m, l > m+1, upward recursion on l.
|
||||
for (unsigned 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);
|
||||
|
@ -0,0 +1,56 @@
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-options "-D__STDCPP_WANT_MATH_SPEC_FUNCS__ -ffp-contract=off" }
|
||||
|
||||
// Copyright (C) 2019 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
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <initializer_list>
|
||||
#include <cmath>
|
||||
#if defined(__TEST_DEBUG)
|
||||
# include <iostream>
|
||||
# define VERIFY(A) \
|
||||
if (!(A)) \
|
||||
{ \
|
||||
std::cout << "line " << __LINE__ \
|
||||
<< " std::assoc_legendre(l, m, x) == 0: " << (A) \
|
||||
<< '\n'; \
|
||||
}
|
||||
#else
|
||||
# include <testsuite_hooks.h>
|
||||
#endif
|
||||
|
||||
template<typename _Tp>
|
||||
void
|
||||
test_m_gt_l()
|
||||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
for (auto l : {0u, 1u, 2u, 5u})
|
||||
for (auto m : {l + 1u, l + 2u})
|
||||
for (auto i : {-2, -1, 0, 1, 2})
|
||||
{
|
||||
auto x = _Tp(i * 0.5L);
|
||||
VERIFY(std::assoc_legendre(l, m, x) == _Tp(0));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test_m_gt_l<float>();
|
||||
test_m_gt_l<double>();
|
||||
test_m_gt_l<long double>();
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-options "-D__STDCPP_WANT_MATH_SPEC_FUNCS__ -ffp-contract=off" }
|
||||
|
||||
// Copyright (C) 2019 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
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <initializer_list>
|
||||
#include <cmath>
|
||||
#if defined(__TEST_DEBUG)
|
||||
# include <iostream>
|
||||
# define VERIFY(A) \
|
||||
if (!(A)) \
|
||||
{ \
|
||||
std::cout << "line " << __LINE__ \
|
||||
<< " std::sph_legendre(l, m, x) == 0: " << (A) \
|
||||
<< '\n'; \
|
||||
}
|
||||
#else
|
||||
# include <testsuite_hooks.h>
|
||||
#endif
|
||||
|
||||
template<typename _Tp>
|
||||
void
|
||||
test_m_gt_l()
|
||||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
for (auto l : {0u, 1u, 2u, 5u})
|
||||
for (auto m : {l + 1u, l + 2u})
|
||||
for (auto i : {-2, -1, 0, 1, 2})
|
||||
{
|
||||
auto theta = std::acos(_Tp(i * 0.5L));
|
||||
VERIFY(std::sph_legendre(l, m, theta) == _Tp(0));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test_m_gt_l<float>();
|
||||
test_m_gt_l<double>();
|
||||
test_m_gt_l<long double>();
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
// { dg-do run }
|
||||
// { dg-options "-std=c++98 -ffp-contract=off" }
|
||||
|
||||
// Copyright (C) 2019 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
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <tr1/cmath>
|
||||
#if defined(__TEST_DEBUG)
|
||||
# include <iostream>
|
||||
# define VERIFY(A) \
|
||||
if (!(A)) \
|
||||
{ \
|
||||
std::cout << "line " << __LINE__ \
|
||||
<< " std::tr1::assoc_legendre(l, m, x) == 0: " << (A) \
|
||||
<< '\n'; \
|
||||
}
|
||||
#else
|
||||
# include <testsuite_hooks.h>
|
||||
#endif
|
||||
|
||||
template<typename _Tp>
|
||||
void
|
||||
test_m_gt_l()
|
||||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
unsigned int larr[4] = {0u, 1u, 2u, 5u};
|
||||
for (unsigned int l = 0; l < 4; ++l)
|
||||
for (unsigned int m = larr[l] + 1u; m <= larr[l] + 2u; ++m)
|
||||
for (int i = -2; i <= +2; ++i)
|
||||
{
|
||||
_Tp x = _Tp(i * 0.5L);
|
||||
VERIFY(std::tr1::assoc_legendre(larr[l], m, x) == _Tp(0));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test_m_gt_l<float>();
|
||||
test_m_gt_l<double>();
|
||||
test_m_gt_l<long double>();
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
// { dg-do run }
|
||||
// { dg-options "-std=c++98 -ffp-contract=off" }
|
||||
|
||||
// Copyright (C) 2019 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
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <tr1/cmath>
|
||||
#if defined(__TEST_DEBUG)
|
||||
# include <iostream>
|
||||
# define VERIFY(A) \
|
||||
if (!(A)) \
|
||||
{ \
|
||||
std::cout << "line " << __LINE__ \
|
||||
<< " std::sph_legendre(l, m, x) == 0: " << (A) \
|
||||
<< '\n'; \
|
||||
}
|
||||
#else
|
||||
# include <testsuite_hooks.h>
|
||||
#endif
|
||||
|
||||
template<typename _Tp>
|
||||
void
|
||||
test_m_gt_l()
|
||||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
unsigned int larr[4] = {0u, 1u, 2u, 5u};
|
||||
for (unsigned int l = 0; l < 4; ++l)
|
||||
for (unsigned int m = larr[l] + 1u; m <= larr[l] + 2u; ++m)
|
||||
for (int i = -2; i <= +2; ++i)
|
||||
{
|
||||
_Tp theta = std::acos(_Tp(i * 0.5L));
|
||||
VERIFY(std::tr1::sph_legendre(larr[l], m, theta) == _Tp(0));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test_m_gt_l<float>();
|
||||
test_m_gt_l<double>();
|
||||
test_m_gt_l<long double>();
|
||||
}
|
Loading…
Reference in New Issue
Block a user