summaryrefslogtreecommitdiff
path: root/src/sin.c
diff options
context:
space:
mode:
authorenge <enge@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2011-01-07 19:14:19 +0000
committerenge <enge@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2011-01-07 19:14:19 +0000
commit3b44845cd9e4242651c760ce642feb8ac41b8348 (patch)
tree138a587ada28eb4c9b0eb76b179b9a724a6d378c /src/sin.c
parentc7e1e96458deb786d7db5ec3143445e3ba37085b (diff)
downloadmpc-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.c69
1 files changed, 1 insertions, 68 deletions
diff --git a/src/sin.c b/src/sin.c
index 48c09be..6581e56 100644
--- a/src/sin.c
+++ b/src/sin.c
@@ -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));
}