Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r75933 - in trunk: boost/math/complex libs/math/test
From: john_at_[hidden]
Date: 2011-12-13 13:11:48


Author: johnmaddock
Date: 2011-12-13 13:11:46 EST (Tue, 13 Dec 2011)
New Revision: 75933
URL: http://svn.boost.org/trac/boost/changeset/75933

Log:
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.
Text files modified:
   trunk/boost/math/complex/acos.hpp | 39 ++++---
   trunk/boost/math/complex/acosh.hpp | 2
   trunk/boost/math/complex/asin.hpp | 44 +++++----
   trunk/boost/math/complex/atanh.hpp | 46 +++++----
   trunk/boost/math/complex/details.hpp | 18 +--
   trunk/libs/math/test/complex_test.cpp | 186 ++++++++++++++++++++++++++-------------
   6 files changed, 201 insertions(+), 134 deletions(-)

Modified: trunk/boost/math/complex/acos.hpp
==============================================================================
--- trunk/boost/math/complex/acos.hpp (original)
+++ trunk/boost/math/complex/acos.hpp 2011-12-13 13:11:46 EST (Tue, 13 Dec 2011)
@@ -38,11 +38,15 @@
    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 @@
    // 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 @@
          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 @@
       // 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 @@
    //
    // 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

Modified: trunk/boost/math/complex/acosh.hpp
==============================================================================
--- trunk/boost/math/complex/acosh.hpp (original)
+++ trunk/boost/math/complex/acosh.hpp 2011-12-13 13:11:46 EST (Tue, 13 Dec 2011)
@@ -24,7 +24,7 @@
    // 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);
 }

Modified: trunk/boost/math/complex/asin.hpp
==============================================================================
--- trunk/boost/math/complex/asin.hpp (original)
+++ trunk/boost/math/complex/asin.hpp 2011-12-13 13:11:46 EST (Tue, 13 Dec 2011)
@@ -38,11 +38,14 @@
    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 @@
    // 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 @@
       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 @@
       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 @@
          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 @@
       // 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 @@
             if(x < one)
             {
                real = std::asin(x);
- imag = y / std::sqrt(xp1*xm1);
+ imag = y / std::sqrt(-xp1*xm1);
             }
             else
             {
@@ -232,12 +235,15 @@
    //
    // 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

Modified: trunk/boost/math/complex/atanh.hpp
==============================================================================
--- trunk/boost/math/complex/atanh.hpp (original)
+++ trunk/boost/math/complex/atanh.hpp 2011-12-13 13:11:46 EST (Tue, 13 Dec 2011)
@@ -37,14 +37,19 @@
    // 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 @@
    //
    // 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 @@
       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 @@
          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 @@
       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 @@
       }
       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 @@
       }
       
       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 @@
             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

Modified: trunk/boost/math/complex/details.hpp
==============================================================================
--- trunk/boost/math/complex/details.hpp (original)
+++ trunk/boost/math/complex/details.hpp 2011-12-13 13:11:46 EST (Tue, 13 Dec 2011)
@@ -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; }
@@ -24,21 +28,9 @@
 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>

Modified: trunk/libs/math/test/complex_test.cpp
==============================================================================
--- trunk/libs/math/test/complex_test.cpp (original)
+++ trunk/libs/math/test/complex_test.cpp 2011-12-13 13:11:46 EST (Tue, 13 Dec 2011)
@@ -77,6 +77,15 @@
       }
    }
 
+ 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 @@
    // 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 @@
    {
       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 @@
    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 @@
    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 @@
 
    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 @@
    
    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 @@
    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 @@
    {
       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 @@
    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 @@
    {
       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 @@
    {
       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 @@
    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 @@
    {
       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 @@
       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);
+ }
 }
 
 //


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk