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