summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Shinn <alexshinn@gmail.com>2024-02-22 16:32:20 +0900
committerAlex Shinn <alexshinn@gmail.com>2024-02-22 16:32:20 +0900
commit56ef426dfa8d0a19dc2f76d52f432b21af1c6286 (patch)
tree099155b5170192a3e97544276f3162ffc58ece26
parent29dd1a3b81e297033f687cbbf2b51319856647f4 (diff)
Catch division edge case of (/ fx-least -1).
Thanks for Jim Rees for reporting.
-rw-r--r--bignum.c3
-rw-r--r--tests/r7rs-tests.scm7
-rw-r--r--vm.c3
3 files changed, 13 insertions, 0 deletions
diff --git a/bignum.c b/bignum.c
index 48a71b84..f721d2d0 100644
--- a/bignum.c
+++ b/bignum.c
@@ -1762,6 +1762,9 @@ sexp sexp_quotient (sexp ctx, sexp a, sexp b) {
break;
case SEXP_NUM_FIX_FIX:
r = sexp_fx_div(a, b);
+ if ((sexp_sint_t)a < 0 && (sexp_sint_t)b < 0 && (sexp_sint_t)r < 0) {
+ r = sexp_quotient(ctx, tmp=sexp_fixnum_to_bignum(ctx, a), b);
+ }
break;
case SEXP_NUM_FIX_BIG:
r = SEXP_ZERO;
diff --git a/tests/r7rs-tests.scm b/tests/r7rs-tests.scm
index 32f74576..6596074d 100644
--- a/tests/r7rs-tests.scm
+++ b/tests/r7rs-tests.scm
@@ -904,6 +904,13 @@
(test 3/20 (/ 3 4 5))
(test 1/3 (/ 3))
+(test 1073741824 (/ -1073741824 -1))
+(test 1073741824 (quotient -1073741824 -1))
+(test 0 (remainder -1073741824 -1))
+(test 4611686018427387904 (/ -4611686018427387904 -1))
+(test 4611686018427387904 (quotient -4611686018427387904 -1))
+(test 0 (remainder -4611686018427387904 -1))
+
(test 7 (abs -7))
(test 7 (abs 7))
diff --git a/vm.c b/vm.c
index bf51af22..e26f4ec5 100644
--- a/vm.c
+++ b/vm.c
@@ -1891,6 +1891,9 @@ sexp sexp_apply (sexp ctx, sexp proc, sexp args) {
if (tmp2 == SEXP_ZERO)
sexp_raise("divide by zero", SEXP_NULL);
_ARG1 = sexp_fx_div(tmp1, tmp2);
+ if ((sexp_sint_t)tmp1 < 0 && (sexp_sint_t)tmp2 < 0 && (sexp_sint_t)_ARG1 < 0) {
+ _ARG1 = sexp_quotient(ctx, tmp1=sexp_fixnum_to_bignum(ctx, tmp1), tmp2);
+ }
}
#if SEXP_USE_BIGNUMS
else {