~ 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