ref: 8342f9a1e9bfc9f6db3253c5d633c2c77ffd6680
parent: 6bc3fe5f11dde87433d417b30a8f669b22642092
author: Doug Currie <[email protected]>
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))