~ chicken-core (chicken-5) cf13a294bf4ea08702633eec1983837961d835ea
commit cf13a294bf4ea08702633eec1983837961d835ea Author: felix <felix@call-with-current-continuation.org> AuthorDate: Wed Sep 8 08:45:43 2010 -0400 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Wed Sep 8 08:45:43 2010 -0400 uses old implementation of division diff --git a/runtime.c b/runtime.c index ca328c97..289a729a 100644 --- a/runtime.c +++ b/runtime.c @@ -6194,23 +6194,28 @@ void C_ccall C_minus(C_word c, C_word closure, C_word k, C_word n1, ...) C_word x, y; C_word iresult; double fresult; + int ff = 0; C_alloc_flonum; if(c < 3) C_bad_min_argc(c, 3); if(n1 & C_FIXNUM_BIT) iresult = n1; - else if(!C_immediatep(n1) && C_block_header(n1) == C_FLONUM_TAG) + else if(!C_immediatep(n1) && C_block_header(n1) == C_FLONUM_TAG) { fresult = C_flonum_magnitude(n1); + ff = 1; + } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "-", n1); if(c == 3) { - if(n1 & C_FIXNUM_BIT) C_kontinue(k, C_fix(-C_unfix(n1))); + if(!ff) C_kontinue(k, C_fix(-C_unfix(n1))); else C_kontinue_flonum(k, -fresult); } va_start(v, n1); c -= 3; + if(ff) goto flonum_result; + while(c--) { x = va_arg(v, C_word); @@ -6276,124 +6281,143 @@ C_regparm C_word C_fcall C_2_minus(C_word **ptr, C_word x, C_word y) } + void C_ccall C_divide(C_word c, C_word closure, C_word k, C_word n1, ...) { va_list v; - C_word x, y; + C_word n2; C_word iresult; - double fresult, f; - int ff = 0; + int fflag; + double fresult, f2; C_alloc_flonum; if(c < 3) C_bad_min_argc(c, 3); - if(n1 & C_FIXNUM_BIT) iresult = n1; + if(n1 & C_FIXNUM_BIT) { + iresult = C_unfix(n1); + fflag = 0; + } else if(!C_immediatep(n1) && C_block_header(n1) == C_FLONUM_TAG) { fresult = C_flonum_magnitude(n1); - ff = 1; + fflag = 1; } else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", n1); if(c == 3) { - if(!ff) { - 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)); + if(fflag) { + if(fresult == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + + fresult = 1.0 / fresult; } - else if(fresult == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - else C_kontinue_flonum(k, 1 / fresult); + else { + if(iresult == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + else if(iresult == 1) C_kontinue(k, C_fix(1)); + + fresult = 1.0 / (double)iresult; + fflag = 1; + } + + goto cont; } va_start(v, n1); c -= 3; - if(ff) goto flonum_result; - while(c--) { - x = va_arg(v, C_word); + n1 = va_arg(v, C_word); - 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(n1 & C_FIXNUM_BIT) { + if(fflag) { + if((n1 = C_unfix(n1)) == 0) + barf(C_DIVISION_BY_ZERO_ERROR, "/"); - if(y == C_SCHEME_FALSE) { - fresult = (double)C_unfix(iresult) / (double)C_unfix(x); - goto flonum_result; + fresult /= n1; } - else iresult = y; - } - 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 { + if((n2 = C_unfix(n1)) == 0) + barf(C_DIVISION_BY_ZERO_ERROR, "/"); - fresult = (double)C_unfix(iresult) / f; - goto flonum_result; + if((fresult = (double)iresult / (double)n2) != (iresult /= n2)) + fflag = 1; + } } - else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", x); - } - - va_end(v); - C_kontinue(k, iresult); + 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, "/"); - flonum_result: - while(c--) { - x = va_arg(v, C_word); + fresult /= f2; + } + else { + fflag = 1; - 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((f2 = C_flonum_magnitude(n1)) == 0) + barf(C_DIVISION_BY_ZERO_ERROR, "/"); - if(f == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - else fresult /= f; + fresult = (double)iresult / f2; + } } - else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", x); + else barf(C_BAD_ARGUMENT_TYPE_ERROR, "/", n1); } va_end(v); - C_kontinue_flonum(k, fresult); + + cont: + if(fflag) { + C_kontinue_flonum(k, fresult); + } + else n1 = C_fix(iresult); + + C_kontinue(k, n1); } C_regparm C_word C_fcall C_2_divide(C_word **ptr, C_word x, C_word y) { C_word iresult; - double f; + double fresult; + int fflag = 0; if(x & C_FIXNUM_BIT) { if(y & C_FIXNUM_BIT) { - if(y == C_fix(0)) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - else iresult = C_i_o_fixnum_quotient(x, y); + if((iresult = C_unfix(y)) == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - if(iresult == C_SCHEME_FALSE) - return C_flonum(ptr, (double)C_unfix(x) / (double)C_unfix(y)); - else return iresult; + fresult = (double)C_unfix(x) / (double)iresult; + iresult = C_unfix(x) / iresult; } else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) { - f = C_flonum_magnitude(y); + if((fresult = C_flonum_magnitude(y)) == 0.0) + barf(C_DIVISION_BY_ZERO_ERROR, "/"); - if(f == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - else return C_flonum(ptr, (double)C_unfix(x) - f); + fresult = (double)C_unfix(x) / fresult; + fflag = 1; } 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) { - if(y == C_fix(0)) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - return C_flonum(ptr, C_flonum_magnitude(x) / (double)C_unfix(y)); + fresult = C_flonum_magnitude(x); + + if((iresult = C_unfix(y)) == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); + + fresult = fresult / (double)iresult; } else if(!C_immediatep(y) && C_block_header(y) == C_FLONUM_TAG) { - f = C_flonum_magnitude(y); + if((fresult = C_flonum_magnitude(y)) == 0.0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - if(f == 0) barf(C_DIVISION_BY_ZERO_ERROR, "/"); - else return C_flonum(ptr, C_flonum_magnitude(x) - f); + fresult = C_flonum_magnitude(x) / fresult; } 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; }Trap