static void check_nans (void) { mpfr_t x, sh, ch; mpfr_init2 (x, 123); mpfr_init2 (sh, 123); mpfr_init2 (ch, 123); /* nan */ mpfr_set_nan (x); mpfr_sinh_cosh (sh, ch, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (sh)); MPFR_ASSERTN (mpfr_nan_p (ch)); /* +inf */ mpfr_set_inf (x, 1); mpfr_sinh_cosh (sh, ch, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_inf_p (sh)); MPFR_ASSERTN (mpfr_sgn (sh) > 0); MPFR_ASSERTN (mpfr_inf_p (ch)); MPFR_ASSERTN (mpfr_sgn (ch) > 0); /* -inf */ mpfr_set_inf (x, -1); mpfr_sinh_cosh (sh, ch, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_inf_p (sh)); MPFR_ASSERTN (mpfr_sgn (sh) < 0); MPFR_ASSERTN (mpfr_inf_p (ch)); MPFR_ASSERTN (mpfr_sgn (ch) > 0); mpfr_clear (x); mpfr_clear (sh); mpfr_clear (ch); }
/* check against sinh, cosh */ static void check (mpfr_t x, mpfr_rnd_t rnd) { mpfr_t s, c, sx, cx; int isc, is, ic; mpfr_inits2 (MPFR_PREC(x), s, c, sx, cx, (mpfr_ptr) 0); isc = mpfr_sinh_cosh (sx, cx, x, rnd); is = mpfr_sinh (s, x, rnd); ic = mpfr_cosh (c, x, rnd); if (!mpfr_equal_p (s, sx) || !mpfr_equal_p (c, cx)) failed (x, s, sx, c, cx); MPFR_ASSERTN (isc = is || ic); mpfr_clears (s, c, sx, cx, (mpfr_ptr) 0); }
static PyObject * _GMPy_MPFR_Sinh_Cosh(PyObject *x, CTXT_Object *context) { MPFR_Object *s, *c; PyObject *result; int code; CHECK_CONTEXT(context); s = GMPy_MPFR_New(0, context); c = GMPy_MPFR_New(0, context); result = PyTuple_New(2); if (!s || !c || !result) { Py_XDECREF((PyObject*)s); Py_XDECREF((PyObject*)c); Py_XDECREF(result); return NULL; } mpfr_clear_flags(); code = mpfr_sinh_cosh(s->f, c->f, MPFR(x), GET_MPFR_ROUND(context)); s->rc = code & 0x03; c->rc = code >> 2; if (s->rc == 2) s->rc = -1; if (c->rc == 2) c->rc = -1; _GMPy_MPFR_Cleanup(&s, context); _GMPy_MPFR_Cleanup(&c, context); if (!s || !c) { Py_XDECREF((PyObject*)s); Py_XDECREF((PyObject*)c); Py_XDECREF(result); return NULL; } PyTuple_SET_ITEM(result, 0, (PyObject*)s); PyTuple_SET_ITEM(result, 1, (PyObject*)c); return result; }
int main() { slong iter; flint_rand_t state; flint_printf("sinh_cosh...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 100000; iter++) { arb_t a, b, c; fmpq_t q; mpfr_t t, u; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); fmpq_init(q); mpfr_init2(t, prec + 100); mpfr_init2(u, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, state, 1 + n_randint(state, 200), 3); arb_randtest(c, state, 1 + n_randint(state, 200), 3); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); mpfr_sinh_cosh(t, u, t, MPFR_RNDN); arb_sinh_cosh(b, c, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment (sin)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); abort(); } if (!arb_contains_mpfr(c, u)) { flint_printf("FAIL: containment (cos)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); abort(); } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(q); mpfr_clear(t); mpfr_clear(u); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
int mpc_sin_cos (mpc_ptr rop_sin, mpc_ptr rop_cos, mpc_srcptr op, mpc_rnd_t rnd_sin, mpc_rnd_t rnd_cos) /* Feature not documented in the texinfo file: One of rop_sin or rop_cos may be NULL, in which case it is not computed, and the corresponding ternary inexact value is set to 0 (exact). */ { if (!mpc_fin_p (op)) return mpc_sin_cos_nonfinite (rop_sin, rop_cos, op, rnd_sin, rnd_cos); else if (mpfr_zero_p (MPC_IM (op))) return mpc_sin_cos_real (rop_sin, rop_cos, op, rnd_sin, rnd_cos); else if (mpfr_zero_p (MPC_RE (op))) return mpc_sin_cos_imag (rop_sin, rop_cos, op, rnd_sin, rnd_cos); else { /* let op = a + i*b, then sin(op) = sin(a)*cosh(b) + i*cos(a)*sinh(b) and cos(op) = cos(a)*cosh(b) - i*sin(a)*sinh(b). For Re(sin(op)) (and analogously, the other parts), we use the following algorithm, 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). */ mpfr_t s, c, sh, ch, sch, csh; mpfr_prec_t prec; int ok; int inex_re, inex_im, inex_sin, inex_cos; prec = 2; if (rop_sin != NULL) prec = MPC_MAX (prec, MPC_MAX_PREC (rop_sin)); if (rop_cos != NULL) prec = MPC_MAX (prec, MPC_MAX_PREC (rop_cos)); mpfr_init2 (s, 2); mpfr_init2 (c, 2); mpfr_init2 (sh, 2); mpfr_init2 (ch, 2); mpfr_init2 (sch, 2); mpfr_init2 (csh, 2); do { ok = 1; 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_set_prec (sch, prec); mpfr_set_prec (csh, prec); mpfr_sin_cos (s, c, MPC_RE(op), GMP_RNDN); mpfr_sinh_cosh (sh, ch, MPC_IM(op), GMP_RNDN); if (rop_sin != NULL) { /* real part of sine */ mpfr_mul (sch, s, ch, GMP_RNDN); ok = (!mpfr_number_p (sch)) || mpfr_can_round (sch, prec - 2, GMP_RNDN, GMP_RNDZ, MPC_PREC_RE (rop_sin) + (MPC_RND_RE (rnd_sin) == GMP_RNDN)); if (ok) { /* imaginary part of sine */ mpfr_mul (csh, c, sh, GMP_RNDN); ok = (!mpfr_number_p (csh)) || mpfr_can_round (csh, prec - 2, GMP_RNDN, GMP_RNDZ, MPC_PREC_IM (rop_sin) + (MPC_RND_IM (rnd_sin) == GMP_RNDN)); } } if (rop_cos != NULL && ok) { /* real part of cosine */ mpfr_mul (c, c, ch, GMP_RNDN); ok = (!mpfr_number_p (c)) || mpfr_can_round (c, prec - 2, GMP_RNDN, GMP_RNDZ, MPC_PREC_RE (rop_cos) + (MPC_RND_RE (rnd_cos) == GMP_RNDN)); if (ok) { /* imaginary part of cosine */ mpfr_mul (s, s, sh, GMP_RNDN); mpfr_neg (s, s, GMP_RNDN); ok = (!mpfr_number_p (s)) || mpfr_can_round (s, prec - 2, GMP_RNDN, GMP_RNDZ, MPC_PREC_IM (rop_cos) + (MPC_RND_IM (rnd_cos) == GMP_RNDN)); } } } while (ok == 0); if (rop_sin != NULL) { inex_re = mpfr_set (MPC_RE (rop_sin), sch, MPC_RND_RE (rnd_sin)); if (mpfr_inf_p (sch)) inex_re = mpfr_sgn (sch); inex_im = mpfr_set (MPC_IM (rop_sin), csh, MPC_RND_IM (rnd_sin)); if (mpfr_inf_p (csh)) inex_im = mpfr_sgn (csh); inex_sin = MPC_INEX (inex_re, inex_im); } else inex_sin = MPC_INEX (0,0); /* return exact if not computed */ if (rop_cos != NULL) { inex_re = mpfr_set (MPC_RE (rop_cos), c, MPC_RND_RE (rnd_cos)); if (mpfr_inf_p (c)) inex_re = mpfr_sgn (c); inex_im = mpfr_set (MPC_IM (rop_cos), s, MPC_RND_IM (rnd_cos)); if (mpfr_inf_p (s)) inex_im = mpfr_sgn (s); inex_cos = MPC_INEX (inex_re, inex_im); } else inex_cos = MPC_INEX (0,0); /* return exact if not computed */ mpfr_clear (s); mpfr_clear (c); mpfr_clear (sh); mpfr_clear (ch); mpfr_clear (sch); mpfr_clear (csh); return (MPC_INEX12 (inex_sin, inex_cos)); } }