From 749d4b6a0ceb4855b55bfbdf9e5f23802a4ca6b7 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Sun, 7 Jan 2024 19:29:20 -0800 Subject: [PATCH] Issue #519 - Properly handle doubles in remainder --- runtime.c | 24 ++++++++++++++++++------ tests/base.scm | 8 +++----- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/runtime.c b/runtime.c index 195cac19..fa16c719 100644 --- a/runtime.c +++ b/runtime.c @@ -4629,6 +4629,7 @@ void Cyc_bignum_remainder(void *data, object cont, object num1, object num2, obj void Cyc_remainder(void *data, object cont, object num1, object num2) { int i = 0, j = 0; + double ii = 0, jj = 0; object result; if (obj_is_int(num1)) { if (obj_is_int(num2)){ @@ -4641,8 +4642,9 @@ void Cyc_remainder(void *data, object cont, object num1, object num2) Cyc_bignum_remainder(data, cont, bn, num2, bn); } else if (is_object_type(num2) && type_of(num2) == double_tag){ - i = obj_obj2int(num1); - j = ((double_type *)num2)->value; + ii = obj_obj2int(num1); + jj = ((double_type *)num2)->value; + goto handledouble; } else { goto typeerror; @@ -4658,6 +4660,7 @@ void Cyc_remainder(void *data, object cont, object num1, object num2) Cyc_bignum_remainder(data, cont, num1, num2, rem); } else if (is_object_type(num2) && type_of(num2) == double_tag){ + // TODO: correct to convert bignum to double here j = ((double_type *)num2)->value; alloc_bignum(data, bn); Cyc_int2bignum(obj_obj2int(j), &(bn->bn)); @@ -4668,18 +4671,21 @@ void Cyc_remainder(void *data, object cont, object num1, object num2) } } else if (is_object_type(num1) && type_of(num1) == double_tag){ if (obj_is_int(num2)){ - i = ((double_type *)num1)->value; - j = obj_obj2int(num2); + ii = ((double_type *)num1)->value; + jj = obj_obj2int(num2); + goto handledouble; } else if (is_object_type(num2) && type_of(num2) == bignum_tag){ + // TODO: convert bignum to double here i = ((double_type *)num1)->value; alloc_bignum(data, bn); Cyc_int2bignum(obj_obj2int(i), &(bn->bn)); Cyc_bignum_remainder(data, cont, bn, num2, bn); } else if (is_object_type(num2) && type_of(num2) == double_tag){ - i = ((double_type *)num1)->value; - j = ((double_type *)num2)->value; + ii = ((double_type *)num1)->value; + jj = ((double_type *)num2)->value; + goto handledouble; } else { goto typeerror; @@ -4690,6 +4696,12 @@ void Cyc_remainder(void *data, object cont, object num1, object num2) if (j == 0) { Cyc_rt_raise_msg(data, "Divide by zero"); } result = obj_int2obj(i % j); return_closcall1(data, cont, result); +handledouble: +{ + if (jj == 0) { Cyc_rt_raise_msg(data, "Divide by zero"); } + make_double(dresult, fmod(ii, jj)); + return_closcall1(data, cont, &dresult); +} typeerror: { make_string(s, "Bad argument type"); diff --git a/tests/base.scm b/tests/base.scm index 48aa601a..3fea3896 100644 --- a/tests/base.scm +++ b/tests/base.scm @@ -75,8 +75,7 @@ (test (values -2 -1) (truncate/ -5 2)) (test (values -2 1) (truncate/ 5 -2)) (test (values 2 -1) (truncate/ -5 -2)) -; TODO: -; (test (values 2.0 -1.0) (truncate/ -5.0 -2)) + (test (values 2.0 -1.0) (truncate/ -5.0 -2)) (test 4 (gcd 32 -36)) (test 0 (gcd)) @@ -95,9 +94,8 @@ (test 4.0 (round 7/2)) ;; Rationals not supported, so result is inexact (test 7 (round 7)) - ; TODO: - ;(test 3 (numerator (/ 6 4))) - ;(test 2 (denominator (/ 6 4))) + (test 3.0 (numerator (/ 6 4))) ;; Inexact because we don't support rationals yet + (test 2.0 (denominator (/ 6 4))) ;; Inexact because we don't support rationals yet (test 2.0 (denominator (inexact (/ 6 4)))) )