shithub: femtolisp

Download patch

ref: 8342f9a1e9bfc9f6db3253c5d633c2c77ffd6680
parent: 6bc3fe5f11dde87433d417b30a8f669b22642092
author: Doug Currie <github.9.eeeeeee@spamgourmet.com>
date: Tue Nov 15 12:49:18 EST 2016

fix issue #33 Negating most-negative-fixnum doesn't. (#35)

* fix issue #33 Negating most-negative-fixnum doesn't.

* Add unit test for issue #33 Negating most-negative-fixnum doesn't.

--- a/cvalues.c
+++ b/cvalues.c
@@ -1115,7 +1115,11 @@
 static value_t fl_neg(value_t n)
 {
     if (isfixnum(n)) {
-        return fixnum(-numval(n));
+        fixnum_t s = fixnum(-numval(n));
+        if (__unlikely(s == n))
+            return mk_long(-numval(n)); // negate overflows
+        else
+            return s;
     }
     else if (iscprim(n)) {
         cprim_t *cp = (cprim_t*)ptr(n);
--- a/flisp.c
+++ b/flisp.c
@@ -1396,8 +1396,13 @@
             NEXT_OP;
         OP(OP_NEG)
         do_neg:
-            if (isfixnum(Stack[SP-1]))
-                Stack[SP-1] = fixnum(-numval(Stack[SP-1]));
+            if (isfixnum(Stack[SP-1])) {
+                s = fixnum(-numval(Stack[SP-1]));
+                if (__unlikely(s == Stack[SP-1]))
+                  Stack[SP-1] = mk_long(-numval(Stack[SP-1])); // negate overflows
+                else
+                  Stack[SP-1] = s;
+            }
             else
                 Stack[SP-1] = fl_neg(Stack[SP-1]);
             NEXT_OP;
--- a/tests/unittest.lsp
+++ b/tests/unittest.lsp
@@ -65,6 +65,9 @@
 (assert (> (- #int32(0x80000000)) 0))
 (assert (< (- #uint64(0x8000000000000000)) 0))
 (assert (> (- #int64(0x8000000000000000)) 0))
+; fixnum versions
+(assert (= (- -536870912) 536870912))
+(assert (= (- -2305843009213693952) 2305843009213693952))
 
 (assert (not (equal? #int64(0x8000000000000000) #uint64(0x8000000000000000))))
 (assert (equal? (+ #int64(0x4000000000000000) #int64(0x4000000000000000))