comparing Vector(-2, 0, 0) and Vector(2, 0, 0) was returning true, this bug is years...
authorCampbell Barton <ideasman42@gmail.com>
Sun, 28 Feb 2010 19:27:06 +0000 (19:27 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 28 Feb 2010 19:27:06 +0000 (19:27 +0000)
use float comparison from the "Ever Faster Float Comparisons" paper, tested with random values as well as random values converted to ints (where this existing code would fail).

source/blender/python/generic/Mathutils.c
source/blender/python/generic/vector.c

index 8ad388ac54016d434cf0d58f9b180a66a692f201..fc21c26dd748b31586165f0602ea674edb484b8e 100644 (file)
@@ -557,25 +557,24 @@ static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
 
 /* Utility functions */
 
-/*---------------------- EXPP_FloatsAreEqual -------------------------
-  Floating point comparisons 
-  floatStep = number of representable floats allowable in between
-   float A and float B to be considered equal. */
-int EXPP_FloatsAreEqual(float A, float B, int floatSteps)
-{
-       int a, b, delta;
-    assert(floatSteps > 0 && floatSteps < (4 * 1024 * 1024));
-    a = *(int*)&A;
-    if (a < 0) 
-               a = 0x80000000 - a;
-    b = *(int*)&B;
-    if (b < 0) 
-               b = 0x80000000 - b;
-    delta = abs(a - b);
-    if (delta <= floatSteps)   
-               return 1;
-    return 0;
+// LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon
+#define SIGNMASK(i) (-(int)(((unsigned int)(i))>>31))
+
+int EXPP_FloatsAreEqual(float af, float bf, int maxDiff)
+{      // solid, fast routine across all platforms
+       // with constant time behavior
+       int ai = *(int *)(&af);
+       int bi = *(int *)(&bf);
+       int test = SIGNMASK(ai^bi);
+       int diff, v1, v2;
+
+       assert((0 == test) || (0xFFFFFFFF == test));
+       diff = (ai ^ (test & 0x7fffffff)) - bi;
+       v1 = maxDiff + diff;
+       v2 = maxDiff - diff;
+       return (v1|v2) >= 0;
 }
+
 /*---------------------- EXPP_VectorsAreEqual -------------------------
   Builds on EXPP_FloatsAreEqual to test vectors */
 int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps)
index 1e44ddafd37a876761a310d236672b76a0a11aa8..e320f87e9b911a15c1c22e932d7aa1568c77da5f 100644 (file)
@@ -1252,12 +1252,7 @@ static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa
                        result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
                        break;
                case Py_NE:
-                       result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
-                       if (result == 0){
-                               result = 1;
-                       }else{
-                               result = 0;
-                       }
+                       result = !EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
                        break;
                case Py_GT:
                        lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);