diff options
| -rw-r--r-- | src/stdlib/reals.c | 46 | ||||
| -rw-r--r-- | test/reals.tm | 2 |
2 files changed, 15 insertions, 33 deletions
diff --git a/src/stdlib/reals.c b/src/stdlib/reals.c index 2ee6da40..6a6d7dc7 100644 --- a/src/stdlib/reals.c +++ b/src/stdlib/reals.c @@ -129,7 +129,7 @@ bool Real$get_rational(Real_t x, int64_t *num, int64_t *den) { // Promote double to exact type if needed static Real_t promote_double(double d) { - if (isfinite(d) && d == floor(d) && fabs(d) < (1LL << 53)) { + if (!isfinite(d)) { return make_double(d); } rational_t *r = GC_MALLOC(sizeof(rational_t)); @@ -213,21 +213,10 @@ Real_t Real$plus(Real_t a, Real_t b) { if (!fetestexcept(FE_INEXACT) && isfinite(result)) { return make_double(result); } - a = promote_double(a.d); - b = promote_double(b.d); } - // Handle mixed rational/double cases by promoting double to rational - if (Real$is_boxed(a) && Real$tag(a) == REAL_TAG_RATIONAL && !Real$is_boxed(b)) { - if (isfinite(b.d)) { - b = promote_double(b.d); - } - } - if (!Real$is_boxed(a) && Real$is_boxed(b) && Real$tag(b) == REAL_TAG_RATIONAL) { - if (isfinite(a.d)) { - a = promote_double(a.d); - } - } + if (!Real$is_boxed(a)) a = promote_double(a.d); + if (!Real$is_boxed(b)) b = promote_double(b.d); // Handle exact rational arithmetic if (Real$tag(a) == REAL_TAG_RATIONAL && Real$tag(b) == REAL_TAG_RATIONAL) { @@ -255,10 +244,11 @@ Real_t Real$minus(Real_t a, Real_t b) { if (!fetestexcept(FE_INEXACT) && isfinite(result)) { return make_double(result); } - a = promote_double(a.d); - b = promote_double(b.d); } + if (!Real$is_boxed(a)) a = promote_double(a.d); + if (!Real$is_boxed(b)) b = promote_double(b.d); + if (Real$tag(a) == REAL_TAG_RATIONAL && Real$tag(b) == REAL_TAG_RATIONAL) { rational_t *ra = get_ptr(a); rational_t *rb = get_ptr(b); @@ -283,21 +273,10 @@ Real_t Real$times(Real_t a, Real_t b) { if (!fetestexcept(FE_INEXACT) && isfinite(result)) { return make_double(result); } - a = promote_double(a.d); - b = promote_double(b.d); } - // Handle mixed rational/double cases by promoting double to rational - if (Real$is_boxed(a) && Real$tag(a) == REAL_TAG_RATIONAL && !Real$is_boxed(b)) { - if (isfinite(b.d)) { - b = promote_double(b.d); - } - } - if (!Real$is_boxed(a) && Real$is_boxed(b) && Real$tag(b) == REAL_TAG_RATIONAL) { - if (isfinite(a.d)) { - a = promote_double(a.d); - } - } + if (!Real$is_boxed(a)) a = promote_double(a.d); + if (!Real$is_boxed(b)) b = promote_double(b.d); if (Real$tag(a) == REAL_TAG_RATIONAL && Real$tag(b) == REAL_TAG_RATIONAL) { rational_t *ra = get_ptr(a); @@ -339,10 +318,11 @@ Real_t Real$divided_by(Real_t a, Real_t b) { if (!fetestexcept(FE_INEXACT) && isfinite(result)) { return make_double(result); } - a = promote_double(a.d); - b = promote_double(b.d); } + if (!Real$is_boxed(a)) a = promote_double(a.d); + if (!Real$is_boxed(b)) b = promote_double(b.d); + if (Real$tag(a) == REAL_TAG_RATIONAL && Real$tag(b) == REAL_TAG_RATIONAL) { rational_t *ra = get_ptr(a); rational_t *rb = get_ptr(b); @@ -844,7 +824,9 @@ PUREFUNC bool Real$is_none(const void *vn, const TypeInfo_t *type) { public bool Real$equal_values(Real_t a, Real_t b) { if (!Real$is_boxed(a) && !Real$is_boxed(b)) return a.d == b.d; - if (Real$is_boxed(a) != Real$is_boxed(b)) return 0; + + if (!Real$is_boxed(a)) a = promote_double(a.d); + if (!Real$is_boxed(b)) b = promote_double(b.d); if (Real$tag(a) == REAL_TAG_RATIONAL && Real$tag(b) == REAL_TAG_RATIONAL) { rational_t *ra = get_ptr(a); diff --git a/test/reals.tm b/test/reals.tm index afb2f5f0..46ff6867 100644 --- a/test/reals.tm +++ b/test/reals.tm @@ -69,7 +69,7 @@ func main() # Modulo assert 7. mod 3. == 1. assert -7. mod 3. == 2. # Euclidean division - assert 7. mod -3. == -2. + assert 7. mod -3. == 1. assert 2.5 mod 1.0 == 0.5 # Mod1 |
