diff --git a/eval.c b/eval.c index fec23de4..3e1a1f6e 100644 --- a/eval.c +++ b/eval.c @@ -63,7 +63,7 @@ static sexp sexp_env_cell_create (sexp ctx, sexp e, sexp key, sexp value) { return cell; } -static sexp sexp_env_global_ref (sexp e, sexp key, sexp dflt) { +sexp sexp_env_global_ref (sexp e, sexp key, sexp dflt) { sexp cell; while (sexp_env_parent(e)) e = sexp_env_parent(e); @@ -1650,7 +1650,7 @@ sexp sexp_vm (sexp ctx, sexp proc) { #if USE_BIGNUMS tmp1 = _ARG1, tmp2 = _ARG2; if (sexp_fixnump(tmp1) && sexp_fixnump(tmp2)) { - prod = sexp_unbox_fixnum(tmp1) * sexp_unbox_fixnum(tmp2); + prod = (sexp_lsint_t)sexp_unbox_fixnum(tmp1) * sexp_unbox_fixnum(tmp2); if ((prod < SEXP_MIN_FIXNUM) || (prod > SEXP_MAX_FIXNUM)) _ARG2 = sexp_mul(ctx, tmp1=sexp_fixnum_to_bignum(ctx, tmp1), tmp2); else diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index d9b1d87e..f304cc9d 100644 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -632,7 +632,7 @@ SEXP_API sexp sexp_make_integer(sexp ctx, sexp_sint_t x); #define sexp_fx_mul(a, b) ((sexp)((((((sexp_sint_t)a)-SEXP_FIXNUM_TAG)*(((sexp_sint_t)b)>>SEXP_FIXNUM_BITS))+SEXP_FIXNUM_TAG))) #define sexp_fx_div(a, b) (sexp_make_fixnum(sexp_unbox_fixnum(a) / sexp_unbox_fixnum(b))) #define sexp_fx_rem(a, b) (sexp_make_fixnum(sexp_unbox_fixnum(a) % sexp_unbox_fixnum(b))) -#define sexp_fx_sign(a) (+1 | (((sexp_sint_t)(a)) >> (sizeof(int)*8 - 1))) +#define sexp_fx_sign(a) (+1 | (((sexp_sint_t)(a)) >> (sizeof(sexp_sint_t)*8 - 1))) #define sexp_fx_neg(a) (sexp_make_fixnum(-(sexp_unbox_fixnum(a)))) #define sexp_fx_abs(a) ((((sexp_sint_t)a) < 0) ? sexp_fx_neg(a) : a) diff --git a/opt/bignum.c b/opt/bignum.c index ed75b6bd..3cd89f8b 100644 --- a/opt/bignum.c +++ b/opt/bignum.c @@ -130,17 +130,11 @@ double sexp_bignum_to_double (sexp a) { sexp sexp_bignum_fxadd (sexp ctx, sexp a, sexp_uint_t b) { sexp_uint_t len=sexp_bignum_hi(a), *data=sexp_bignum_data(a), - carry=b, i, n; - for (i=0; i (SEXP_UINT_T_MAX - carry)) { - carry = 1; - } else { - carry = 0; - break; - } - } + carry=b, i=0, n; + do { n = data[i]; + data[i] += carry; + carry = (n > (SEXP_UINT_T_MAX - carry)); + } while (++i=offset; i--) { @@ -470,13 +464,13 @@ static int sexp_number_types[] = {0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0}; static int sexp_number_type (sexp a) { - return sexp_pointerp(a) ? sexp_number_types[sexp_pointer_tag(a)&1111] + return sexp_pointerp(a) ? sexp_number_types[sexp_pointer_tag(a)&15] : sexp_fixnump(a); } sexp sexp_add (sexp ctx, sexp a, sexp b) { int at=sexp_number_type(a), bt=sexp_number_type(b), t; - sexp r; + sexp r=SEXP_VOID; if (at > bt) {r=a; a=b; b=r; t=at; at=bt; bt=t;} switch ((at << 2) + bt) { case SEXP_NUM_NOT_NOT: case SEXP_NUM_NOT_FIX: @@ -484,7 +478,7 @@ sexp sexp_add (sexp ctx, sexp a, sexp b) { r = sexp_type_exception(ctx, "+: not a number", a); break; case SEXP_NUM_FIX_FIX: - r = sexp_fx_add(a, b); /* XXXX check overflow */ + r = sexp_fx_add(a, b); /* VM catches this case */ break; case SEXP_NUM_FIX_FLO: r = sexp_make_flonum(ctx, sexp_fixnum_to_double(a)+sexp_flonum_value(b)); @@ -507,7 +501,7 @@ sexp sexp_add (sexp ctx, sexp a, sexp b) { sexp sexp_sub (sexp ctx, sexp a, sexp b) { int at=sexp_number_type(a), bt=sexp_number_type(b); - sexp r; + sexp r=SEXP_VOID; switch ((at << 2) + bt) { case SEXP_NUM_NOT_NOT: case SEXP_NUM_NOT_FIX: case SEXP_NUM_NOT_FLO: case SEXP_NUM_NOT_BIG: @@ -517,7 +511,7 @@ sexp sexp_sub (sexp ctx, sexp a, sexp b) { r = sexp_type_exception(ctx, "-: not a number", b); break; case SEXP_NUM_FIX_FIX: - r = sexp_fx_sub(a, b); /* XXXX check overflow */ + r = sexp_fx_sub(a, b); /* VM catches this case */ break; case SEXP_NUM_FIX_FLO: r = sexp_make_flonum(ctx, sexp_fixnum_to_double(a)-sexp_flonum_value(b)); @@ -550,7 +544,7 @@ sexp sexp_sub (sexp ctx, sexp a, sexp b) { sexp sexp_mul (sexp ctx, sexp a, sexp b) { int at=sexp_number_type(a), bt=sexp_number_type(b), t; - sexp r; + sexp r=SEXP_VOID; if (at > bt) {r=a; a=b; b=r; t=at; at=bt; bt=t;} switch ((at << 2) + bt) { case SEXP_NUM_NOT_NOT: case SEXP_NUM_NOT_FIX: @@ -583,7 +577,7 @@ 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); double f; - sexp r, rem; + sexp r=SEXP_VOID, rem; switch ((at << 2) + bt) { case SEXP_NUM_NOT_NOT: case SEXP_NUM_NOT_FIX: case SEXP_NUM_NOT_FLO: case SEXP_NUM_NOT_BIG: @@ -632,7 +626,7 @@ sexp sexp_div (sexp ctx, sexp a, sexp b) { sexp sexp_quotient (sexp ctx, sexp a, sexp b) { int at=sexp_number_type(a), bt=sexp_number_type(b); - sexp r; + sexp r=SEXP_VOID; switch ((at << 2) + bt) { case SEXP_NUM_NOT_NOT: case SEXP_NUM_NOT_FIX: case SEXP_NUM_NOT_FLO: case SEXP_NUM_NOT_BIG: @@ -665,7 +659,7 @@ sexp sexp_quotient (sexp ctx, sexp a, sexp b) { sexp sexp_remainder (sexp ctx, sexp a, sexp b) { int at=sexp_number_type(a), bt=sexp_number_type(b); - sexp r; + sexp r=SEXP_VOID; switch ((at << 2) + bt) { case SEXP_NUM_NOT_NOT: case SEXP_NUM_NOT_FIX: case SEXP_NUM_NOT_FLO: case SEXP_NUM_NOT_BIG: @@ -698,7 +692,7 @@ sexp sexp_remainder (sexp ctx, sexp a, sexp b) { sexp sexp_compare (sexp ctx, sexp a, sexp b) { int at=sexp_number_type(a), bt=sexp_number_type(b); - sexp r; + sexp r=SEXP_VOID; double f; if (at > bt) { r = sexp_compare(ctx, b, a); diff --git a/tests/numeric-tests.scm b/tests/numeric-tests.scm index a5d17b2f..76a783f0 100644 --- a/tests/numeric-tests.scm +++ b/tests/numeric-tests.scm @@ -128,6 +128,12 @@ (-12884901889 4294967297 36893488151714070528 0 -4294967296)) (sign-combinations (expt 2 32) (+ 1 (expt 2 33)))) +(test '((18446744078004518913 -18446744069414584321 79228162514264337597838917632 0 4294967296) + (18446744069414584321 -18446744078004518913 -79228162514264337597838917632 0 -4294967296) + (-18446744069414584321 18446744078004518913 -79228162514264337597838917632 0 4294967296) + (-18446744078004518913 18446744069414584321 79228162514264337597838917632 0 -4294967296)) + (sign-combinations (expt 2 32) (+ 1 (expt 2 64)))) + ;; bigger x big (test '((12884901889 4294967297 36893488151714070528 2 1) (-4294967297 -12884901889 -36893488151714070528 -2 -1) @@ -135,4 +141,10 @@ (-12884901889 -4294967297 36893488151714070528 2 -1)) (sign-combinations (+ 1 (expt 2 33)) (expt 2 32))) +(test '((18446744078004518913 18446744069414584321 79228162514264337597838917632 4294967296 1) + (-18446744069414584321 -18446744078004518913 -79228162514264337597838917632 -4294967296 -1) + (18446744069414584321 18446744078004518913 -79228162514264337597838917632 -4294967296 1) + (-18446744078004518913 -18446744069414584321 79228162514264337597838917632 4294967296 -1)) + (sign-combinations (+ 1 (expt 2 64)) (expt 2 32))) + (test-report)