From e8ba3f1c1b4a0c461367b7aacd8a9f6cda0cd028 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Mon, 11 Sep 2023 18:24:33 -0700 Subject: [PATCH] Issue #510 - Exact conversion of large doubles Allow `exact` to convert large double values to bignums. --- include/cyclone/runtime.h | 25 +++++++++++++++++++------ tests/base.scm | 2 ++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/include/cyclone/runtime.h b/include/cyclone/runtime.h index faab85db..a97414ec 100644 --- a/include/cyclone/runtime.h +++ b/include/cyclone/runtime.h @@ -517,6 +517,7 @@ int Cyc_have_mstreams(); } else if (type_of(z) == bignum_tag) { \ return_closcall1(data, cont, z); \ } else if (type_of(z) == complex_num_tag) { \ + return_closcall1(data, cont, z); \ } else { \ double d = ((double_type *)z)->value; \ if (isnan(d)) { \ @@ -525,15 +526,15 @@ int Cyc_have_mstreams(); Cyc_rt_raise2(data, "Expected number but received", z); \ } else if (d == -INFINITY) { \ Cyc_rt_raise2(data, "Expected number but received", z); \ + } else if (d > CYC_FIXNUM_MAX || d < CYC_FIXNUM_MIN){ \ + alloc_bignum(data, bn); \ + BIGNUM_CALL(mp_set_double(&bignum_value(bn), d)); \ + return_closcall1(data, cont, bn); \ } \ i = (int)OP(((double_type *)z)->value); \ } \ return_closcall1(data, cont, obj_int2obj(i)) -// TODO: truncate complex number components -// TODO: what if double is outside fixnum range?? -// need to convert to a bignum - /** * Directly compute exact */ @@ -546,13 +547,25 @@ int Cyc_have_mstreams(); i = (int)OP(((integer_type *)z)->value); \ } else if (type_of(z) == bignum_tag) { \ return z; \ + } else if (type_of(z) == complex_num_tag) { \ + return z; \ } else { \ + double d = ((double_type *)z)->value; \ + if (isnan(d)) { \ + Cyc_rt_raise2(data, "Expected number but received", z); \ + } else if (d == INFINITY) { \ + Cyc_rt_raise2(data, "Expected number but received", z); \ + } else if (d == -INFINITY) { \ + Cyc_rt_raise2(data, "Expected number but received", z); \ + } else if (d > CYC_FIXNUM_MAX || d < CYC_FIXNUM_MIN){ \ + alloc_bignum(data, bn); \ + BIGNUM_CALL(mp_set_double(&bignum_value(bn), d)); \ + return bn; \ + } \ i = (int)OP(((double_type *)z)->value); \ } \ return obj_int2obj(i); -// TODO: sync changes from above CPS macro - /** * Take Scheme object that is a number and return the number as a C type */ diff --git a/tests/base.scm b/tests/base.scm index 033bb705..e3e4f5fe 100644 --- a/tests/base.scm +++ b/tests/base.scm @@ -65,6 +65,8 @@ (test -1 (exact -1.0)) (test -1 (exact -1.1)) (test -1 (exact -1.1)) + (test #t (bignum? (exact 111111111111111111111111111.0))) + (test #t (bignum? (exact -111111111111111111111111111.0))) ;(test +inf.0 (exact +inf.0)) )