[Cppunit-devel] assertDoubleEquals, NaN & Microsoft Visual Studio 6
Brought to you by:
blep
|
From: CppUnit d. m. l. <cpp...@li...> - 2007-02-24 21:13:58
|
The detection of NaN in assertDoubleEquals failed on Microsoft Visual Studio 6. The implementation assumes that NaN != NaN (IEEE-754 says it should). The failure was caused by the way MSVC6 compares floating point number equality: fld qword ptr [nan] fcomp qword ptr [nan] fnstsw ax // copie fp (floating-point) status to register to ax test ah,40h // test bit 14 of ax (0x4000) => C3 of fp status register je $L18438+0B9h (00410be2) According to this doc: http://webster.cs.ucr.edu/AoA/Windows/HTML/RealArithmetic.html#1000117 C2 should be tested for "undefined" value (which I guess NaN fall into). NaN comparison works under visual studio 2005. The equality test is done as follow: fld qword ptr [ebp+10h] fcomp qword ptr [ebp+8] fnstsw ax test ah,44h // Visual Studio 2005 does test both C2 & C3... jp CppUnit::assertDoubleEquals+1B5h (4777A5h) This seems to confirm that MSVC6 code generator is bug (does not respect IEEE-754 standard in spite of what the doc claim). To work-around this, I added an explicit test for NaN value when testing non-finite value for equalities. Here is the function: // To work around this, a NaN is assumed to be detected if no strict ordering is found. inline bool floatingPointIsUnordered( double x ) { // x != x will detect a NaN on conformant platform // (2.0 < x && x < 1.0) will detect a NaN on non conformant platform: // => no ordering can be found for x. return (x != x) || (2.0 < x && x < 1.0); } I'm not an expert on floating-point manipulation & NaN. Does any one see anything wrong on the above implementation or the comments? I modified the defined implementation for isfinite() test to: /// \brief Tests if a floating-point is finite. /// @return \c true if x is neither a NaN, nor +inf, nor -inf, \c false otherwise. inline bool floatingPointIsFinite( double x ) { double testInf = x * 0.0; // Produce 0.0 if x is finite, a NaN otherwise. return testInf == 0.0 && !floatingPointIsUnordered(testInf); } Feedbacks are welcome, Baptiste. --- Baptiste Lepilleur <bl...@us...> CppUnit maintainer OpenTest and CppUnit 2 developer. |