~ chicken-core (chicken-5) 69cf7a985c6bdc0c2c8c154fea3dccb08e7bb4a1
commit 69cf7a985c6bdc0c2c8c154fea3dccb08e7bb4a1 Author: Peter Bex <peter@more-magic.net> AuthorDate: Wed May 22 13:58:11 2024 +0200 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Wed May 22 17:01:17 2024 +0200 Call integer_divrem straight from the modulo operations These would call C_s_a_i_remainder initially, which performs many of the same checks that we've just already done before actually calling integer_divrem. It also allocates more memory on the stack which is not necessary. In the case of the generic operator, doing so requires duplicating the code which converts floating-point integers to exact integers and back again. In the case of the integer-specific operator, there's no point in calling the *generic* remainder function in the first place! Signed-off-by: felix <felix@call-with-current-continuation.org> diff --git a/runtime.c b/runtime.c index 5116ed37..29dbcb00 100644 --- a/runtime.c +++ b/runtime.c @@ -9243,7 +9243,8 @@ C_s_a_u_i_integer_remainder(C_word **ptr, C_word n, C_word x, C_word y) C_regparm C_word C_fcall C_s_a_i_modulo(C_word **ptr, C_word n, C_word x, C_word y) { - C_word ab[C_SIZEOF_FIX_BIGNUM], *a = ab, r; + C_word ab[C_SIZEOF_FIX_BIGNUM], *a = ab, r, + nx = C_SCHEME_FALSE, ny = C_SCHEME_FALSE; if (!C_truep(C_i_integerp(x))) barf(C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR, "modulo", x); @@ -9251,13 +9252,41 @@ C_s_a_i_modulo(C_word **ptr, C_word n, C_word x, C_word y) barf(C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR, "modulo", y); if (C_truep(C_i_zerop(y))) C_div_by_zero_error("modulo"); - r = C_s_a_i_remainder(&a, 2, x, y); - if (C_i_positivep(y) != C_i_positivep(r) && !C_truep(C_i_zerop(r))) { + if (C_truep(C_i_flonump(x))) { + if C_truep(C_i_flonump(y)) { + double dx = C_flonum_magnitude(x), dy = C_flonum_magnitude(y), tmp; + + C_modf(dx / dy, &tmp); + tmp = dx - tmp * dy; + if ((dx > 0.0) != (dy > 0.0) && tmp != 0.0) { + return C_flonum(ptr, tmp + dy); + } else { + return C_flonum(ptr, tmp); + } + } + x = nx = C_s_a_u_i_flo_to_int(&a, 1, x); + } + if (C_truep(C_i_flonump(y))) { + y = ny = C_s_a_u_i_flo_to_int(&a, 1, y); + } + + integer_divrem(&a, x, y, NULL, &r); + if (C_i_positivep(y) != C_i_positivep(r) && r != C_fix(0)) { C_word m = C_s_a_i_plus(ptr, 2, r, y); m = move_buffer_object(ptr, ab, m); clear_buffer_object(ab, r); r = m; } + + if (C_truep(nx) || C_truep(ny)) { + C_word newr = C_a_i_exact_to_inexact(ptr, 1, r); + clear_buffer_object(ab, r); + r = newr; + + clear_buffer_object(ab, nx); + clear_buffer_object(ab, ny); + } + return move_buffer_object(ptr, ab, r); } @@ -9267,7 +9296,7 @@ C_s_a_u_i_integer_modulo(C_word **ptr, C_word n, C_word x, C_word y) C_word ab[C_SIZEOF_FIX_BIGNUM], *a = ab, r; if (y == C_fix(0)) C_div_by_zero_error("modulo"); - r = C_s_a_i_remainder(&a, 2, x, y); + integer_divrem(&a, x, y, NULL, &r); if (C_i_positivep(y) != C_i_positivep(r) && r != C_fix(0)) { C_word m = C_s_a_u_i_integer_plus(ptr, 2, r, y); m = move_buffer_object(ptr, ab, m);Trap