klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

commit 9059985f07cb71c058ce8ae85de8540b3f25c129
parent f02a11015371ea0dd91da1df3cadc23396767375
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Thu, 19 May 2011 03:53:39 -0300

Added inexact support to simplest-rational & rationalize.

Diffstat:
Msrc/kgnumbers.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 66 insertions(+), 4 deletions(-)

diff --git a/src/kgnumbers.c b/src/kgnumbers.c @@ -762,10 +762,13 @@ TValue knum_real_to_integer(klisp_State *K, TValue n, kround_mode mode) TValue knum_simplest_rational(klisp_State *K, TValue n1, TValue n2) { + /* this is not so nice but simplifies some cases */ + /* XXX: this may cause overflows! */ + kensure_same_exactness(K, n1, n2); + /* first check that case that n1 > n2 */ if (knum_gtp(K, n1, n2)) { - klispE_throw_simple(K, "result with no primary value " - "(n1 > n2)"); + klispE_throw_simple(K, "x0 doesn't exists (n1 > n2)"); return KINERT; } @@ -779,10 +782,25 @@ TValue knum_simplest_rational(klisp_State *K, TValue n1, TValue n2) kensure_bigrat(n2); return kbigrat_simplest_rational(K, n1, n2); } + case K_TDOUBLE: { + /* both are double, for now just convert to rational */ + krooted_vars_push(K, &n1); + krooted_vars_push(K, &n2); + n1 = kinexact_to_exact(K, n1); + n2 = kinexact_to_exact(K, n2); + TValue res = knum_simplest_rational(K, n1, n2); + krooted_tvs_push(K, res); + res = kexact_to_inexact(K, res); + krooted_tvs_pop(K); + krooted_vars_pop(K); + krooted_vars_pop(K); + return res; + } case K_TEINF: /* we know that n1 <= n2 */ if (tv_equal(n1, n2)) { - klispE_throw_simple(K, "result with no primary value"); + klispE_throw_simple(K, "x0 doesn't exists (n1 == n2 & " + "irrational)"); return KINERT; } else if (knegativep(K, n1) && kpositivep(K, n2)) { return i2tv(0); @@ -797,6 +815,24 @@ TValue knum_simplest_rational(klisp_State *K, TValue n1, TValue n2) /* ASK John: is this behaviour for infinities ok? */ return knum_real_to_integer(K, n1, K_CEILING); } + case K_TIINF: + /* we know that n1 <= n2 */ + if (tv_equal(n1, n2)) { + klispE_throw_simple(K, "result with no primary value"); + return KINERT; + } else if (knegativep(K, n1) && kpositivep(K, n2)) { + return d2tv(0.0); + } else if (knegativep(K, n1)) { + /* n1 -inf, n2 finite negative */ + /* ASK John: is this behaviour for infinities ok? */ + /* Also in the report example both 1/3 & 1/2 are simpler than + 2/5... */ + return knum_real_to_integer(K, n2, K_FLOOR); + } else { + /* n1 finite positive, n2 +inf */ + /* ASK John: is this behaviour for infinities ok? */ + return knum_real_to_integer(K, n1, K_CEILING); + } default: klispE_throw_simple(K, "unsupported type"); return KINERT; @@ -805,6 +841,10 @@ TValue knum_simplest_rational(klisp_State *K, TValue n1, TValue n2) TValue knum_rationalize(klisp_State *K, TValue n1, TValue n2) { + /* this is not so nice but simplifies some cases */ + /* XXX: this may cause overflows! */ + kensure_same_exactness(K, n1, n2); + switch(max_ttype(n1, n2)) { case K_TFIXINT: case K_TBIGINT: /* for now do all with bigrat */ @@ -814,12 +854,34 @@ TValue knum_rationalize(klisp_State *K, TValue n1, TValue n2) kensure_bigrat(n2); return kbigrat_rationalize(K, n1, n2); } + case K_TDOUBLE: { + /* both are double, for now just convert to rational */ + krooted_vars_push(K, &n1); + krooted_vars_push(K, &n2); + n1 = kinexact_to_exact(K, n1); + n2 = kinexact_to_exact(K, n2); + TValue res = knum_rationalize(K, n1, n2); + krooted_tvs_push(K, res); + res = kexact_to_inexact(K, res); + krooted_tvs_pop(K); + krooted_vars_pop(K); + krooted_vars_pop(K); + return res; + } case K_TEINF: if (kfinitep(n1) || !kfinitep(n2)) { return i2tv(0); } else { /* infinite n1, finite n2 */ /* ASK John: is this behaviour for infinities ok? */ - klispE_throw_simple(K, "result with no primary value"); + klispE_throw_simple(K, "x0 doesn't exists"); + return KINERT; + } + case K_TIINF: + if (kfinitep(n1) || !kfinitep(n2)) { + return d2tv(0.0); + } else { /* infinite n1, finite n2 */ + /* ASK John: is this behaviour for infinities ok? */ + klispE_throw_simple(K, "x0 doesn't exists"); return KINERT; } default: