klisp

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

commit b205307761ad4928e6dca14f6c721c9ef6684d08
parent bc146bc5128a5fffaf4db62075832e958ac4c952
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Fri,  6 May 2011 19:05:34 -0300

Added underflow/overflow checking to real->inexact when strict-arithmetic dynamic variable is true.

Diffstat:
Msrc/kreal.c | 38++++++++++++++++++++++++++++++++++----
1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/src/kreal.c b/src/kreal.c @@ -93,20 +93,50 @@ double kbigrat_to_double(klisp_State *K, Bigrat *bigrat) if set */ TValue kexact_to_inexact(klisp_State *K, TValue n) { + bool strictp = bvalue(kcurr_strict_arithp(K)); + switch(ttype(n)) { case K_TFIXINT: + /* NOTE: can't over or underflow, and can't give NaN */ return d2tv((double) ivalue(n)); case K_TBIGINT: { Bigint *bigint = tv2bigint(n); double d = kbigint_to_double(bigint); - /* d may be inf, ktag_double will handle it */ - /* MAYBE should throw an exception if strict is on */ - return ktag_double(d); + if (strictp && (d == 0.0 || isinf(d) || isnan(d))) { + /* NOTE: bigints can't be zero */ + char *msg; + if (isnan(d)) + msg = "unexpected error"; + else if (isinf(d)) + msg = "overflow"; + else + msg = "undeflow"; + klispE_throw_simple_with_irritants(K, msg, 1, n); + return KUNDEF; + } else { + /* d may be inf, ktag_double will handle it */ + return ktag_double(d); + } } case K_TBIGRAT: { Bigrat *bigrat = tv2bigrat(n); double d = kbigrat_to_double(K, bigrat); - return ktag_double(d); + /* REFACTOR: this code is the same for bigints... */ + if (strictp && (d == 0.0 || isinf(d) || isnan(d))) { + /* NOTE: bigrats can't be zero */ + char *msg; + if (isnan(d)) + msg = "unexpected error"; + else if (isinf(d)) + msg = "overflow"; + else + msg = "undeflow"; + klispE_throw_simple_with_irritants(K, msg, 1, n); + return KUNDEF; + } else { + /* d may be inf, ktag_double will handle it */ + return ktag_double(d); + } } case K_TEINF: return tv_equal(n, KEPINF)? KIPINF : KIMINF;