diff options
author | enge <enge@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2011-01-07 19:14:19 +0000 |
---|---|---|
committer | enge <enge@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2011-01-07 19:14:19 +0000 |
commit | 3b44845cd9e4242651c760ce642feb8ac41b8348 (patch) | |
tree | 138a587ada28eb4c9b0eb76b179b9a724a6d378c /src/sin.c | |
parent | c7e1e96458deb786d7db5ec3143445e3ba37085b (diff) | |
download | mpc-3b44845cd9e4242651c760ce642feb8ac41b8348.tar.gz |
sin and cos call sin_cos also for ordinary arguments
git-svn-id: svn://scm.gforge.inria.fr/svn/mpc/trunk@859 211d60ee-9f03-0410-a15a-8952a2c7a4e4
Diffstat (limited to 'src/sin.c')
-rw-r--r-- | src/sin.c | 69 |
1 files changed, 1 insertions, 68 deletions
@@ -24,72 +24,5 @@ MA 02111-1307, USA. */ int mpc_sin (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd) { - mpfr_t s, c, sh, ch; - mpfr_prec_t prec; - int ok = 0; - int inex_re, inex_im; - - /* special values */ - if (!mpc_fin_p (op) || mpfr_zero_p (MPC_IM (op)) || mpfr_zero_p (MPC_RE (op))) - return MPC_INEX1 (mpc_sin_cos (rop, NULL, op, rnd, 0)); - - /* let op = a + i*b, then sin(op) = sin(a)*cosh(b) + i*cos(a)*sinh(b). - - We use the following algorithm (same for the imaginary part), - with rounding to nearest for all operations, and working precision w: - - (1) x = o(sin(a)) - (2) y = o(cosh(b)) - (3) r = o(x*y) - then the error on r is at most 4 ulps, since we can write - r = sin(a)*cosh(b)*(1+t)^3 with |t| <= 2^(-w), - thus for w >= 2, r = sin(a)*cosh(b)*(1+4*t) with |t| <= 2^(-w), - thus the relative error is bounded by 4*2^(-w) <= 4*ulp(r). - */ - - prec = MPC_MAX_PREC(rop); - - mpfr_init2 (s, 2); - mpfr_init2 (c, 2); - mpfr_init2 (sh, 2); - mpfr_init2 (ch, 2); - - do - { - prec += mpc_ceil_log2 (prec) + 5; - - mpfr_set_prec (s, prec); - mpfr_set_prec (c, prec); - mpfr_set_prec (sh, prec); - mpfr_set_prec (ch, prec); - - mpfr_sin_cos (s, c, MPC_RE(op), GMP_RNDN); - mpfr_sinh_cosh (sh, ch, MPC_IM(op), GMP_RNDN); - mpfr_mul (s, s, ch, GMP_RNDN); - ok = (!mpfr_number_p (s)) - || mpfr_can_round (s, prec - 2, GMP_RNDN, GMP_RNDZ, - MPC_PREC_RE(rop) + (MPC_RND_RE(rnd) == GMP_RNDN)); - if (ok) /* compute imaginary part */ - { - mpfr_mul (c, c, sh, GMP_RNDN); - ok = (!mpfr_number_p (c)) - || mpfr_can_round (c, prec - 2, GMP_RNDN, GMP_RNDZ, - MPC_PREC_IM(rop) + (MPC_RND_IM(rnd) == GMP_RNDN)); - } - } - while (ok == 0); - - inex_re = mpfr_set (MPC_RE(rop), s, MPC_RND_RE(rnd)); - if (mpfr_inf_p (s)) - inex_re = mpfr_sgn (s); - inex_im = mpfr_set (MPC_IM(rop), c, MPC_RND_IM(rnd)); - if (mpfr_inf_p (c)) - inex_im = mpfr_sgn (c); - - mpfr_clear (s); - mpfr_clear (c); - mpfr_clear (sh); - mpfr_clear (ch); - - return MPC_INEX (inex_re, inex_im); + return MPC_INEX1 (mpc_sin_cos (rop, NULL, op, rnd, 0)); } |