Catch division edge case of (/ fx-least -1).

Thanks for Jim Rees for reporting.
This commit is contained in:
Alex Shinn 2024-02-22 16:32:20 +09:00
parent 29dd1a3b81
commit 56ef426dfa
3 changed files with 13 additions and 0 deletions

View file

@ -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;

View file

@ -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))

3
vm.c
View file

@ -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 {