mirror of
https://github.com/boostorg/math.git
synced 2026-02-13 12:32:15 +00:00
Changed calculation of upper and lower safe bounds to avoid problems with std::sqrt(long double) returning infinities.
[SVN r31885]
This commit is contained in:
@@ -106,8 +106,8 @@ std::complex<T> acos(const std::complex<T>& z)
|
||||
// fortunately the quantities M and u identified by Hull et al (figure 3),
|
||||
// match with the max() and min() methods of numeric_limits<T>.
|
||||
//
|
||||
T safe_max = std::sqrt((std::numeric_limits<T>::max)()) / T(8);
|
||||
T safe_min = static_cast<T>(4) * std::sqrt((std::numeric_limits<T>::min)());
|
||||
T safe_max = detail::safe_max(static_cast<T>(8));
|
||||
T safe_min = detail::safe_min(static_cast<T>(4));
|
||||
|
||||
T xp1 = one + x;
|
||||
T xm1 = x - one;
|
||||
|
||||
@@ -116,8 +116,8 @@ inline std::complex<T> asin(const std::complex<T>& z)
|
||||
// fortunately the quantities M and u identified by Hull et al (figure 3),
|
||||
// match with the max() and min() methods of numeric_limits<T>.
|
||||
//
|
||||
T safe_max = std::sqrt((std::numeric_limits<T>::max)()) / T(8);
|
||||
T safe_min = static_cast<T>(4) * std::sqrt((std::numeric_limits<T>::min)());
|
||||
T safe_max = detail::safe_max(static_cast<T>(8));
|
||||
T safe_min = detail::safe_min(static_cast<T>(4));
|
||||
|
||||
T xp1 = one + x;
|
||||
T xm1 = x - one;
|
||||
|
||||
@@ -50,8 +50,8 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
|
||||
T real, imag; // our results
|
||||
|
||||
T safe_upper = std::sqrt((std::numeric_limits<T>::max)()) / two;
|
||||
T safe_lower = std::sqrt((std::numeric_limits<T>::min)());
|
||||
T safe_upper = detail::safe_max(two);
|
||||
T safe_lower = detail::safe_min(static_cast<T>(2));
|
||||
|
||||
//
|
||||
// Begin by handling the special cases specified in C99:
|
||||
@@ -131,13 +131,13 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
// without either overflow or underflow in the squared terms.
|
||||
//
|
||||
T alpha = 0;
|
||||
if(x > safe_upper)
|
||||
if(x >= safe_upper)
|
||||
{
|
||||
if((x == std::numeric_limits<T>::infinity()) || (y == std::numeric_limits<T>::infinity()))
|
||||
{
|
||||
alpha = 0;
|
||||
}
|
||||
else if(y > safe_upper)
|
||||
else if(y >= safe_upper)
|
||||
{
|
||||
// Big x and y: divide alpha through by x*y:
|
||||
alpha = (two/y) / (x/y + y/x);
|
||||
@@ -153,7 +153,7 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
alpha = two/x;
|
||||
}
|
||||
}
|
||||
else if(y > safe_upper)
|
||||
else if(y >= safe_upper)
|
||||
{
|
||||
if(x > one)
|
||||
{
|
||||
@@ -226,7 +226,10 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
//
|
||||
// y^2 is negligible:
|
||||
//
|
||||
imag = std::atan2(two*y, 1 - x*x);
|
||||
if((y == zero) && (x == one))
|
||||
imag = 0;
|
||||
else
|
||||
imag = std::atan2(two*y, 1 - x*x);
|
||||
}
|
||||
imag /= two;
|
||||
if(z.imag() < 0)
|
||||
|
||||
@@ -10,13 +10,17 @@
|
||||
// inverse trig complex functions, it also contains all the includes
|
||||
// that we need to implement all these functions.
|
||||
//
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/no_tr1/complex.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <math.h> // isnan where available
|
||||
#include <cmath>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std{ using ::sqrt; }
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T>
|
||||
inline bool test_is_nan(T t)
|
||||
@@ -48,6 +52,29 @@ inline std::complex<T> mult_minus_i(const std::complex<T>& t)
|
||||
return std::complex<T>(t.imag(), mult_minus_one(t.real()));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T safe_max(T t)
|
||||
{
|
||||
return std::sqrt((std::numeric_limits<T>::max)()) / t;
|
||||
}
|
||||
inline long double safe_max(long double t)
|
||||
{
|
||||
// long double sqrt often returns infinity due to
|
||||
// insufficient internal precision:
|
||||
return std::sqrt((std::numeric_limits<double>::max)()) / t;
|
||||
}
|
||||
template <class T>
|
||||
inline T safe_min(T t)
|
||||
{
|
||||
return std::sqrt((std::numeric_limits<T>::min)()) * t;
|
||||
}
|
||||
inline long double safe_min(long double t)
|
||||
{
|
||||
// long double sqrt often returns zero due to
|
||||
// insufficient internal precision:
|
||||
return std::sqrt((std::numeric_limits<double>::min)()) * t;
|
||||
}
|
||||
|
||||
} } } // namespaces
|
||||
|
||||
#endif // BOOST_MATH_COMPLEX_DETAILS_INCLUDED
|
||||
|
||||
Reference in New Issue
Block a user