~ chicken-core (chicken-5) 73949bd8f231069953024c02efd0444f7c398981
commit 73949bd8f231069953024c02efd0444f7c398981 Author: felix <felix@call-with-current-continuation.org> AuthorDate: Wed Sep 8 04:46:57 2010 -0400 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Wed Sep 8 04:46:57 2010 -0400 reimplemented basic arithmetic ops diff --git a/runtime.c b/runtime.c index 7a8242bf..57378df2 100644 --- a/runtime.c +++ b/runtime.c @@ -6039,10 +6039,9 @@ void C_ccall values_continuation(C_word c, C_word closure, C_word arg0, ...) void C_ccall C_times(C_word c, C_word closure, C_word k, ...) { va_list v; - C_word x; - C_word iresult = 1; - int fflag = 0; - double fresult = 1; + C_word x, y; + C_word iresult = C_fix(1); + double fresult; C_alloc_flonum; va_start(v, k); @@ -6052,71 +6051,73 @@ void C_ccall C_times(C_word c, C_word closure, C_word k, ...) x = va_arg(v, C_word); if(x & C_FIXNUM_BIT) { - fresult *= C_unfix(x); - - if(!fflag) iresult *= C_unfix(x); + y = C_i_o_fixnum_times(iresult, x); + + if(y == C_SCHEME_FALSE) { + fresult = (double)C_unfix(iresult) * (double)C_unfix(x); + goto flonum_result; + } + else iresult = y; } else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) { - fresult *= C_flonum_magnitude(x); - - if(!fflag) fflag = 1; + fresult = (double)C_unfix(iresult) * C_flonum_magnitude(x); + goto flonum_result; } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "*", x); } va_end(v); - x = C_fix(iresult); - - if(fflag || (double)C_unfix(x) != fresult) { - C_kontinue_flonum(k, fresult); + C_kontinue(k, iresult); + + flonum_result: + while(c--) { + x = va_arg(v, C_word); + + if(x & C_FIXNUM_BIT) + fresult *= (double)C_unfix(x); + else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) + fresult *= C_flonum_magnitude(x); + else barf(C_BAD_ARGUMENT_TYPE_ERROR, "*", x); } - C_kontinue(k, x); + va_end(v); + C_kontinue_flonum(k, fresult); } C_regparm C_word C_fcall C_2_times(C_word **ptr, C_word x, C_word y) { C_word iresult; - double fresult; - int fflag = 0; if(x & C_FIXNUM_BIT) { if(y & C_FIXNUM_BIT) { - iresult = C_unfix(x) * C_unfix(y); - fresult = (double)C_unfix(x) * (double)C_unfix(y); - } - else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) { - fresult = C_unfix(x) * C_flonum_magnitude(y); - fflag = 1; + iresult = C_i_o_fixnum_times(x, y); + + if(iresult == C_SCHEME_FALSE) + return C_flonum(ptr, (double)C_unfix(x) * (double)C_unfix(y)); + else return iresult; } + else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) + return C_flonum(ptr, (double)C_unfix(x) * C_flonum_magnitude(y)); else barf(C_BAD_ARGUMENT_TYPE_ERROR, "*", y); } else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) { - fflag = 1; - - if(y & C_FIXNUM_BIT) fresult = C_flonum_magnitude(x) * C_unfix(y); + if(y & C_FIXNUM_BIT) + return C_flonum(ptr, C_flonum_magnitude(x) * (double)C_unfix(y)); else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) - fresult = C_flonum_magnitude(x) * C_flonum_magnitude(y); + return C_flonum(ptr, C_flonum_magnitude(x) * C_flonum_magnitude(y)); else barf(C_BAD_ARGUMENT_TYPE_ERROR, "*", y); } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "*", x); - - iresult = C_fix(iresult); - - if(fflag || (double)C_unfix(iresult) != fresult) return C_flonum(ptr, fresult); - - return iresult; } void C_ccall C_plus(C_word c, C_word closure, C_word k, ...) { va_list v; - C_word x; - C_word iresult = 0; - int fflag = 0; - double fresult = 0; + C_word x, y; + C_word iresult = C_fix(0); + double fresult; C_alloc_flonum; va_start(v, k); @@ -6126,293 +6127,268 @@ void C_ccall C_plus(C_word c, C_word closure, C_word k, ...) x = va_arg(v, C_word); if(x & C_FIXNUM_BIT) { - fresult += C_unfix(x); + y = C_i_o_fixnum_plus(iresult, x); - if(!fflag) iresult += C_unfix(x); + if(y == C_SCHEME_FALSE) { + fresult = (double)C_unfix(iresult) + (double)C_unfix(x); + goto flonum_result; + } + else iresult = y; } else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) { - fresult += C_flonum_magnitude(x); - - if(!fflag) fflag = 1; + fresult = (double)C_unfix(iresult) + C_flonum_magnitude(x); + goto flonum_result; } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "+", x); } va_end(v); - x = C_fix(iresult); + C_kontinue(k, iresult); - if(fflag || (double)C_unfix(x) != fresult) { - C_kontinue_flonum(k, fresult); + flonum_result: + while(c--) { + x = va_arg(v, C_word); + + if(x & C_FIXNUM_BIT) + fresult += (double)C_unfix(x); + else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) + fresult += C_flonum_magnitude(x); + else barf(C_BAD_ARGUMENT_TYPE_ERROR, "+", x); } - C_kontinue(k, x); + va_end(v); + C_kontinue_flonum(k, fresult); } C_regparm C_word C_fcall C_2_plus(C_word **ptr, C_word x, C_word y) { C_word iresult; - double fresult; - int fflag = 0; if(x & C_FIXNUM_BIT) { if(y & C_FIXNUM_BIT) { - iresult = C_unfix(x) + C_unfix(y); - fresult = (double)C_unfix(x) + (double)C_unfix(y); - } - else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) { - fresult = C_unfix(x) + C_flonum_magnitude(y); - fflag = 1; + iresult = C_i_o_fixnum_plus(x, y); + + if(iresult == C_SCHEME_FALSE) + return C_flonum(ptr, (double)C_unfix(x) + (double)C_unfix(y)); + else return iresult; } + else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) + return C_flonum(ptr, (double)C_unfix(x) + C_flonum_magnitude(y)); else barf(C_BAD_ARGUMENT_TYPE_ERROR, "+", y); } else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) { - fflag = 1; - - if(y & C_FIXNUM_BIT) fresult = C_flonum_magnitude(x) + C_unfix(y); + if(y & C_FIXNUM_BIT) + return C_flonum(ptr, C_flonum_magnitude(x) + (double)C_unfix(y)); else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) - fresult = C_flonum_magnitude(x) + C_flonum_magnitude(y); + return C_flonum(ptr, C_flonum_magnitude(x) + C_flonum_magnitude(y)); else barf(C_BAD_ARGUMENT_TYPE_ERROR, "+", y); } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "+", x); - - iresult = C_fix(iresult); - - if(fflag || (double)C_unfix(iresult) != fresult) return C_flonum(ptr, fresult); - - return iresult; } void C_ccall C_minus(C_word c, C_word closure, C_word k, C_word n1, ...) { va_list v; + C_word x, y; C_word iresult; - int fflag; double fresult; C_alloc_flonum; if(c < 3) C_bad_min_argc(c, 3); - if(n1 & C_FIXNUM_BIT) { - fresult = iresult = C_unfix(n1); - fflag = 0; - } - else if(!C_immediatep(n1) && C_block_header(n1) == C_FLONUM_TAG) { + if(n1 & C_FIXNUM_BIT) iresult = n1; + else if(!C_immediatep(n1) && C_block_header(n1) == C_FLONUM_TAG) fresult = C_flonum_magnitude(n1); - fflag = 1; - } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "-", n1); if(c == 3) { - if(fflag) fresult = -fresult; - else fresult = iresult = -iresult; - - goto cont; + if(n1 & C_FIXNUM_BIT) C_kontinue(k, C_fix(-C_unfix(n1))); + else C_kontinue_flonum(k, -fresult); } va_start(v, n1); c -= 3; while(c--) { - n1 = va_arg(v, C_word); + x = va_arg(v, C_word); - if(n1 & C_FIXNUM_BIT) { - fresult -= C_unfix(n1); + if(x & C_FIXNUM_BIT) { + y = C_i_o_fixnum_difference(iresult, x); - if(!fflag) iresult -= C_unfix(n1); + if(y == C_SCHEME_FALSE) { + fresult = (double)C_unfix(iresult) - (double)C_unfix(x); + goto flonum_result; + } + else iresult = y; } - else if(!C_immediatep(n1) && C_block_header(n1) == C_FLONUM_TAG) { - fresult -= C_flonum_magnitude(n1); - - if(!fflag) fflag = 1; + else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) { + fresult = (double)C_unfix(iresult) - C_flonum_magnitude(x); + goto flonum_result; } - else barf(C_BAD_ARGUMENT_TYPE_ERROR, "-", n1); + else barf(C_BAD_ARGUMENT_TYPE_ERROR, "-", x); } va_end(v); - - cont: - n1 = C_fix(iresult); + C_kontinue(k, iresult); - if(fflag || (double)C_unfix(n1) != fresult) { - C_kontinue_flonum(k, fresult); + flonum_result: + while(c--) { + x = va_arg(v, C_word); + + if(x & C_FIXNUM_BIT) + fresult -= (double)C_unfix(x); + else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) + fresult -= C_flonum_magnitude(x); + else barf(C_BAD_ARGUMENT_TYPE_ERROR, "-", x); } - C_kontinue(k, n1); + va_end(v); + C_kontinue_flonum(k, fresult); } C_regparm C_word C_fcall C_2_minus(C_word **ptr, C_word x, C_word y) { C_word iresult; - double fresult; - int fflag = 0; if(x & C_FIXNUM_BIT) { if(y & C_FIXNUM_BIT) { - iresult = C_unfix(x) - C_unfix(y); - fresult = (double)C_unfix(x) - (double)C_unfix(y); - } - else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) { - fresult = C_unfix(x) - C_flonum_magnitude(y); - fflag = 1; + iresult = C_i_o_fixnum_difference(x, y); + + if(iresult == C_SCHEME_FALSE) + return C_flonum(ptr, (double)C_unfix(x) - (double)C_unfix(y)); + else return iresult; } + else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) + return C_flonum(ptr, (double)C_unfix(x) - C_flonum_magnitude(y)); else barf(C_BAD_ARGUMENT_TYPE_ERROR, "-", y); } else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) { - fflag = 1; - - if(y & C_FIXNUM_BIT) fresult = C_flonum_magnitude(x) - C_unfix(y); + if(y & C_FIXNUM_BIT) + return C_flonum(ptr, C_flonum_magnitude(x) - (double)C_unfix(y)); else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) - fresult = C_flonum_magnitude(x) - C_flonum_magnitude(y); + return C_flonum(ptr, C_flonum_magnitude(x) - C_flonum_magnitude(y)); else barf(C_BAD_ARGUMENT_TYPE_ERROR, "-", y); } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "-", x); - - iresult = C_fix(iresult); - - if(fflag || (double)C_unfix(iresult) != fresult) return C_flonum(ptr, fresult); - - return iresult; } void C_ccall C_divide(C_word c, C_word closure, C_word k, C_word n1, ...) { va_list v; - C_word n2; + C_word x, y; C_word iresult; - int fflag; - double fresult, f2; + double fresult, f; C_alloc_flonum; if(c < 3) C_bad_min_argc(c, 3); - if(n1 & C_FIXNUM_BIT) { - iresult = C_unfix(n1); - fflag = 0; - } - else if(!C_immediatep(n1) && C_block_header(n1) == C_FLONUM_TAG) { + if(n1 & C_FIXNUM_BIT) iresult = n1; + else if(!C_immediatep(n1) && C_block_header(n1) == C_FLONUM_TAG) fresult = C_flonum_magnitude(n1); - fflag = 1; - } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", n1); if(c == 3) { - if(fflag) { - if(fresult == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - - fresult = 1.0 / fresult; - } - else { - if(iresult == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - - fresult = 1.0 / (double)iresult; - fflag = 1; + if(n1 & C_FIXNUM_BIT) { + if(n1 == C_fix(0)) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + else if(n1 == C_fix(1)) C_kontinue(k, C_fix(1)); + else C_kontinue_flonum(k, 1 / (double)C_unfix(n1)); } - - goto cont; + else if(fresult == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + else C_kontinue_flonum(k, 1 / fresult); } va_start(v, n1); c -= 3; while(c--) { - n1 = va_arg(v, C_word); + x = va_arg(v, C_word); - if(n1 & C_FIXNUM_BIT) { - if(fflag) { - if((n1 = C_unfix(n1)) == 0) - barf(C_DIVISION_BY_ZERO_ERROR, "/"); - - fresult /= n1; - } - else { - if((n2 = C_unfix(n1)) == 0) - barf(C_DIVISION_BY_ZERO_ERROR, "/"); + if(x & C_FIXNUM_BIT) { + if(x == C_fix(0)) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + else y = C_i_o_fixnum_quotient(iresult, x); - if((fresult = (double)iresult / (double)n2) != (iresult /= n2)) - fflag = 1; + if(y == C_SCHEME_FALSE) { + fresult = (double)C_unfix(iresult) / (double)C_unfix(x); + goto flonum_result; } + else iresult = y; } - else if(!C_immediatep(n1) && C_block_header(n1) == C_FLONUM_TAG) { - if(fflag) { - if((f2 = C_flonum_magnitude(n1)) == 0) - barf(C_DIVISION_BY_ZERO_ERROR, "/"); - - fresult /= f2; - } - else { - fflag = 1; + else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) { + f = C_flonum_magnitude(x); - if((f2 = C_flonum_magnitude(n1)) == 0) - barf(C_DIVISION_BY_ZERO_ERROR, "/"); + if(f == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - fresult = (double)iresult / f2; - } + fresult = (double)C_unfix(iresult) / f; + goto flonum_result; } - else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", n1); + else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", x); } va_end(v); - - cont: - if(fflag) { - C_kontinue_flonum(k, fresult); + C_kontinue(k, iresult); + + flonum_result: + while(c--) { + x = va_arg(v, C_word); + + if(x & C_FIXNUM_BIT) { + if(x == C_fix(0)) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + else fresult /= (double)C_unfix(x); + } + else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) { + f = C_flonum_magnitude(x); + + if(f == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + else fresult /= f; + } + else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", x); } - else n1 = C_fix(iresult); - C_kontinue(k, n1); + va_end(v); + C_kontinue_flonum(k, fresult); } C_regparm C_word C_fcall C_2_divide(C_word **ptr, C_word x, C_word y) { C_word iresult; - double fresult; - int fflag = 0; + double f; if(x & C_FIXNUM_BIT) { if(y & C_FIXNUM_BIT) { - if((iresult = C_unfix(y)) == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + if(y == C_fix(0)) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + else iresult = C_i_o_fixnum_quotient(x, y); - fresult = (double)C_unfix(x) / (double)iresult; - iresult = C_unfix(x) / iresult; + if(iresult == C_SCHEME_FALSE) + return C_flonum(ptr, (double)C_unfix(x) / (double)C_unfix(y)); + else return iresult; } else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) { - if((fresult = C_flonum_magnitude(y)) == 0.0) - barf(C_DIVISION_BY_ZERO_ERROR, "/"); + f = C_flonum_magnitude(y); - fresult = (double)C_unfix(x) / fresult; - fflag = 1; + if(f == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + else return C_flonum(ptr, (double)C_unfix(x) - f); } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", y); } else if(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG) { - fflag = 1; - if(y & C_FIXNUM_BIT) { - fresult = C_flonum_magnitude(x); - - if((iresult = C_unfix(y)) == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - - fresult = fresult / (double)iresult; + if(y == C_fix(0)) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + return C_flonum(ptr, C_flonum_magnitude(x) / (double)C_unfix(y)); } else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) { - if((fresult = C_flonum_magnitude(y)) == 0.0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + f = C_flonum_magnitude(y); - fresult = C_flonum_magnitude(x) / fresult; + if(f == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + else return C_flonum(ptr, C_flonum_magnitude(x) - f); } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", y); } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", x); - - iresult = C_fix(iresult); - - if(fflag || (double)C_unfix(iresult) != fresult) return C_flonum(ptr, fresult); - - return iresult; } diff --git a/tests/library-tests.scm b/tests/library-tests.scm index b5494c52..c120f338 100644 --- a/tests/library-tests.scm +++ b/tests/library-tests.scm @@ -20,6 +20,29 @@ (assert (not (rational? +inf.))) (assert (not (rational? 'foo))) +(define-syntax assert-fail + (syntax-rules () + ((_ exp) + (assert (handle-exceptions ex #t exp #f))))) + +(assert-fail (/ 1 1 0)) +(assert-fail (/ 1 1 0.0)) +(assert-fail (/ 1 0.0)) +(assert-fail (/ 1 0)) +(assert-fail (/ 0)) +(assert-fail (/ 0.0)) + +(assert (fixnum? (/ 1))) + +(assert (= -3 (- 3))) +(assert (= 3 (- -3))) +(assert (= 2 (- 5 3))) +(assert (> 1 (/ 3))) +(assert (> 1 (/ 3.0))) +(assert (= 2 (/ 8 4))) +(assert (zero? (+))) +(assert (= 1 (*))) + ;; number->string conversionTrap