/ returns ratios when possible

This commit is contained in:
Alex Shinn 2011-08-06 15:57:09 +09:00
parent 3ff658e3a7
commit 3b44424140
2 changed files with 25 additions and 2 deletions

View file

@ -1086,7 +1086,9 @@ sexp sexp_mul (sexp ctx, sexp a, sexp b) {
sexp sexp_div (sexp ctx, sexp a, sexp b) {
int at=sexp_number_type(a), bt=sexp_number_type(b);
#if ! SEXP_USE_RATIOS
double f;
#endif
sexp r=SEXP_VOID;
sexp_gc_var2(tmp, rem);
sexp_gc_preserve2(ctx, tmp, rem);
@ -1105,15 +1107,23 @@ sexp sexp_div (sexp ctx, sexp a, sexp b) {
r = sexp_type_exception(ctx, NULL, SEXP_NUMBER, b);
break;
case SEXP_NUM_FIX_FIX:
#if SEXP_USE_RATIOS
r = sexp_make_ratio(ctx, a, b);
#else
f = sexp_fixnum_to_double(a) / sexp_fixnum_to_double(b);
r = ((f == trunc(f)) ? sexp_make_fixnum((sexp_sint_t)f)
: sexp_make_flonum(ctx, f));
#endif
break;
case SEXP_NUM_FIX_FLO:
r = sexp_make_flonum(ctx, sexp_fixnum_to_double(a)/sexp_flonum_value(b));
break;
case SEXP_NUM_FIX_BIG:
#if SEXP_USE_RATIOS
r = sexp_make_ratio(ctx, a, b);
#else
r = sexp_make_flonum(ctx, sexp_fixnum_to_double(a)/sexp_bignum_to_double(b));
#endif
break;
case SEXP_NUM_FLO_FIX:
r = sexp_make_flonum(ctx, sexp_flonum_value(a)/sexp_fixnum_to_double(b));
@ -1125,15 +1135,24 @@ sexp sexp_div (sexp ctx, sexp a, sexp b) {
r = sexp_make_flonum(ctx, sexp_flonum_value(a) / sexp_bignum_to_double(b));
break;
case SEXP_NUM_BIG_FIX:
#if SEXP_USE_RATIOS
r = sexp_make_ratio(ctx, a, b);
break;
#else
b = tmp = sexp_fixnum_to_bignum(ctx, b);
/* ... FALLTHROUGH ... */
#endif
/* ... FALLTHROUGH if ! SEXP_USE_RATIOS ... */
case SEXP_NUM_BIG_BIG:
#if SEXP_USE_RATIOS
r = sexp_make_ratio(ctx, a, b);
#else
r = sexp_bignum_quot_rem(ctx, &rem, a, b);
if (sexp_bignum_normalize(rem) != SEXP_ZERO)
r = sexp_make_flonum(ctx, sexp_bignum_to_double(a)
/ sexp_bignum_to_double(b));
else
r = sexp_bignum_normalize(r);
#endif
break;
case SEXP_NUM_BIG_FLO:
r = sexp_make_flonum(ctx, sexp_bignum_to_double(a) / sexp_flonum_value(b));

4
vm.c
View file

@ -1473,6 +1473,9 @@ sexp sexp_apply (sexp ctx, sexp proc, sexp args) {
#endif
sexp_raise("divide by zero", SEXP_NULL);
} else if (sexp_fixnump(tmp1) && sexp_fixnump(tmp2)) {
#if SEXP_USE_RATIOS
_ARG1 = sexp_make_ratio(ctx, tmp1, tmp2);
#else
#if SEXP_USE_FLONUMS
tmp1 = sexp_fixnum_to_flonum(ctx, tmp1);
tmp2 = sexp_fixnum_to_flonum(ctx, tmp2);
@ -1481,6 +1484,7 @@ sexp sexp_apply (sexp ctx, sexp proc, sexp args) {
_ARG1 = sexp_make_fixnum(sexp_flonum_value(_ARG1));
#else
_ARG1 = sexp_fx_div(tmp1, tmp2);
#endif
#endif
}
#if SEXP_USE_BIGNUMS