fix complex divide: avoiding overflow/underflow ended up with the sign wrong in one case
svn: r4606
This commit is contained in:
parent
585d319eac
commit
332195b88c
|
@ -214,6 +214,7 @@ Scheme_Object *scheme_complex_divide(const Scheme_Object *_n, const Scheme_Objec
|
||||||
Scheme_Complex *cn = (Scheme_Complex *)_n;
|
Scheme_Complex *cn = (Scheme_Complex *)_n;
|
||||||
Scheme_Complex *cd = (Scheme_Complex *)_d;
|
Scheme_Complex *cd = (Scheme_Complex *)_d;
|
||||||
Scheme_Object *den, *r, *i, *a, *b, *c, *d, *cm, *dm, *aa[1];
|
Scheme_Object *den, *r, *i, *a, *b, *c, *d, *cm, *dm, *aa[1];
|
||||||
|
int swap;
|
||||||
|
|
||||||
if ((cn->r == zero) && (cn->i == zero))
|
if ((cn->r == zero) && (cn->i == zero))
|
||||||
return zero;
|
return zero;
|
||||||
|
@ -234,6 +235,21 @@ Scheme_Object *scheme_complex_divide(const Scheme_Object *_n, const Scheme_Objec
|
||||||
return scheme_make_complex(r, i);
|
return scheme_make_complex(r, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!SCHEME_FLOATP(c) && !SCHEME_FLOATP(d)) {
|
||||||
|
/* The simple way: */
|
||||||
|
cm = scheme_bin_plus(scheme_bin_mult(c, c),
|
||||||
|
scheme_bin_mult(d, d));
|
||||||
|
|
||||||
|
r = scheme_bin_div(scheme_bin_plus(scheme_bin_mult(c, a),
|
||||||
|
scheme_bin_mult(d, b)),
|
||||||
|
cm);
|
||||||
|
i = scheme_bin_div(scheme_bin_minus(scheme_bin_mult(c, b),
|
||||||
|
scheme_bin_mult(d, a)),
|
||||||
|
cm);
|
||||||
|
|
||||||
|
return scheme_make_complex(r, i);
|
||||||
|
}
|
||||||
|
|
||||||
aa[0] = d;
|
aa[0] = d;
|
||||||
if (SCHEME_TRUEP(scheme_zero_p(1, aa))) {
|
if (SCHEME_TRUEP(scheme_zero_p(1, aa))) {
|
||||||
/* This is like dividing by a real number, except that
|
/* This is like dividing by a real number, except that
|
||||||
|
@ -270,12 +286,17 @@ Scheme_Object *scheme_complex_divide(const Scheme_Object *_n, const Scheme_Objec
|
||||||
cm = c;
|
cm = c;
|
||||||
c = d;
|
c = d;
|
||||||
d = cm;
|
d = cm;
|
||||||
}
|
swap = 1;
|
||||||
|
} else
|
||||||
|
swap = 0;
|
||||||
|
|
||||||
r = scheme_bin_div(c, d);
|
r = scheme_bin_div(c, d);
|
||||||
|
|
||||||
den = scheme_bin_plus(d, scheme_bin_mult(c, r));
|
den = scheme_bin_plus(d, scheme_bin_mult(c, r));
|
||||||
|
|
||||||
i = scheme_bin_div(scheme_bin_minus(a, scheme_bin_mult(b, r)),
|
i = scheme_bin_div((swap
|
||||||
|
? scheme_bin_minus(a, scheme_bin_mult(b, r))
|
||||||
|
: scheme_bin_minus(scheme_bin_mult(b, r), a)),
|
||||||
den);
|
den);
|
||||||
r = scheme_bin_div(scheme_bin_plus(b, scheme_bin_mult(a, r)),
|
r = scheme_bin_div(scheme_bin_plus(b, scheme_bin_mult(a, r)),
|
||||||
den);
|
den);
|
||||||
|
|
|
@ -1908,6 +1908,11 @@ scheme_expt(int argc, Scheme_Object *argv[])
|
||||||
if (SCHEME_NUMBERP(e))
|
if (SCHEME_NUMBERP(e))
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
if (SCHEME_RATIONALP(e)
|
||||||
|
&& (((Scheme_Rational *)e)->num == scheme_exact_one)
|
||||||
|
&& (((Scheme_Rational *)e)->denom == scheme_make_integer(2))) {
|
||||||
|
return scheme_sqrt(1, argv);
|
||||||
|
}
|
||||||
|
|
||||||
if (n == zeroi) {
|
if (n == zeroi) {
|
||||||
/* Power of exact zero */
|
/* Power of exact zero */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user