From 833ad991dd9e4e3231cf2181cc78ca8429af3632 Mon Sep 17 00:00:00 2001 From: cutealien Date: Tue, 5 Jun 2012 11:46:37 +0000 Subject: [PATCH] - Add function equalsByUlp to test for spacing between floating point numbers. - Allow difference of 1 ULP in fast_atof tests (as that is still correct). Note that this only fixes part of the fast_atof test, the whole tests still fails on 64-bit because test_strtol still fails (that looks more like a real bug). git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4179 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 2 ++ include/fast_atof.h | 3 +-- include/irrMath.h | 30 ++++++++++++++++++++++++++++++ tests/fast_atof.cpp | 9 +++++++-- tests/tests-last-passed-at.txt | 2 +- tests/triangleSelector.cpp | 4 ++-- 6 files changed, 43 insertions(+), 7 deletions(-) diff --git a/changes.txt b/changes.txt index 2c0b57ce..666db7bb 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,7 @@ Changes in 1.8 (??.??.2011) + - new function equalsByUlp to test for spacing between floating point numbers. + - speedup for collada writing. - speedup for xml-writing. diff --git a/include/fast_atof.h b/include/fast_atof.h index 79e560d2..18d9b5b7 100644 --- a/include/fast_atof.h +++ b/include/fast_atof.h @@ -303,8 +303,7 @@ inline f32 strtof10(const char* in, const char** out = 0) */ inline const char* fast_atof_move(const char* in, f32& result) { - // Please run this regression test when making any modifications to this function: - // https://sourceforge.net/tracker/download.php?group_id=74339&atid=540676&file_id=298968&aid=1865300 + // Please run the regression test when making any modifications to this function. result = 0.f; if (!in) diff --git a/include/irrMath.h b/include/irrMath.h index 93aea625..2adf2e5a 100644 --- a/include/irrMath.h +++ b/include/irrMath.h @@ -188,6 +188,36 @@ namespace core { return (a + tolerance >= b) && (a - tolerance <= b); } + + //! We compare the difference in ULP's (spacing between floating-point numbers, aka ULP=1 means there exists no float between). + //\result true when numbers have a ULP <= maxUlpDiff AND have the same sign. + inline bool equalsByUlp(f32 a, f32 b, int maxUlpDiff) + { + // Based on the ideas from Bruce Dawson on + // http://www.altdevblogaday.com/2012/02/22/comparing-floating-point-numbers-2012-edition/ + // When floats are interpreted as integers the two nearest possible float numbers differ just + // by one integer number. Also works the other way round, an integer of 1 interpreted as float + // is for example the smallest possible float number. + int ia = *reinterpret_cast(&a); + int ib = *reinterpret_cast(&b); + + // Different signs, we could maybe get difference to 0, but so close to 0 using epsilons is better. + if ( (ia >> 31 != 0) != (ib >> 31 != 0) ) + { + // Check for equality to make sure +0==-0 + if (a == b) + return true; + return false; + } + + // Find the difference in ULPs. + int ulpsDiff = abs_(ia - ib); + if (ulpsDiff <= maxUlpDiff) + return true; + + return false; + } + #if 0 //! returns if a equals b, not using any rounding tolerance inline bool equals(const s32 a, const s32 b) diff --git a/tests/fast_atof.cpp b/tests/fast_atof.cpp index 7fc579ac..4d909ba7 100644 --- a/tests/fast_atof.cpp +++ b/tests/fast_atof.cpp @@ -90,7 +90,9 @@ static bool testCalculation_atof(const char * valueString) logTestString("\n String '%s'\n New fast %.40f\n Old fast %.40f\n atof %.40f\n", valueString, newFastValue, oldFastValue, atofValue); - bool accurate = fabs(newFastValue - atofValue) <= fabs(oldFastValue - atofValue); + const f32 diffNew = fabs(newFastValue - atofValue) ; + const f32 diffOld = fabs(newFastValue - atofValue) ; + bool accurate = diffNew <= diffOld || equalsByUlp(diffNew, diffOld, 1); if(!accurate) logTestString("*** ERROR - less accurate than old method ***\n\n"); @@ -275,5 +277,8 @@ bool test_strtol(void) bool fast_atof(void) { - return test_fast_atof() && test_strtol(); + bool ok = true; + ok &= test_fast_atof() ; + ok &= test_strtol(); + return ok; } diff --git a/tests/tests-last-passed-at.txt b/tests/tests-last-passed-at.txt index aeab21d5..f36a2943 100644 --- a/tests/tests-last-passed-at.txt +++ b/tests/tests-last-passed-at.txt @@ -1,4 +1,4 @@ Tests finished. 1 test of 1 passed. Compiled as DEBUG -Test suite pass at GMT Sun Jun 3 18:56:35 2012 +Test suite pass at GMT Sun Jun 3 20:56:51 2012 diff --git a/tests/triangleSelector.cpp b/tests/triangleSelector.cpp index 1d61b87e..2f926054 100644 --- a/tests/triangleSelector.cpp +++ b/tests/triangleSelector.cpp @@ -56,10 +56,10 @@ bool octree() if (q3levelmesh) { scene::ISceneNode* q3node = smgr->addOctreeSceneNode(q3levelmesh->getMesh(0)); - + q3node->setPosition(core::vector3df(-1350,-130,-1400)); - scene::ITriangleSelector * selector = + scene::ITriangleSelector * selector = smgr->createOctreeTriangleSelector(q3levelmesh->getMesh(0), q3node, 128); meta->addTriangleSelector(selector); selector->drop();