diff --git a/eval.c b/eval.c index 263f4797..2d06a3d2 100644 --- a/eval.c +++ b/eval.c @@ -1584,6 +1584,77 @@ sexp sexp_complex_imag_op (sexp ctx, sexp self, sexp_sint_t n, sexp cpx) { } #endif +sexp sexp_exact_to_inexact (sexp ctx, sexp self, sexp_sint_t n, sexp i) { + sexp_gc_var1(res); + res = i; + if (sexp_fixnump(i)) + res = sexp_fixnum_to_flonum(ctx, i); +#if SEXP_USE_FLONUMS + else if (sexp_flonump(i)) + res = i; +#endif +#if SEXP_USE_BIGNUMS + else if (sexp_bignump(i)) + res = sexp_make_flonum(ctx, sexp_bignum_to_double(i)); +#endif +#if SEXP_USE_RATIOS + else if (sexp_ratiop(i)) + res = sexp_make_flonum(ctx, sexp_ratio_to_double(i)); +#endif +#if SEXP_USE_COMPLEX + else if (sexp_complexp(i)) { + sexp_gc_preserve1(ctx, res); + res = sexp_make_complex(ctx, SEXP_ZERO, SEXP_ZERO); + sexp_complex_real(res) = sexp_exact_to_inexact(ctx, self, 1, sexp_complex_real(i)); + sexp_complex_imag(res) = sexp_exact_to_inexact(ctx, self, 1, sexp_complex_imag(i)); + sexp_gc_release1(ctx); + } +#endif + else + res = sexp_type_exception(ctx, self, SEXP_FIXNUM, i); + return res; +} + +sexp sexp_inexact_to_exact (sexp ctx, sexp self, sexp_sint_t n, sexp z) { + sexp_gc_var1(res); + if (sexp_exactp(z)) { + res = z; + } +#if SEXP_USE_FLONUMS + else if (sexp_flonump(z)) { + if (isinf(sexp_flonum_value(z)) || isnan(sexp_flonum_value(z))) { + res = sexp_xtype_exception(ctx, self, "exact: not an finite number", z); + } else if (sexp_flonum_value(z) != trunc(sexp_flonum_value(z))) { +#if SEXP_USE_RATIOS + res = sexp_double_to_ratio(ctx, sexp_flonum_value(z)); +#else + res = sexp_xtype_exception(ctx, self, "exact: not an integer", z); +#endif +#if SEXP_USE_BIGNUMS + } else if ((sexp_flonum_value(z) > SEXP_MAX_FIXNUM) + || sexp_flonum_value(z) < SEXP_MIN_FIXNUM) { + res = sexp_double_to_bignum(ctx, sexp_flonum_value(z)); +#endif + } else { + res = sexp_make_fixnum((sexp_sint_t)sexp_flonum_value(z)); + } + } +#endif +#if SEXP_USE_COMPLEX + else if (sexp_complexp(z)) { + sexp_gc_preserve1(ctx, res); + res = sexp_make_complex(ctx, SEXP_ZERO, SEXP_ZERO); + sexp_complex_real(res) = sexp_inexact_to_exact(ctx, self, 1, sexp_complex_real(z)); + sexp_complex_imag(res) = sexp_inexact_to_exact(ctx, self, 1, sexp_complex_imag(z)); + sexp_gc_release1(ctx); + } +#endif + else { + res = sexp_type_exception(ctx, self, SEXP_FLONUM, z); + } + return res; +} + sexp sexp_string_cmp_op (sexp ctx, sexp self, sexp_sint_t n, sexp str1, sexp str2, sexp ci) { sexp_sint_t len1, len2, len, diff; sexp_assert_type(ctx, sexp_stringp, SEXP_STRING, str1); diff --git a/include/chibi/eval.h b/include/chibi/eval.h index ced169cf..5417f23c 100644 --- a/include/chibi/eval.h +++ b/include/chibi/eval.h @@ -168,14 +168,14 @@ SEXP_API sexp sexp_floor(sexp ctx, sexp self, sexp_sint_t n, sexp x); SEXP_API sexp sexp_ceiling(sexp ctx, sexp self, sexp_sint_t n, sexp x); #endif SEXP_API sexp sexp_expt_op(sexp ctx, sexp self, sexp_sint_t n, sexp z1, sexp z2); +SEXP_API sexp sexp_exact_to_inexact(sexp ctx, sexp self, sexp_sint_t n, sexp i); +SEXP_API sexp sexp_inexact_to_exact(sexp ctx, sexp self, sexp_sint_t n, sexp x); #if SEXP_USE_NATIVE_X86 SEXP_API sexp sexp_write_char_op(sexp ctx, sexp self, sexp_sint_t n, sexp ch, sexp out); SEXP_API sexp sexp_newline_op(sexp ctx, sexp self, sexp_sint_t n, sexp out); SEXP_API sexp sexp_read_char_op(sexp ctx, sexp self, sexp_sint_t n, sexp in); SEXP_API sexp sexp_peek_char_op(sexp ctx, sexp self, sexp_sint_t n, sexp in); -SEXP_API sexp sexp_exact_to_inexact(sexp ctx, sexp self, sexp_sint_t n, sexp i); -SEXP_API sexp sexp_inexact_to_exact(sexp ctx, sexp self, sexp_sint_t n, sexp x); SEXP_API sexp sexp_char_upcase(sexp ctx, sexp self, sexp_sint_t n, sexp ch); SEXP_API sexp sexp_char_downcase(sexp ctx, sexp self, sexp_sint_t n, sexp ch); #endif diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index 794c5495..e8fb00a8 100755 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -1607,8 +1607,6 @@ enum sexp_opcode_names { SEXP_OP_LE, SEXP_OP_EQN, SEXP_OP_EQ, - SEXP_OP_FIX2FLO, - SEXP_OP_FLO2FIX, SEXP_OP_CHAR2INT, SEXP_OP_INT2CHAR, SEXP_OP_CHAR_UPCASE, diff --git a/opcodes.c b/opcodes.c index 264ac985..b29f8ce4 100644 --- a/opcodes.c +++ b/opcodes.c @@ -67,14 +67,12 @@ _OP(SEXP_OPC_SETTER, SEXP_OP_STRING_SET, 3, 0, SEXP_VOID, _I(SEXP_STRING), _I(SE #endif #endif _OP(SEXP_OPC_GETTER, SEXP_OP_STRING_LENGTH, 1, 0, _I(SEXP_FIXNUM), _I(SEXP_STRING), SEXP_FALSE, SEXP_FALSE, 0,"string-length", 0, NULL), -#if SEXP_USE_NATIVE_X86 _FN1(_I(SEXP_FLONUM), _I(SEXP_FIXNUM), "exact->inexact", 0, sexp_exact_to_inexact), _FN1(_I(SEXP_FIXNUM), _I(SEXP_FLONUM), "inexact->exact", 0, sexp_inexact_to_exact), +#if SEXP_USE_NATIVE_X86 _FN1(_I(SEXP_CHAR), _I(SEXP_CHAR), "char-upcase", 0, sexp_char_upcase), _FN1(_I(SEXP_CHAR), _I(SEXP_CHAR), "char-downcase", 0, sexp_char_downcase), #else -_OP(SEXP_OPC_GENERIC, SEXP_OP_FIX2FLO, 1, 0, _I(SEXP_FLONUM), _I(SEXP_NUMBER), SEXP_FALSE, SEXP_FALSE, 0, "exact->inexact", 0, NULL), -_OP(SEXP_OPC_GENERIC, SEXP_OP_FLO2FIX, 1, 0, _I(SEXP_FIXNUM), _I(SEXP_NUMBER), SEXP_FALSE, SEXP_FALSE, 0, "inexact->exact", 0, NULL), _OP(SEXP_OPC_GENERIC, SEXP_OP_CHAR_UPCASE, 1, 0, _I(SEXP_CHAR), _I(SEXP_CHAR), SEXP_FALSE, SEXP_FALSE, 0, "char-upcase", 0, NULL), _OP(SEXP_OPC_GENERIC, SEXP_OP_CHAR_DOWNCASE, 1, 0, _I(SEXP_CHAR), _I(SEXP_CHAR), SEXP_FALSE, SEXP_FALSE, 0, "char-downcase", 0, NULL), #endif diff --git a/vm.c b/vm.c index 2aa798c3..ba14ced4 100644 --- a/vm.c +++ b/vm.c @@ -1857,48 +1857,6 @@ sexp sexp_apply (sexp ctx, sexp proc, sexp args) { _ARG2 = sexp_make_boolean(_ARG1 == _ARG2); top--; break; - case SEXP_OP_FIX2FLO: -#if SEXP_USE_FLONUMS - sexp_context_top(ctx) = top; - if (sexp_fixnump(_ARG1)) - _ARG1 = sexp_fixnum_to_flonum(ctx, _ARG1); -#if SEXP_USE_BIGNUMS - else if (sexp_bignump(_ARG1)) - _ARG1 = sexp_make_flonum(ctx, sexp_bignum_to_double(_ARG1)); -#endif -#if SEXP_USE_RATIOS - else if (sexp_ratiop(_ARG1)) - _ARG1 = sexp_make_flonum(ctx, sexp_ratio_to_double(_ARG1)); -#endif - else if (! sexp_flonump(_ARG1)) - sexp_raise("inexact: not a number", sexp_list1(ctx, _ARG1)); -#endif - break; - case SEXP_OP_FLO2FIX: -#if SEXP_USE_FLONUMS - if (sexp_flonump(_ARG1)) { - if (isinf(sexp_flonum_value(_ARG1)) || isnan(sexp_flonum_value(_ARG1))) { - sexp_raise("exact: not an finite number", sexp_list1(ctx, _ARG1)); - } else if (sexp_flonum_value(_ARG1) != trunc(sexp_flonum_value(_ARG1))) { -#if SEXP_USE_RATIOS - _ARG1 = sexp_double_to_ratio(ctx, sexp_flonum_value(_ARG1)); -#else - sexp_raise("exact: not an integer", sexp_list1(ctx, _ARG1)); -#endif -#if SEXP_USE_BIGNUMS - } else if ((sexp_flonum_value(_ARG1) > SEXP_MAX_FIXNUM) - || sexp_flonum_value(_ARG1) < SEXP_MIN_FIXNUM) { - sexp_context_top(ctx) = top; - _ARG1 = sexp_double_to_bignum(ctx, sexp_flonum_value(_ARG1)); -#endif - } else { - _ARG1 = sexp_make_fixnum((sexp_sint_t)sexp_flonum_value(_ARG1)); - } - } else if (!sexp_exactp(_ARG1)) { - sexp_raise("exact: not a number", sexp_list1(ctx, _ARG1)); - } -#endif - break; case SEXP_OP_CHAR2INT: if (! sexp_charp(_ARG1)) sexp_raise("char->integer: not a character", sexp_list1(ctx, _ARG1));