shithub: femtolisp

Download patch

ref: 72d1ee7522223f6a2085ec619b933db2e716416e
parent: c019b3bf2d42f3a70c682cc517a45c8a77f7964d
author: Jeff Bezanson <bezanson@post.harvard.edu>
date: Wed Mar 14 20:21:39 EDT 2012

fixing large int64 comparison bug

--- a/operators.c
+++ b/operators.c
@@ -206,9 +206,10 @@
         return 0;
 
     if (atag == T_UINT64) {
-        // this is safe because if a had been bigger than S64_MAX,
-        // we would already have concluded that it's bigger than b.
         if (btag == T_INT64) {
+            if (*(int64_t*)b >= 0) {
+                return (*(uint64_t*)a < (uint64_t)*(int64_t*)b);
+            }
             return ((int64_t)*(uint64_t*)a < *(int64_t*)b);
         }
         else if (btag == T_DOUBLE) {
@@ -218,6 +219,9 @@
     }
     else if (atag == T_INT64) {
         if (btag == T_UINT64) {
+            if (*(int64_t*)a >= 0) {
+                return ((uint64_t)*(int64_t*)a < *(uint64_t*)b);
+            }
             return (*(int64_t*)a < (int64_t)*(uint64_t*)b);
         }
         else if (btag == T_DOUBLE) {
@@ -225,20 +229,14 @@
             return (*(int64_t*)a < (int64_t)*(double*)b);
         }
     }
-    else if (btag == T_UINT64) {
-        if (atag == T_INT64) {
-            return ((int64_t)*(uint64_t*)b > *(int64_t*)a);
-        }
-        else if (atag == T_DOUBLE) {
+    if (btag == T_UINT64) {
+        if (atag == T_DOUBLE) {
             if (da != da) return 0;
             return (*(uint64_t*)b > (uint64_t)*(double*)a);
         }
     }
     else if (btag == T_INT64) {
-        if (atag == T_UINT64) {
-            return (*(int64_t*)b > (int64_t)*(uint64_t*)a);
-        }
-        else if (atag == T_DOUBLE) {
+        if (atag == T_DOUBLE) {
             if (da != da) return 0;
             return (*(int64_t*)b > (int64_t)*(double*)a);
         }
@@ -303,62 +301,3 @@
     }
     return 1;
 }
-
-#ifdef ENABLE_LLT_TEST
-void test_operators()
-{
-    int8_t i8, i8b;
-    uint8_t ui8, ui8b;
-    int16_t i16, i16b;
-    uint16_t ui16, ui16b;
-    int32_t i32, i32b;
-    uint32_t ui32, ui32b;
-    int64_t i64, i64b;
-    uint64_t ui64, ui64b;
-    float f, fb;
-    double d, db;
-
-    ui64 = U64_MAX;
-    ui64b = U64_MAX-1;
-    i64 = S64_MIN;
-    i64b = i64+1;
-    d = (double)ui64;
-    db = (double)i64b;
-
-    assert(cmp_lt(&i64, T_INT64, &ui64, T_UINT64));
-    assert(!cmp_lt(&ui64, T_UINT64, &i64, T_INT64));
-    assert(cmp_lt(&i64, T_INT64, &ui64b, T_UINT64));
-    assert(!cmp_lt(&ui64b, T_UINT64, &i64, T_INT64));
-    assert(cmp_lt(&i64, T_INT64, &i64b, T_INT64));
-    assert(!cmp_lt(&i64b, T_INT64, &i64, T_INT64));
-
-    // try to compare a double too big to fit in an int64 with an
-    // int64 requiring too much precision to fit in a double...
-    // this case fails but it's very difficult/expensive to support
-    //assert(cmp_lt(&ui64b, T_UINT64, &d, T_DOUBLE));
-
-    i64 = S64_MAX;
-    ui64 = S64_MAX-1;
-    assert(cmp_lt(&ui64, T_UINT64, &i64, T_INT64));
-    assert(!cmp_lt(&i64, T_INT64, &ui64, T_UINT64));
-    i64 = S64_MAX-1;
-    ui64 = S64_MAX;
-    assert(cmp_lt(&i64, T_INT64, &ui64, T_UINT64));
-    assert(!cmp_lt(&ui64, T_UINT64, &i64, T_INT64));
-
-    d = DBL_MAXINT;
-    i64 = DBL_MAXINT+100;
-    assert(cmp_lt(&d, T_DOUBLE, &i64, T_INT64));
-    assert(!cmp_lt(&i64, T_INT64, &d, T_DOUBLE));
-    i64 = DBL_MAXINT+10;
-    assert(cmp_lt(&d, T_DOUBLE, &i64, T_INT64));
-    assert(!cmp_lt(&i64, T_INT64, &d, T_DOUBLE));
-    i64 = DBL_MAXINT+1;
-    assert(cmp_lt(&d, T_DOUBLE, &i64, T_INT64));
-    assert(!cmp_lt(&i64, T_INT64, &d, T_DOUBLE));
-
-    assert(!cmp_eq(&d, T_DOUBLE, &i64, T_INT64, 0));
-    i64 = DBL_MAXINT;
-    assert(cmp_eq(&d, T_DOUBLE, &i64, T_INT64, 0));
-}
-#endif
--- a/tests/unittest.lsp
+++ b/tests/unittest.lsp
@@ -76,6 +76,8 @@
 
 (assert (equal? (string 'sym #byte(65) #wchar(945) "blah") "symA\u03B1blah"))
 
+(assert (> 9223372036854775808 9223372036854775807))
+
 ; NaNs
 (assert (equal? +nan.0 +nan.0))
 (assert (not (= +nan.0 +nan.0)))