FloatingPoint.h 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. #ifndef CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED
  2. #define CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED
  3. #include <cppunit/Portability.h>
  4. #include <math.h>
  5. CPPUNIT_NS_BEGIN
  6. /// \brief Tests if a floating-point is a NaN.
  7. // According to IEEE-754 floating point standard,
  8. // (see e.g. page 8 of
  9. // http://www.cs.berkeley.edu/~wkahan/ieee754status/ieee754.ps)
  10. // all comparisons with NaN are false except "x != x", which is true.
  11. //
  12. // At least Microsoft Visual Studio 6 is known not to implement this test correctly.
  13. // It emits the following code to test equality:
  14. // fcomp qword ptr [nan]
  15. // fnstsw ax // copie fp (floating-point) status register to ax
  16. // test ah,40h // test bit 14 of ax (0x4000) => C3 of fp status register
  17. // According to the following documentation on the x86 floating point status register,
  18. // the C2 bit should be tested to test for NaN value.
  19. // http://webster.cs.ucr.edu/AoA/Windows/HTML/RealArithmetic.html#1000117
  20. // In Microsoft Visual Studio 2003 & 2005, the test is implemented with:
  21. // test ah,44h // Visual Studio 2005 test both C2 & C3...
  22. //
  23. // To work around this, a NaN is assumed to be detected if no strict ordering is found.
  24. inline bool floatingPointIsUnordered( double x )
  25. {
  26. // x != x will detect a NaN on conformant platform
  27. // (2.0 < x && x < 1.0) will detect a NaN on non conformant platform:
  28. // => no ordering can be found for x.
  29. return (x != x) || (2.0 < x && x < 1.0);
  30. }
  31. /// \brief Tests if a floating-point is finite.
  32. /// @return \c true if x is neither a NaN, nor +inf, nor -inf, \c false otherwise.
  33. inline int floatingPointIsFinite( double x )
  34. {
  35. #if defined(CPPUNIT_HAVE_ISFINITE)
  36. return isfinite( x );
  37. #elif defined(CPPUNIT_HAVE_FINITE)
  38. return finite( x );
  39. #elif defined(CPPUNIT_HAVE__FINITE)
  40. return _finite(x);
  41. #else
  42. double testInf = x * 0.0; // Produce 0.0 if x is finite, a NaN otherwise.
  43. return testInf == 0.0 && !floatingPointIsUnordered(testInf);
  44. #endif
  45. }
  46. CPPUNIT_NS_END
  47. #endif // CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED