Scheme_Object *scheme_rational_power(const Scheme_Object *o, const Scheme_Object *p) { double b, e, v; if (((Scheme_Rational *)p)->denom == one) { Scheme_Object *a[2], *n; a[0] = ((Scheme_Rational *)o)->num; a[1] = ((Scheme_Rational *)p)->num; n = scheme_expt(2, a); a[0] = ((Scheme_Rational *)o)->denom; return make_rational(n, scheme_expt(2, a), 0); } if (scheme_is_rational_positive(o)) { b = scheme_rational_to_double(o); e = scheme_rational_to_double(p); v = pow(b, e); #ifdef USE_SINGLE_FLOATS_AS_DEFAULT return scheme_make_float(v); #else return scheme_make_double(v); #endif } else { return scheme_complex_power(scheme_real_to_complex(o), scheme_real_to_complex(p)); } }
Scheme_Object *scheme_complex_sqrt(const Scheme_Object *o) { Scheme_Complex *c = (Scheme_Complex *)o; Scheme_Object *r, *i, *ssq, *srssq, *nrsq, *prsq, *nr, *ni; r = c->r; i = c->i; if (scheme_is_zero(i)) { /* Special case for x+0.0i: */ r = scheme_sqrt(1, &r); if (!SCHEME_COMPLEXP(r)) return scheme_make_complex(r, i); else { c = (Scheme_Complex *)r; if (SAME_OBJ(c->r, zero)) { /* need an inexact-zero real part: */ #ifdef MZ_USE_SINGLE_FLOATS if (SCHEME_FLTP(c->i)) r = scheme_make_float(0.0); else #endif r = scheme_make_double(0.0); return scheme_make_complex(r, c->i); } else return r; } } ssq = scheme_bin_plus(scheme_bin_mult(r, r), scheme_bin_mult(i, i)); srssq = scheme_sqrt(1, &ssq); if (SCHEME_FLOATP(srssq)) { /* We may have lost too much precision, if i << r. The result is going to be inexact, anyway, so switch to using expt. */ Scheme_Object *a[2]; a[0] = (Scheme_Object *)o; a[1] = scheme_make_double(0.5); return scheme_expt(2, a); } nrsq = scheme_bin_div(scheme_bin_minus(srssq, r), scheme_make_integer(2)); nr = scheme_sqrt(1, &nrsq); if (scheme_is_negative(i)) nr = scheme_bin_minus(zero, nr); prsq = scheme_bin_div(scheme_bin_plus(srssq, r), scheme_make_integer(2)); ni = scheme_sqrt(1, &prsq); return scheme_make_complex(ni, nr); }