diff --git a/bignum.c b/bignum.c index 79a86c89..8c5d298d 100644 --- a/bignum.c +++ b/bignum.c @@ -1528,7 +1528,16 @@ sexp sexp_compare (sexp ctx, sexp a, sexp b) { r = sexp_make_fixnum(f < g ? -1 : f == g ? 0 : 1); break; case SEXP_NUM_FLO_BIG: - a = tmp = sexp_double_to_bignum(ctx, sexp_flonum_value(a)); + f = sexp_flonum_value(a); + if (isinf(f)) { + r = f > 0 ? SEXP_ONE : SEXP_NEG_ONE; + break; + } else if (isnan(f)) { + r = sexp_xtype_exception(ctx, NULL, "can't compare NaN", a); + break; + } else { + a = tmp = sexp_double_to_bignum(ctx, f); + } /* ... FALLTHROUGH ... */ case SEXP_NUM_BIG_BIG: r = sexp_make_fixnum(sexp_bignum_compare(a, b)); @@ -1536,8 +1545,14 @@ sexp sexp_compare (sexp ctx, sexp a, sexp b) { #if SEXP_USE_RATIOS case SEXP_NUM_FLO_RAT: f = sexp_flonum_value(a); - g = sexp_ratio_to_double(b); - r = sexp_make_fixnum(f < g ? -1 : f == g ? 0 : 1); + if (isinf(f)) { + r = f > 0 ? SEXP_ONE : SEXP_NEG_ONE; + } else if (isnan(f)) { + r = sexp_xtype_exception(ctx, NULL, "can't compare NaN", a); + } else { + g = sexp_ratio_to_double(b); + r = sexp_make_fixnum(f < g ? -1 : f == g ? 0 : 1); + } break; case SEXP_NUM_FIX_RAT: case SEXP_NUM_BIG_RAT: diff --git a/vm.c b/vm.c index 3cad0810..82804225 100644 --- a/vm.c +++ b/vm.c @@ -1750,8 +1750,14 @@ sexp sexp_apply (sexp ctx, sexp proc, sexp args) { _ARG1 = sexp_make_boolean(i); } else { _ARG1 = sexp_compare(ctx, tmp1, tmp2); - sexp_check_exception(); - _ARG1 = sexp_make_boolean(sexp_unbox_fixnum(_ARG1) < 0); + if (sexp_exceptionp(_ARG1)) { + if (strcmp("can't compare NaN", sexp_string_data(sexp_exception_message(_ARG1))) == 0) + _ARG1 = SEXP_FALSE; + else + goto call_error_handler; + } else { + _ARG1 = sexp_make_boolean(sexp_unbox_fixnum(_ARG1) < 0); + } } #else #if SEXP_USE_FLONUMS @@ -1775,8 +1781,14 @@ sexp sexp_apply (sexp ctx, sexp proc, sexp args) { _ARG1 = sexp_make_boolean(i); } else { _ARG1 = sexp_compare(ctx, tmp1, tmp2); - sexp_check_exception(); - _ARG1 = sexp_make_boolean(sexp_unbox_fixnum(_ARG1) <= 0); + if (sexp_exceptionp(_ARG1)) { + if (strcmp("can't compare NaN", sexp_string_data(sexp_exception_message(_ARG1))) == 0) + _ARG1 = SEXP_FALSE; + else + goto call_error_handler; + } else { + _ARG1 = sexp_make_boolean(sexp_unbox_fixnum(_ARG1) <= 0); + } } #else #if SEXP_USE_FLONUMS @@ -1828,8 +1840,14 @@ sexp sexp_apply (sexp ctx, sexp proc, sexp args) { #endif /* neither is complex */ _ARG1 = sexp_compare(ctx, tmp1, tmp2); - sexp_check_exception(); - _ARG1 = sexp_make_boolean(_ARG1 == SEXP_ZERO); + if (sexp_exceptionp(_ARG1)) { + if (strcmp("can't compare NaN", sexp_string_data(sexp_exception_message(_ARG1))) == 0) + _ARG1 = SEXP_FALSE; + else + goto call_error_handler; + } else { + _ARG1 = sexp_make_boolean(_ARG1 == SEXP_ZERO); + } } #else #if SEXP_USE_FLONUMS