CppUnit project page | FAQ |
00001 #ifndef CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED 00002 #define CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED 00003 00004 #include <cppunit/Portability.h> 00005 #include <math.h> 00006 00007 #if defined(__sun) && !defined(CPPUNIT_HAVE_ISFINITE) && defined(CPPUNIT_HAVE_FINITE) 00008 #include <ieeefp.h> 00009 // <math.h> is still needed for usage of fabs in TestAssert.cpp 00010 #endif 00011 00012 CPPUNIT_NS_BEGIN 00013 00015 // According to IEEE-754 floating point standard, 00016 // (see e.g. page 8 of 00017 // http://www.cs.berkeley.edu/~wkahan/ieee754status/ieee754.ps) 00018 // all comparisons with NaN are false except "x != x", which is true. 00019 // 00020 // At least Microsoft Visual Studio 6 is known not to implement this test correctly. 00021 // It emits the following code to test equality: 00022 // fcomp qword ptr [nan] 00023 // fnstsw ax // copie fp (floating-point) status register to ax 00024 // test ah,40h // test bit 14 of ax (0x4000) => C3 of fp status register 00025 // According to the following documentation on the x86 floating point status register, 00026 // the C2 bit should be tested to test for NaN value. 00027 // http://webster.cs.ucr.edu/AoA/Windows/HTML/RealArithmetic.html#1000117 00028 // In Microsoft Visual Studio 2003 & 2005, the test is implemented with: 00029 // test ah,44h // Visual Studio 2005 test both C2 & C3... 00030 // 00031 // To work around this, a NaN is assumed to be detected if no strict ordering is found. 00032 inline bool floatingPointIsUnordered( double x ) 00033 { 00034 // x != x will detect a NaN on conformant platform 00035 // (2.0 < x && x < 1.0) will detect a NaN on non conformant platform: 00036 // => no ordering can be found for x. 00037 return (x != x) || (2.0 < x && x < 1.0); 00038 } 00039 00040 00043 inline int floatingPointIsFinite( double x ) 00044 { 00045 #if defined(CPPUNIT_HAVE_ISFINITE) 00046 return isfinite( x ); 00047 #elif defined(CPPUNIT_HAVE_FINITE) 00048 return finite( x ); 00049 #elif defined(CPPUNIT_HAVE__FINITE) 00050 return _finite(x); 00051 #else 00052 double testInf = x * 0.0; // Produce 0.0 if x is finite, a NaN otherwise. 00053 return testInf == 0.0 && !floatingPointIsUnordered(testInf); 00054 #endif 00055 } 00056 00057 CPPUNIT_NS_END 00058 00059 #endif // CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED
Send comments to: CppUnit Developers |