Blame include/cppunit/portability/FloatingPoint.h

Packit 8c9aa0
#ifndef CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED
Packit 8c9aa0
#define CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED
Packit 8c9aa0
Packit 8c9aa0
#include <cppunit/Portability.h>
Packit 8c9aa0
#include <math.h>
Packit 8c9aa0
Packit 8c9aa0
#if defined(__sun) && !defined(CPPUNIT_HAVE_ISFINITE) && defined(CPPUNIT_HAVE_FINITE)
Packit 8c9aa0
#include <ieeefp.h>
Packit 8c9aa0
  // <math.h> is still needed for usage of fabs in TestAssert.cpp
Packit 8c9aa0
#endif
Packit 8c9aa0
Packit 8c9aa0
CPPUNIT_NS_BEGIN
Packit 8c9aa0
Packit 8c9aa0
/// \brief Tests if a floating-point is a NaN.
Packit 8c9aa0
// According to IEEE-754 floating point standard, 
Packit 8c9aa0
// (see e.g. page 8 of
Packit 8c9aa0
// http://www.cs.berkeley.edu/~wkahan/ieee754status/ieee754.ps) 
Packit 8c9aa0
// all comparisons with NaN are false except "x != x", which is true.
Packit 8c9aa0
//
Packit 8c9aa0
// At least Microsoft Visual Studio 6 is known not to implement this test correctly.
Packit 8c9aa0
// It emits the following code to test equality:
Packit 8c9aa0
//  fcomp       qword ptr [nan]
Packit 8c9aa0
//  fnstsw      ax                        // copie fp (floating-point) status register to ax
Packit 8c9aa0
//  test        ah,40h                    // test bit 14 of ax (0x4000) => C3 of fp status register
Packit 8c9aa0
// According to the following documentation on the x86 floating point status register,
Packit 8c9aa0
// the C2 bit should be tested to test for NaN value. 
Packit 8c9aa0
// http://webster.cs.ucr.edu/AoA/Windows/HTML/RealArithmetic.html#1000117
Packit 8c9aa0
// In Microsoft Visual Studio 2003 & 2005, the test is implemented with:
Packit 8c9aa0
//  test        ah,44h         // Visual Studio 2005 test both C2 & C3...
Packit 8c9aa0
//
Packit 8c9aa0
// To work around this, a NaN is assumed to be detected if no strict ordering is found.
Packit 8c9aa0
inline bool floatingPointIsUnordered( double x )
Packit 8c9aa0
{
Packit 8c9aa0
   // x != x will detect a NaN on conformant platform
Packit 8c9aa0
   // (2.0 < x  &&  x < 1.0) will detect a NaN on non conformant platform:
Packit 8c9aa0
   // => no ordering can be found for x.
Packit 8c9aa0
   return  (x != x) ||  (2.0 < x  &&  x < 1.0);
Packit 8c9aa0
}
Packit 8c9aa0
Packit 8c9aa0
Packit 8c9aa0
/// \brief Tests if a floating-point is finite.
Packit 8c9aa0
/// @return \c true if x is neither a NaN, nor +inf, nor -inf, \c false otherwise.
Packit 8c9aa0
inline int floatingPointIsFinite( double x )
Packit 8c9aa0
{
Packit 8c9aa0
#if defined(CPPUNIT_HAVE_ISFINITE)
Packit 8c9aa0
   return isfinite( x );
Packit 8c9aa0
#elif defined(CPPUNIT_HAVE_FINITE)
Packit 8c9aa0
   return finite( x );
Packit 8c9aa0
#elif defined(CPPUNIT_HAVE__FINITE)
Packit 8c9aa0
   return _finite(x);
Packit 8c9aa0
#else
Packit 8c9aa0
   double testInf = x * 0.0;  // Produce 0.0 if x is finite, a NaN otherwise.
Packit 8c9aa0
   return testInf == 0.0  &&  !floatingPointIsUnordered(testInf);
Packit 8c9aa0
#endif
Packit 8c9aa0
}
Packit 8c9aa0
Packit 8c9aa0
CPPUNIT_NS_END
Packit 8c9aa0
Packit 8c9aa0
#endif // CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED