bc: improve complex sin/cos by using sinh/cosh() from the c library.

Related to #3822.
This commit is contained in:
Sam Tobin-Hochstadt 2021-05-07 15:49:02 -04:00 committed by Sam Tobin-Hochstadt
parent 7084b617c4
commit 022066530e

View File

@ -2803,14 +2803,8 @@ static Scheme_Object *get_frac(char *name, int low_p,
return n; return n;
} }
static Scheme_Object *un_exp(Scheme_Object *o);
static Scheme_Object *un_log(Scheme_Object *o); static Scheme_Object *un_log(Scheme_Object *o);
static Scheme_Object *un_exp(Scheme_Object *o)
{
return exp_prim(1, &o);
}
static Scheme_Object *un_log(Scheme_Object *o) static Scheme_Object *un_log(Scheme_Object *o)
{ {
return log_e_prim(1, &o); return log_e_prim(1, &o);
@ -2889,28 +2883,54 @@ static Scheme_Object *bignum_log(Scheme_Object *b)
return scheme_make_double(d); return scheme_make_double(d);
} }
static Scheme_Object *inexact_cosh(Scheme_Object *n) {
double r;
r = cosh(TO_DOUBLE_VAL(n));
#ifdef MZ_USE_SINGLE_FLOATS
if (SCHEME_FLTP(n)) return scheme_make_float(r);
#endif
return scheme_make_double(r);
}
static Scheme_Object *inexact_sinh(Scheme_Object *n) {
double r;
r = sinh(TO_DOUBLE_VAL(n));
#ifdef MZ_USE_SINGLE_FLOATS
if (SCHEME_FLTP(n)) return scheme_make_float(r);
#endif
return scheme_make_double(r);
}
static Scheme_Object *complex_sin(Scheme_Object *c) static Scheme_Object *complex_sin(Scheme_Object *c)
{ {
Scheme_Object *i_c; Scheme_Object *a, *b;
i_c = scheme_bin_mult(c, scheme_plus_i); /* sin(a+bi) = sin(a)cosh(b)+cos(a)sinh(b)i */
return scheme_bin_div(scheme_bin_minus(un_exp(i_c), a = _scheme_complex_real_part(c);
un_exp(scheme_bin_minus(zeroi, i_c))), b = _scheme_complex_imaginary_part(c);
scheme_bin_mult(scheme_make_integer(2), scheme_plus_i));
return scheme_make_complex(scheme_bin_mult(sin_prim(1, &a), inexact_cosh(b)),
scheme_bin_mult(cos_prim(1, &a), inexact_sinh(b)));
} }
static Scheme_Object *complex_cos(Scheme_Object *c) static Scheme_Object *complex_cos(Scheme_Object *c)
{ {
Scheme_Object *i_c; Scheme_Object *a, *b;
i_c = scheme_bin_mult(c, scheme_plus_i); /* cos(a+bi) = cos(a)cosh(b)-sin(a)sinh(b)i */
return scheme_bin_div(scheme_bin_plus(un_exp(i_c), a = _scheme_complex_real_part(c);
un_exp(scheme_bin_minus(zeroi, i_c))), b = _scheme_complex_imaginary_part(c);
scheme_make_integer(2));
return scheme_make_complex(scheme_bin_mult(cos_prim(1, &a), inexact_cosh(b)),
scheme_bin_minus(scheme_make_integer(0),
scheme_bin_mult(sin_prim(1, &a),
inexact_sinh(b))));
} }
static Scheme_Object *complex_tan(Scheme_Object *c) static Scheme_Object *complex_tan(Scheme_Object *c)
{ {
return scheme_bin_div(complex_sin(c), complex_cos(c)); return scheme_bin_div(complex_sin(c), complex_cos(c));