diff --git a/c/types.c b/c/types.c index d99415c..0e044c8 100644 --- a/c/types.c +++ b/c/types.c @@ -419,18 +419,20 @@ Value num_mul(Value a, Value b) { } Value num_div(Value a, Value b) { - /* Integer / integer that divides cleanly stays integer (matches Python / - * Scheme semantics for `/` between exacts when the quotient is exact). - * For bignum case we treat as exact division (truncating to integer when - * quotient is exact, else fall back to double for now — secp256k1 ops - * never use fractional bignum). */ + /* Integer / integer that divides cleanly stays integer; otherwise we + * promote to an exact rational (matches Python lumbda and R7RS: + * `/` between exacts produces an exact result). The previous code + * fell back to double for non-divisible int/int — that broke parity + * with the Python tier on (/ 67 7), (/ 1 3), etc. */ if (IS_INTEGER(a) && IS_INTEGER(b)) { if (big_is_zero(b)) lisp_error("division by zero"); Value q = big_quotient(a, b); Value r = big_remainder(a, b); if (big_is_zero(r)) return q; - /* Inexact fallback. */ - return make_double(as_number_double(a) / as_number_double(b)); + int64_t an, ad, bn, bd; + to_rational(a, &an, &ad); + to_rational(b, &bn, &bd); + return rational_normalize(an * bd, ad * bn); } if (is_exact(a) && is_exact(b)) { int64_t an, ad, bn, bd; diff --git a/www/playground/c/lumbda-c.wasm b/www/playground/c/lumbda-c.wasm index e3aa277..c0835e8 100755 Binary files a/www/playground/c/lumbda-c.wasm and b/www/playground/c/lumbda-c.wasm differ diff --git a/www/repl/c/lumbda-c.wasm b/www/repl/c/lumbda-c.wasm index e3aa277..c0835e8 100755 Binary files a/www/repl/c/lumbda-c.wasm and b/www/repl/c/lumbda-c.wasm differ