mirror of
https://github.com/boostorg/math.git
synced 2026-01-19 04:22:09 +00:00
Fix complex number routines to work with signed zeros, changes involve:
* Use boost::math::signbit rather than comparison to zero. * Use boost::math::changesign rather than unary negation (unary negation fails for Intel on Linux when the argument is a zero). * Update to use boost::math::isnan/isinf rather than the old code. * Update to use boost::math constants. Fixes #6171. [SVN r75933]
This commit is contained in:
@@ -38,11 +38,15 @@ std::complex<T> acos(const std::complex<T>& z)
|
||||
static const T half = static_cast<T>(0.5L);
|
||||
static const T a_crossover = static_cast<T>(1.5L);
|
||||
static const T b_crossover = static_cast<T>(0.6417L);
|
||||
static const T s_pi = static_cast<T>(3.141592653589793238462643383279502884197L);
|
||||
static const T half_pi = static_cast<T>(1.57079632679489661923132169163975144L);
|
||||
static const T log_two = static_cast<T>(0.69314718055994530941723212145817657L);
|
||||
static const T quarter_pi = static_cast<T>(0.78539816339744830961566084581987572L);
|
||||
static const T s_pi = boost::math::constants::pi<T>();
|
||||
static const T half_pi = s_pi / 2;
|
||||
static const T log_two = boost::math::constants::ln_two<T>();
|
||||
static const T quarter_pi = s_pi / 4;
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
//
|
||||
// Get real and imaginary parts, discard the signs as we can
|
||||
// figure out the sign of the result later:
|
||||
@@ -58,14 +62,14 @@ std::complex<T> acos(const std::complex<T>& z)
|
||||
// but doing it this way prevents overflow/underflow arithmetic
|
||||
// in the main body of the logic, which may trip up some machines:
|
||||
//
|
||||
if(std::numeric_limits<T>::has_infinity && (x == std::numeric_limits<T>::infinity()))
|
||||
if((boost::math::isinf)(x))
|
||||
{
|
||||
if(y == std::numeric_limits<T>::infinity())
|
||||
if((boost::math::isinf)(y))
|
||||
{
|
||||
real = quarter_pi;
|
||||
imag = std::numeric_limits<T>::infinity();
|
||||
}
|
||||
else if(detail::test_is_nan(y))
|
||||
else if((boost::math::isnan)(y))
|
||||
{
|
||||
return std::complex<T>(y, -std::numeric_limits<T>::infinity());
|
||||
}
|
||||
@@ -76,18 +80,18 @@ std::complex<T> acos(const std::complex<T>& z)
|
||||
imag = std::numeric_limits<T>::infinity();
|
||||
}
|
||||
}
|
||||
else if(detail::test_is_nan(x))
|
||||
else if((boost::math::isnan)(x))
|
||||
{
|
||||
if(y == std::numeric_limits<T>::infinity())
|
||||
return std::complex<T>(x, (z.imag() < 0) ? std::numeric_limits<T>::infinity() : -std::numeric_limits<T>::infinity());
|
||||
if((boost::math::isinf)(y))
|
||||
return std::complex<T>(x, ((boost::math::signbit)(z.imag())) ? std::numeric_limits<T>::infinity() : -std::numeric_limits<T>::infinity());
|
||||
return std::complex<T>(x, x);
|
||||
}
|
||||
else if(std::numeric_limits<T>::has_infinity && (y == std::numeric_limits<T>::infinity()))
|
||||
else if((boost::math::isinf)(y))
|
||||
{
|
||||
real = half_pi;
|
||||
imag = std::numeric_limits<T>::infinity();
|
||||
}
|
||||
else if(detail::test_is_nan(y))
|
||||
else if((boost::math::isnan)(y))
|
||||
{
|
||||
return std::complex<T>((x == 0) ? half_pi : y, y);
|
||||
}
|
||||
@@ -98,7 +102,7 @@ std::complex<T> acos(const std::complex<T>& z)
|
||||
// begin with the special case for real numbers:
|
||||
//
|
||||
if((y == 0) && (x <= one))
|
||||
return std::complex<T>((x == 0) ? half_pi : std::acos(z.real()));
|
||||
return std::complex<T>((x == 0) ? half_pi : std::acos(z.real()), (boost::math::changesign)(z.imag()));
|
||||
//
|
||||
// Figure out if our input is within the "safe area" identified by Hull et al.
|
||||
// This would be more efficient with portable floating point exception handling;
|
||||
@@ -222,12 +226,15 @@ std::complex<T> acos(const std::complex<T>& z)
|
||||
//
|
||||
// Finish off by working out the sign of the result:
|
||||
//
|
||||
if(z.real() < 0)
|
||||
if((boost::math::signbit)(z.real()))
|
||||
real = s_pi - real;
|
||||
if(z.imag() > 0)
|
||||
imag = -imag;
|
||||
if(!(boost::math::signbit)(z.imag()))
|
||||
imag = (boost::math::changesign)(imag);
|
||||
|
||||
return std::complex<T>(real, imag);
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
} } // namespaces
|
||||
|
||||
@@ -24,7 +24,7 @@ inline std::complex<T> acosh(const std::complex<T>& z)
|
||||
// as well as compatibility with C99.
|
||||
//
|
||||
std::complex<T> result = boost::math::acos(z);
|
||||
if(!detail::test_is_nan(result.imag()) && result.imag() <= 0)
|
||||
if(!(boost::math::isnan)(result.imag()) && signbit(result.imag()))
|
||||
return detail::mult_i(result);
|
||||
return detail::mult_minus_i(result);
|
||||
}
|
||||
|
||||
@@ -38,11 +38,14 @@ inline std::complex<T> asin(const std::complex<T>& z)
|
||||
static const T half = static_cast<T>(0.5L);
|
||||
static const T a_crossover = static_cast<T>(1.5L);
|
||||
static const T b_crossover = static_cast<T>(0.6417L);
|
||||
//static const T pi = static_cast<T>(3.141592653589793238462643383279502884197L);
|
||||
static const T half_pi = static_cast<T>(1.57079632679489661923132169163975144L);
|
||||
static const T log_two = static_cast<T>(0.69314718055994530941723212145817657L);
|
||||
static const T quarter_pi = static_cast<T>(0.78539816339744830961566084581987572L);
|
||||
|
||||
static const T s_pi = boost::math::constants::pi<T>();
|
||||
static const T half_pi = s_pi / 2;
|
||||
static const T log_two = boost::math::constants::ln_two<T>();
|
||||
static const T quarter_pi = s_pi / 4;
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
//
|
||||
// Get real and imaginary parts, discard the signs as we can
|
||||
// figure out the sign of the result later:
|
||||
@@ -57,11 +60,11 @@ inline std::complex<T> asin(const std::complex<T>& z)
|
||||
// below, but handling it as a special case prevents overflow/underflow
|
||||
// arithmetic which may trip up some machines:
|
||||
//
|
||||
if(detail::test_is_nan(x))
|
||||
if((boost::math::isnan)(x))
|
||||
{
|
||||
if(detail::test_is_nan(y))
|
||||
if((boost::math::isnan)(y))
|
||||
return std::complex<T>(x, x);
|
||||
if(std::numeric_limits<T>::has_infinity && (y == std::numeric_limits<T>::infinity()))
|
||||
if((boost::math::isinf)(y))
|
||||
{
|
||||
real = x;
|
||||
imag = std::numeric_limits<T>::infinity();
|
||||
@@ -69,14 +72,14 @@ inline std::complex<T> asin(const std::complex<T>& z)
|
||||
else
|
||||
return std::complex<T>(x, x);
|
||||
}
|
||||
else if(detail::test_is_nan(y))
|
||||
else if((boost::math::isnan)(y))
|
||||
{
|
||||
if(x == 0)
|
||||
{
|
||||
real = 0;
|
||||
imag = y;
|
||||
}
|
||||
else if(std::numeric_limits<T>::has_infinity && (x == std::numeric_limits<T>::infinity()))
|
||||
else if((boost::math::isinf)(x))
|
||||
{
|
||||
real = y;
|
||||
imag = std::numeric_limits<T>::infinity();
|
||||
@@ -84,9 +87,9 @@ inline std::complex<T> asin(const std::complex<T>& z)
|
||||
else
|
||||
return std::complex<T>(y, y);
|
||||
}
|
||||
else if(std::numeric_limits<T>::has_infinity && (x == std::numeric_limits<T>::infinity()))
|
||||
else if((boost::math::isinf)(x))
|
||||
{
|
||||
if(y == std::numeric_limits<T>::infinity())
|
||||
if((boost::math::isinf)(y))
|
||||
{
|
||||
real = quarter_pi;
|
||||
imag = std::numeric_limits<T>::infinity();
|
||||
@@ -97,7 +100,7 @@ inline std::complex<T> asin(const std::complex<T>& z)
|
||||
imag = std::numeric_limits<T>::infinity();
|
||||
}
|
||||
}
|
||||
else if(std::numeric_limits<T>::has_infinity && (y == std::numeric_limits<T>::infinity()))
|
||||
else if((boost::math::isinf)(y))
|
||||
{
|
||||
real = 0;
|
||||
imag = std::numeric_limits<T>::infinity();
|
||||
@@ -108,7 +111,7 @@ inline std::complex<T> asin(const std::complex<T>& z)
|
||||
// special case for real numbers:
|
||||
//
|
||||
if((y == 0) && (x <= one))
|
||||
return std::complex<T>(std::asin(z.real()));
|
||||
return std::complex<T>(std::asin(z.real()), z.imag());
|
||||
//
|
||||
// Figure out if our input is within the "safe area" identified by Hull et al.
|
||||
// This would be more efficient with portable floating point exception handling;
|
||||
@@ -174,7 +177,7 @@ inline std::complex<T> asin(const std::complex<T>& z)
|
||||
if(x < one)
|
||||
{
|
||||
real = std::asin(x);
|
||||
imag = y / std::sqrt(xp1*xm1);
|
||||
imag = y / std::sqrt(-xp1*xm1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -232,12 +235,15 @@ inline std::complex<T> asin(const std::complex<T>& z)
|
||||
//
|
||||
// Finish off by working out the sign of the result:
|
||||
//
|
||||
if(z.real() < 0)
|
||||
real = -real;
|
||||
if(z.imag() < 0)
|
||||
imag = -imag;
|
||||
if((boost::math::signbit)(z.real()))
|
||||
real = (boost::math::changesign)(real);
|
||||
if((boost::math::signbit)(z.imag()))
|
||||
imag = (boost::math::changesign)(imag);
|
||||
|
||||
return std::complex<T>(real, imag);
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
} } // namespaces
|
||||
|
||||
@@ -37,14 +37,19 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
// at : http://jove.prohosting.com/~skripty/toc.htm
|
||||
//
|
||||
|
||||
static const T half_pi = static_cast<T>(1.57079632679489661923132169163975144L);
|
||||
static const T pi = static_cast<T>(3.141592653589793238462643383279502884197L);
|
||||
static const T pi = boost::math::constants::pi<T>();
|
||||
static const T half_pi = pi / 2;
|
||||
static const T one = static_cast<T>(1.0L);
|
||||
static const T two = static_cast<T>(2.0L);
|
||||
static const T four = static_cast<T>(4.0L);
|
||||
static const T zero = static_cast<T>(0);
|
||||
static const T a_crossover = static_cast<T>(0.3L);
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
|
||||
T x = std::fabs(z.real());
|
||||
T y = std::fabs(z.imag());
|
||||
|
||||
@@ -56,20 +61,20 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
//
|
||||
// Begin by handling the special cases specified in C99:
|
||||
//
|
||||
if(detail::test_is_nan(x))
|
||||
if((boost::math::isnan)(x))
|
||||
{
|
||||
if(detail::test_is_nan(y))
|
||||
if((boost::math::isnan)(y))
|
||||
return std::complex<T>(x, x);
|
||||
else if(std::numeric_limits<T>::has_infinity && (y == std::numeric_limits<T>::infinity()))
|
||||
return std::complex<T>(0, ((z.imag() < 0) ? -half_pi : half_pi));
|
||||
else if((boost::math::isinf)(y))
|
||||
return std::complex<T>(0, ((boost::math::signbit)(z.imag()) ? -half_pi : half_pi));
|
||||
else
|
||||
return std::complex<T>(x, x);
|
||||
}
|
||||
else if(detail::test_is_nan(y))
|
||||
else if((boost::math::isnan)(y))
|
||||
{
|
||||
if(x == 0)
|
||||
return std::complex<T>(x, y);
|
||||
if(std::numeric_limits<T>::has_infinity && (x == std::numeric_limits<T>::infinity()))
|
||||
if((boost::math::isinf)(x))
|
||||
return std::complex<T>(0, y);
|
||||
else
|
||||
return std::complex<T>(y, y);
|
||||
@@ -104,7 +109,7 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
T alpha = two*x / (one + xx + yy);
|
||||
if(alpha < a_crossover)
|
||||
{
|
||||
real = boost::math::log1p(alpha) - boost::math::log1p(-alpha);
|
||||
real = boost::math::log1p(alpha) - boost::math::log1p((boost::math::changesign)(alpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -112,13 +117,13 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
real = boost::math::log1p(x2 + xx + yy) - std::log(xm1*xm1 + yy);
|
||||
}
|
||||
real /= four;
|
||||
if(z.real() < 0)
|
||||
real = -real;
|
||||
if((boost::math::signbit)(z.real()))
|
||||
real = (boost::math::changesign)(real);
|
||||
|
||||
imag = std::atan2((y * two), (one - xx - yy));
|
||||
imag /= two;
|
||||
if(z.imag() < 0)
|
||||
imag = -imag;
|
||||
imag = (boost::math::changesign)(imag);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -133,9 +138,7 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
T alpha = 0;
|
||||
if(x >= safe_upper)
|
||||
{
|
||||
// this is really a test for infinity,
|
||||
// but we may not have the necessary numeric_limits support:
|
||||
if((x > (std::numeric_limits<T>::max)()) || (y > (std::numeric_limits<T>::max)()))
|
||||
if((boost::math::isinf)(x) || (boost::math::isinf)(y))
|
||||
{
|
||||
alpha = 0;
|
||||
}
|
||||
@@ -180,7 +183,7 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
}
|
||||
if(alpha < a_crossover)
|
||||
{
|
||||
real = boost::math::log1p(alpha) - boost::math::log1p(-alpha);
|
||||
real = boost::math::log1p(alpha) - boost::math::log1p((boost::math::changesign)(alpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -194,8 +197,8 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
}
|
||||
|
||||
real /= four;
|
||||
if(z.real() < 0)
|
||||
real = -real;
|
||||
if((boost::math::signbit)(z.real()))
|
||||
real = (boost::math::changesign)(real);
|
||||
|
||||
//
|
||||
// Now handle imaginary part, this is much easier,
|
||||
@@ -234,10 +237,13 @@ std::complex<T> atanh(const std::complex<T>& z)
|
||||
imag = std::atan2(two*y, 1 - x*x);
|
||||
}
|
||||
imag /= two;
|
||||
if(z.imag() < 0)
|
||||
imag = -imag;
|
||||
if((boost::math::signbit)(z.imag()))
|
||||
imag = (boost::math::changesign)(imag);
|
||||
}
|
||||
return std::complex<T>(real, imag);
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
} } // namespaces
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
#include <boost/limits.hpp>
|
||||
#include <math.h> // isnan where available
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std{ using ::sqrt; }
|
||||
@@ -23,22 +27,10 @@ namespace std{ using ::sqrt; }
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T>
|
||||
inline bool test_is_nan(T t)
|
||||
{
|
||||
// Comparisons with Nan's always fail:
|
||||
return std::numeric_limits<T>::has_infinity && (!(t <= std::numeric_limits<T>::infinity()) || !(t >= -std::numeric_limits<T>::infinity()));
|
||||
}
|
||||
#ifdef isnan
|
||||
template<> inline bool test_is_nan<float>(float t) { return isnan(t); }
|
||||
template<> inline bool test_is_nan<double>(double t) { return isnan(t); }
|
||||
template<> inline bool test_is_nan<long double>(long double t) { return isnan(t); }
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline T mult_minus_one(const T& t)
|
||||
{
|
||||
return test_is_nan(t) ? t : -t;
|
||||
return (boost::math::isnan)(t) ? t : (boost::math::changesign)(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -77,6 +77,15 @@ bool check_complex(const std::complex<T>& a, const std::complex<T>& b, int max_e
|
||||
}
|
||||
}
|
||||
|
||||
if((boost::math::isnan)(a.real()))
|
||||
{
|
||||
BOOST_ERROR("Found non-finite value for real part: " << a);
|
||||
}
|
||||
if((boost::math::isnan)(a.imag()))
|
||||
{
|
||||
BOOST_ERROR("Found non-finite value for inaginary part: " << a);
|
||||
}
|
||||
|
||||
T rel = boost::math::fabs((b-a)/b) / eps;
|
||||
if( rel > max_error)
|
||||
{
|
||||
@@ -276,7 +285,7 @@ void check_spots(const T&)
|
||||
// but an attempt to access it will terminate the program!!!!
|
||||
if(std::numeric_limits<T>::has_quiet_NaN)
|
||||
nan = std::numeric_limits<T>::quiet_NaN();
|
||||
if(boost::math::detail::test_is_nan(nan))
|
||||
if((boost::math::isnan)(nan))
|
||||
test_nan = true;
|
||||
#endif
|
||||
#if defined(__DECCXX) && !defined(_IEEE_FP)
|
||||
@@ -303,11 +312,11 @@ void check_spots(const T&)
|
||||
{
|
||||
result = boost::math::acos(ct(zero,nan));
|
||||
BOOST_CHECK_CLOSE(result.real(), half_pi, eps*200);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acos(ct(mzero,nan));
|
||||
BOOST_CHECK_CLOSE(result.real(), half_pi, eps*200);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
}
|
||||
if(test_infinity)
|
||||
{
|
||||
@@ -323,8 +332,8 @@ void check_spots(const T&)
|
||||
if(test_nan)
|
||||
{
|
||||
result = boost::math::acos(ct(one, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
}
|
||||
if(test_infinity)
|
||||
{
|
||||
@@ -363,41 +372,70 @@ void check_spots(const T&)
|
||||
if(test_nan)
|
||||
{
|
||||
result = boost::math::acos(ct(infinity, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK(std::fabs(result.imag()) == infinity);
|
||||
|
||||
result = boost::math::acos(ct(-infinity, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK(std::fabs(result.imag()) == infinity);
|
||||
|
||||
result = boost::math::acos(ct(nan, zero));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acos(ct(nan, -zero));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acos(ct(nan, one));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acos(ct(nan, -one));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acos(ct(nan, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acos(ct(nan, infinity));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK(result.imag() == -infinity);
|
||||
|
||||
result = boost::math::acos(ct(nan, -infinity));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK(result.imag() == infinity);
|
||||
}
|
||||
if(boost::math::signbit(mzero))
|
||||
{
|
||||
result = boost::math::acos(ct(-1.25f, zero));
|
||||
BOOST_CHECK(result.real() > 0);
|
||||
BOOST_CHECK(result.imag() < 0);
|
||||
result = boost::math::asin(ct(-1.75f, mzero));
|
||||
BOOST_CHECK(result.real() < 0);
|
||||
BOOST_CHECK(result.imag() < 0);
|
||||
result = boost::math::atan(ct(mzero, -1.75f));
|
||||
BOOST_CHECK(result.real() < 0);
|
||||
BOOST_CHECK(result.imag() < 0);
|
||||
|
||||
result = boost::math::acos(ct(zero, zero));
|
||||
BOOST_CHECK(result.real() > 0);
|
||||
BOOST_CHECK(result.imag() == 0);
|
||||
BOOST_CHECK((boost::math::signbit)(result.imag()));
|
||||
result = boost::math::acos(ct(zero, mzero));
|
||||
BOOST_CHECK(result.real() > 0);
|
||||
BOOST_CHECK(result.imag() == 0);
|
||||
BOOST_CHECK(0 == (boost::math::signbit)(result.imag()));
|
||||
result = boost::math::acos(ct(mzero, zero));
|
||||
BOOST_CHECK(result.real() > 0);
|
||||
BOOST_CHECK(result.imag() == 0);
|
||||
BOOST_CHECK((boost::math::signbit)(result.imag()));
|
||||
result = boost::math::acos(ct(mzero, mzero));
|
||||
BOOST_CHECK(result.real() > 0);
|
||||
BOOST_CHECK(result.imag() == 0);
|
||||
BOOST_CHECK(0 == (boost::math::signbit)(result.imag()));
|
||||
}
|
||||
|
||||
//
|
||||
// C99 spot tests for acosh:
|
||||
@@ -408,7 +446,7 @@ void check_spots(const T&)
|
||||
|
||||
result = boost::math::acosh(ct(zero, mzero));
|
||||
BOOST_CHECK(result.real() == 0);
|
||||
BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);
|
||||
BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);
|
||||
|
||||
result = boost::math::acosh(ct(mzero, zero));
|
||||
BOOST_CHECK(result.real() == 0);
|
||||
@@ -416,7 +454,7 @@ void check_spots(const T&)
|
||||
|
||||
result = boost::math::acosh(ct(mzero, mzero));
|
||||
BOOST_CHECK(result.real() == 0);
|
||||
BOOST_CHECK_CLOSE(result.imag(), half_pi, eps*200);
|
||||
BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);
|
||||
|
||||
if(test_infinity)
|
||||
{
|
||||
@@ -432,8 +470,8 @@ void check_spots(const T&)
|
||||
if(test_nan)
|
||||
{
|
||||
result = boost::math::acosh(ct(one, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
}
|
||||
if(test_infinity)
|
||||
{
|
||||
@@ -474,31 +512,37 @@ void check_spots(const T&)
|
||||
{
|
||||
result = boost::math::acosh(ct(infinity, nan));
|
||||
BOOST_CHECK(result.real() == infinity);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acosh(ct(-infinity, nan));
|
||||
BOOST_CHECK(result.real() == infinity);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acosh(ct(nan, one));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acosh(ct(nan, infinity));
|
||||
BOOST_CHECK(result.real() == infinity);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acosh(ct(nan, -one));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acosh(ct(nan, -infinity));
|
||||
BOOST_CHECK(result.real() == infinity);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::acosh(ct(nan, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
}
|
||||
if(boost::math::signbit(mzero))
|
||||
{
|
||||
result = boost::math::acosh(ct(-2.5f, zero));
|
||||
BOOST_CHECK(result.real() > 0);
|
||||
BOOST_CHECK(result.imag() > 0);
|
||||
}
|
||||
//
|
||||
// C99 spot checks for asinh:
|
||||
@@ -541,16 +585,16 @@ void check_spots(const T&)
|
||||
if(test_nan)
|
||||
{
|
||||
result = boost::math::asinh(ct(one, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::asinh(ct(-one, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::asinh(ct(zero, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
}
|
||||
|
||||
if(test_infinity)
|
||||
@@ -592,39 +636,45 @@ void check_spots(const T&)
|
||||
{
|
||||
result = boost::math::asinh(ct(infinity, nan));
|
||||
BOOST_CHECK(result.real() == infinity);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::asinh(ct(-infinity, nan));
|
||||
BOOST_CHECK(result.real() == -infinity);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::asinh(ct(nan, zero));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK(result.imag() == 0);
|
||||
|
||||
result = boost::math::asinh(ct(nan, mzero));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK(result.imag() == 0);
|
||||
|
||||
result = boost::math::asinh(ct(nan, one));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::asinh(ct(nan, -one));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::asinh(ct(nan, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::asinh(ct(nan, infinity));
|
||||
BOOST_CHECK(std::fabs(result.real()) == infinity);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::asinh(ct(nan, -infinity));
|
||||
BOOST_CHECK(std::fabs(result.real()) == infinity);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
}
|
||||
if(boost::math::signbit(mzero))
|
||||
{
|
||||
result = boost::math::asinh(ct(zero, 1.5f));
|
||||
BOOST_CHECK(result.real() > 0);
|
||||
BOOST_CHECK(result.imag() > 0);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -650,11 +700,11 @@ void check_spots(const T&)
|
||||
{
|
||||
result = boost::math::atanh(ct(zero, nan));
|
||||
BOOST_CHECK(result.real() == zero);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::atanh(ct(-zero, nan));
|
||||
BOOST_CHECK(result.real() == zero);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
}
|
||||
|
||||
if(test_infinity)
|
||||
@@ -694,12 +744,12 @@ void check_spots(const T&)
|
||||
if(test_nan)
|
||||
{
|
||||
result = boost::math::atanh(ct(pi, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::atanh(ct(-pi, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
}
|
||||
|
||||
if(test_infinity)
|
||||
@@ -741,19 +791,19 @@ void check_spots(const T&)
|
||||
{
|
||||
result = boost::math::atanh(ct(infinity, nan));
|
||||
BOOST_CHECK(result.real() == 0);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::atanh(ct(-infinity, nan));
|
||||
BOOST_CHECK(result.real() == 0);
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::atanh(ct(nan, pi));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::atanh(ct(nan, -pi));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
result = boost::math::atanh(ct(nan, infinity));
|
||||
BOOST_CHECK(result.real() == 0);
|
||||
@@ -764,10 +814,16 @@ void check_spots(const T&)
|
||||
BOOST_CHECK_CLOSE(result.imag(), -half_pi, eps*200);
|
||||
|
||||
result = boost::math::atanh(ct(nan, nan));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.real()));
|
||||
BOOST_CHECK(boost::math::detail::test_is_nan(result.imag()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.real()));
|
||||
BOOST_CHECK((boost::math::isnan)(result.imag()));
|
||||
|
||||
}
|
||||
if(boost::math::signbit(mzero))
|
||||
{
|
||||
result = boost::math::atanh(ct(-2.0f, mzero));
|
||||
BOOST_CHECK(result.real() < 0);
|
||||
BOOST_CHECK(result.imag() < 0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user