static void special_overflow (void) { /* Check for overflow in 3 cases: 1. cosh(x) is representable, but not exp(x) 2. cosh(x) is not representable in the selected range of exp. 3. cosh(x) exp overflow even with the largest range of exp */ mpfr_t x, y; mp_exp_t emin, emax; emin = mpfr_get_emin (); emax = mpfr_get_emax (); set_emin (-125); set_emax (128); mpfr_init2 (x, 24); mpfr_init2 (y, 24); mpfr_set_str_binary (x, "0.101100100000000000110100E7"); mpfr_cosh (y, x, GMP_RNDN); if (mpfr_cmp_str (y, "0.101010001111001010001110E128", 2, GMP_RNDN)) { printf("Special overflow error 1.\n"); mpfr_dump (y); exit (1); } mpfr_set_str_binary (x, "0.101100100000000000110100E8"); mpfr_cosh (y, x, GMP_RNDN); if (!mpfr_inf_p(y)) { printf("Special overflow error 2.\n"); mpfr_dump (y); exit (1); } set_emin (emin); set_emax (emax); mpfr_set_str_binary (x, "0.101100100000000000110100E1000000"); mpfr_cosh (y, x, GMP_RNDN); if (!mpfr_inf_p(y)) { printf("Special overflow error 3.\n"); mpfr_dump (y); exit (1); } mpfr_clear (y); mpfr_clear (x); }
/// @brief sin keyword implementation /// void program::rpn_sin(void) { MIN_ARGUMENTS(1); if (_stack->get_type(0) == cmd_number) { floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) { // sin(x+iy)=sin(x)cosh(y)+icos(x)sinh(y) stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value; floating_t* x = ((complex*)_calc_stack.get_obj(1))->re(); floating_t* y = ((complex*)_calc_stack.get_obj(1))->im(); floating_t* re = ((complex*)_stack->get_obj(0))->re(); floating_t* im = ((complex*)_stack->get_obj(0))->im(); CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cos(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); _calc_stack.pop_back(2); } else ERR_CONTEXT(ret_bad_operand_type); }
int main() { slong iter; flint_rand_t state; flint_printf("cosh...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, 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_cosh(t, t, MPFR_RNDN); arb_cosh(b, a, prec); if (!arb_contains_mpfr(b, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); abort(); } arb_cosh(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
decimal r_cosh(const decimal& a,bool round) { #ifdef USE_CGAL CGAL::Gmpfr m; CGAL::Gmpfr n=to_gmpfr(a); mpfr_cosh(m.fr(),n.fr(),MPFR_RNDN); return r_round_preference(decimal(m),round); #else return r_round_preference(cosh(a),round); #endif }
//------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_float::cosh() { #ifdef KNUMBER_USE_MPFR mpfr_t mpfr; mpfr_init_set_f(mpfr, mpf_, rounding_mode); mpfr_cosh(mpfr, mpfr, rounding_mode); mpfr_get_f(mpf_, mpfr, rounding_mode); mpfr_clear(mpfr); return this; #else const double x = mpf_get_d(mpf_); return execute_libc_func< ::cosh>(x); #endif }
static void pure_real_argument (void) { /* cosh(x -i*0) = cosh(x) +i*0 if x<0 */ /* cosh(x -i*0) = cosh(x) -i*0 if x>0 */ /* cosh(x +i*0) = cosh(x) -i*0 if x<0 */ /* cosh(x -i*0) = cosh(x) +i*0 if x>0 */ mpc_t u; mpc_t z; mpc_t cosh_z; mpc_init2 (z, 2); mpc_init2 (u, 100); mpc_init2 (cosh_z, 100); /* cosh(1 +i*0) = cosh(1) +i*0 */ mpc_set_ui_ui (z, 1, 0, MPC_RNDNN); mpfr_cosh (MPC_RE (u), MPC_RE (z), GMP_RNDN); mpfr_set_ui (MPC_IM (u), 0, GMP_RNDN); mpc_cosh (cosh_z, z, MPC_RNDNN); if (mpc_cmp (cosh_z, u) != 0 || mpfr_signbit (MPC_IM (cosh_z))) TEST_FAILED ("mpc_cosh", z, cosh_z, u, MPC_RNDNN); /* cosh(1 -i*0) = cosh(1) -i*0 */ mpc_conj (z, z, MPC_RNDNN); mpc_conj (u, u, MPC_RNDNN); mpc_cosh (cosh_z, z, MPC_RNDNN); if (mpc_cmp (cosh_z, u) != 0 || !mpfr_signbit (MPC_IM (cosh_z))) TEST_FAILED ("mpc_cosh", z, cosh_z, u, MPC_RNDNN); /* cosh(-1 +i*0) = cosh(1) -i*0 */ mpc_neg (z, z, MPC_RNDNN); mpc_cosh (cosh_z, z, MPC_RNDNN); if (mpc_cmp (cosh_z, u) != 0 || !mpfr_signbit (MPC_IM (cosh_z))) TEST_FAILED ("mpc_cosh", z, cosh_z, u, MPC_RNDNN); /* cosh(-1 -i*0) = cosh(1) +i*0 */ mpc_conj (z, z, MPC_RNDNN); mpc_conj (u, u, MPC_RNDNN); mpc_cosh (cosh_z, z, MPC_RNDNN); if (mpc_cmp (cosh_z, u) != 0 || mpfr_signbit (MPC_IM (cosh_z))) TEST_FAILED ("mpc_cosh", z, cosh_z, u, MPC_RNDNN); mpc_clear (cosh_z); mpc_clear (z); mpc_clear (u); }
/* 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 int mpc_sin_cos_imag (mpc_ptr rop_sin, mpc_ptr rop_cos, mpc_srcptr op, mpc_rnd_t rnd_sin, mpc_rnd_t rnd_cos) /* assumes that op is purely imaginary */ { int inex_sin_im = 0, inex_cos_re = 0; /* assume exact if not computed */ int overlap; mpc_t op_loc; overlap = (rop_sin == op || rop_cos == op); if (overlap) { mpc_init3 (op_loc, MPC_PREC_RE (op), MPC_PREC_IM (op)); mpc_set (op_loc, op, MPC_RNDNN); } else op_loc [0] = op [0]; if (rop_sin != NULL) { /* sin(+-O +i*y) = +-0 +i*sinh(y) */ mpfr_set (MPC_RE(rop_sin), MPC_RE(op_loc), GMP_RNDN); inex_sin_im = mpfr_sinh (MPC_IM(rop_sin), MPC_IM(op_loc), MPC_RND_IM(rnd_sin)); } if (rop_cos != NULL) { /* cos(-0 - i * y) = cos(+0 + i * y) = cosh(y) - i * 0, cos(-0 + i * y) = cos(+0 - i * y) = cosh(y) + i * 0, where y >= 0 */ if (mpfr_zero_p (MPC_IM (op_loc))) inex_cos_re = mpfr_set_ui (MPC_RE (rop_cos), 1ul, MPC_RND_RE (rnd_cos)); else inex_cos_re = mpfr_cosh (MPC_RE (rop_cos), MPC_IM (op_loc), MPC_RND_RE (rnd_cos)); mpfr_set_ui (MPC_IM (rop_cos), 0ul, MPC_RND_IM (rnd_cos)); if (mpfr_signbit (MPC_RE (op_loc)) == mpfr_signbit (MPC_IM (op_loc))) MPFR_CHANGE_SIGN (MPC_IM (rop_cos)); } if (overlap) mpc_clear (op_loc); return MPC_INEX12 (MPC_INEX (0, inex_sin_im), MPC_INEX (inex_cos_re, 0)); }
static int check_NAN (void) { mpfr_t t, ch,sh,th,ach,ash,ath; int tester; int fail = 0; mpfr_init2(t,200); mpfr_init2(ch,200); mpfr_init2(sh,200); mpfr_init2(th,200); mpfr_init2(ach,200); mpfr_init2(ash,200); mpfr_init2(ath,200); MPFR_SET_NAN(t); /******cosh********/ tester=mpfr_cosh(ch,t,MPFR_RNDD); if (!MPFR_IS_NAN(ch) || tester!=0) { printf("cosh NAN \n"); fail = 1; goto clean_up; } /******sinh********/ tester=mpfr_sinh(sh,t,MPFR_RNDD); if (!MPFR_IS_NAN(sh) || tester!=0) { printf("sinh NAN \n"); fail = 1; goto clean_up; } /******tanh********/ tester=mpfr_tanh(th,t,MPFR_RNDD); if (!MPFR_IS_NAN(th) || tester!=0) { printf("tanh NAN \n"); fail = 1; goto clean_up; } /******acosh********/ tester=mpfr_acosh(ach,t,MPFR_RNDD); if (!MPFR_IS_NAN(ach) || tester!=0) { printf("acosh NAN \n"); fail = 1; goto clean_up; } /******asinh********/ tester=mpfr_asinh(ash,t,MPFR_RNDD); if (!MPFR_IS_NAN(ash) || tester!=0) { printf("asinh NAN \n"); fail = 1; goto clean_up; } /******atanh********/ tester=mpfr_atanh(ath,t,MPFR_RNDD); if (!MPFR_IS_NAN(ath) || tester!=0) { printf("atanh NAN \n"); fail = 1; goto clean_up; } clean_up: mpfr_clear(t); mpfr_clear(ch); mpfr_clear(sh); mpfr_clear(th); mpfr_clear(ach); mpfr_clear(ash); mpfr_clear(ath); return fail; }
static int check_INF (void) { mpfr_t t, ch, sh, th, ach, ash, ath; int tester; int fail = 0; mpfr_init2 (t, 200); mpfr_init2 (ch, 200); mpfr_init2 (sh, 200); mpfr_init2 (th, 200); mpfr_init2 (ach, 200); mpfr_init2 (ash, 200); mpfr_init2 (ath, 200); MPFR_SET_INF(t); if(MPFR_IS_NEG (t)) MPFR_CHANGE_SIGN(t); /******cosh********/ tester = mpfr_cosh(ch,t,MPFR_RNDD); if (!MPFR_IS_INF(ch) || MPFR_IS_NEG (ch) || tester!=0) { printf("cosh(INF) \n"); fail = 1; goto clean_up; } /******sinh********/ tester=mpfr_sinh(sh,t,MPFR_RNDD); if (!MPFR_IS_INF(sh) || MPFR_IS_NEG (sh) || tester!=0) { printf("sinh(INF) \n"); fail = 1; goto clean_up; } /******tanh********/ tester=mpfr_tanh(th,t,MPFR_RNDD); if (mpfr_cmp_ui(th,1) != 0 || tester!=0) { printf("tanh(INF) \n"); fail = 1; goto clean_up; } /******acosh********/ tester=mpfr_acosh(ach,t,MPFR_RNDD); if (!MPFR_IS_INF(ach) || MPFR_IS_NEG (ach) || tester!=0) { printf("acosh(INF) \n"); fail = 1; goto clean_up; } /******asinh********/ tester=mpfr_asinh(ash,t,MPFR_RNDD); if (!MPFR_IS_INF(ash) || MPFR_IS_NEG (ash) || tester!=0) { printf("asinh(INF) \n"); fail = 1; goto clean_up; } /******atanh********/ tester = mpfr_atanh (ath, t, MPFR_RNDD); if (!MPFR_IS_NAN(ath) || tester != 0) { printf("atanh(INF) \n"); fail = 1; goto clean_up; } MPFR_CHANGE_SIGN(t); /******cosh********/ tester=mpfr_cosh(ch,t,MPFR_RNDD); if (!MPFR_IS_INF(ch) || MPFR_IS_NEG (ch) || tester!=0) { printf("cosh(-INF) \n"); fail = 1; goto clean_up; } /******sinh********/ tester=mpfr_sinh(sh,t,MPFR_RNDD); if (!MPFR_IS_INF(sh) || MPFR_IS_POS (sh) || tester!=0) { printf("sinh(-INF) \n"); fail = 1; goto clean_up; } /******tanh********/ tester=mpfr_tanh(th,t,MPFR_RNDD); if (!mpfr_cmp_ui(th,-1) || tester!=0) { printf("tanh(-INF) \n"); fail = 1; goto clean_up; } /******acosh********/ tester=mpfr_acosh(ach,t,MPFR_RNDD); if (!MPFR_IS_NAN(ach) || tester!=0) { printf("acosh(-INF) \n"); fail = 1; goto clean_up; } /******asinh********/ tester=mpfr_asinh(ash,t,MPFR_RNDD); if (!MPFR_IS_INF(ash) || MPFR_IS_POS (ash) || tester!=0) { printf("asinh(-INF) \n"); fail = 1; goto clean_up; } /******atanh********/ tester = mpfr_atanh (ath, t, MPFR_RNDD); if (!MPFR_IS_NAN(ath) || tester != 0) { printf("atanh(-INF) \n"); fail = 1; goto clean_up; } clean_up: mpfr_clear(t); mpfr_clear(ch); mpfr_clear(sh); mpfr_clear(th); mpfr_clear(ach); mpfr_clear(ash); mpfr_clear(ath); return fail; }
static int check_zero (void) { mpfr_t t, ch,sh,th,ach,ash,ath; int tester; int fail = 0; mpfr_init2(t,200); mpfr_init2(ch,200); mpfr_init2(sh,200); mpfr_init2(th,200); mpfr_init2(ach,200); mpfr_init2(ash,200); mpfr_init2(ath,200); mpfr_set_ui(t,0,MPFR_RNDD); /******cosh********/ tester = mpfr_cosh (ch, t, MPFR_RNDD); if (mpfr_cmp_ui(ch, 1) || tester) { printf("cosh(0) \n"); fail = 1; goto clean_up; } /******sinh********/ tester = mpfr_sinh (sh, t, MPFR_RNDD); if (!MPFR_IS_ZERO(sh) || tester) { printf("sinh(0) \n"); fail = 1; goto clean_up; } /******tanh********/ tester = mpfr_tanh (th, t, MPFR_RNDD); if (!MPFR_IS_ZERO(th) || tester) { printf("tanh(0) \n"); fail = 1; goto clean_up; } /******acosh********/ tester=mpfr_acosh(ach,t,MPFR_RNDD); if (!MPFR_IS_NAN(ach) || tester) { printf("acosh(0) \n"); fail = 1; goto clean_up; } /******asinh********/ tester=mpfr_asinh(ash,t,MPFR_RNDD); if (!MPFR_IS_ZERO(ash) || tester) { printf("asinh(0) \n"); fail = 1; goto clean_up; } /******atanh********/ tester=mpfr_atanh(ath,t,MPFR_RNDD); if (!MPFR_IS_ZERO(ath) || tester) { printf("atanh(0) \n"); fail = 1; goto clean_up; } clean_up: mpfr_clear(t); mpfr_clear(ch); mpfr_clear(sh); mpfr_clear(th); mpfr_clear(ach); mpfr_clear(ash); mpfr_clear(ath); return fail; }
int mpfr_sinh (mpfr_ptr y, mpfr_srcptr xt, mpfr_rnd_t rnd_mode) { mpfr_t x; int inexact; MPFR_LOG_FUNC (("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (xt), mpfr_log_prec, xt, rnd_mode), ("y[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (y), mpfr_log_prec, y, inexact)); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (xt))) { if (MPFR_IS_NAN (xt)) { MPFR_SET_NAN (y); MPFR_RET_NAN; } else if (MPFR_IS_INF (xt)) { MPFR_SET_INF (y); MPFR_SET_SAME_SIGN (y, xt); MPFR_RET (0); } else /* xt is zero */ { MPFR_ASSERTD (MPFR_IS_ZERO (xt)); MPFR_SET_ZERO (y); /* sinh(0) = 0 */ MPFR_SET_SAME_SIGN (y, xt); MPFR_RET (0); } } /* sinh(x) = x + x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */ MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, xt, -2 * MPFR_GET_EXP(xt), 2, 1, rnd_mode, {}); MPFR_TMP_INIT_ABS (x, xt); { mpfr_t t, ti; mpfr_exp_t d; mpfr_prec_t Nt; /* Precision of the intermediary variable */ long int err; /* Precision of error */ MPFR_ZIV_DECL (loop); MPFR_SAVE_EXPO_DECL (expo); MPFR_GROUP_DECL (group); MPFR_SAVE_EXPO_MARK (expo); /* compute the precision of intermediary variable */ Nt = MAX (MPFR_PREC (x), MPFR_PREC (y)); /* the optimal number of bits : see algorithms.ps */ Nt = Nt + MPFR_INT_CEIL_LOG2 (Nt) + 4; /* If x is near 0, exp(x) - 1/exp(x) = 2*x+x^3/3+O(x^5) */ if (MPFR_GET_EXP (x) < 0) Nt -= 2*MPFR_GET_EXP (x); /* initialise of intermediary variables */ MPFR_GROUP_INIT_2 (group, Nt, t, ti); /* First computation of sinh */ MPFR_ZIV_INIT (loop, Nt); for (;;) { MPFR_BLOCK_DECL (flags); /* compute sinh */ MPFR_BLOCK (flags, mpfr_exp (t, x, MPFR_RNDD)); if (MPFR_OVERFLOW (flags)) /* exp(x) does overflow */ { /* sinh(x) = 2 * sinh(x/2) * cosh(x/2) */ mpfr_div_2ui (ti, x, 1, MPFR_RNDD); /* exact */ /* t <- cosh(x/2): error(t) <= 1 ulp(t) */ MPFR_BLOCK (flags, mpfr_cosh (t, ti, MPFR_RNDD)); if (MPFR_OVERFLOW (flags)) /* when x>1 we have |sinh(x)| >= cosh(x/2), so sinh(x) overflows too */ { inexact = mpfr_overflow (y, rnd_mode, MPFR_SIGN (xt)); MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_OVERFLOW); break; } /* ti <- sinh(x/2): , error(ti) <= 1 ulp(ti) cannot overflow because 0 < sinh(x) < cosh(x) when x > 0 */ mpfr_sinh (ti, ti, MPFR_RNDD); /* multiplication below, error(t) <= 5 ulp(t) */ MPFR_BLOCK (flags, mpfr_mul (t, t, ti, MPFR_RNDD)); if (MPFR_OVERFLOW (flags)) { inexact = mpfr_overflow (y, rnd_mode, MPFR_SIGN (xt)); MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_OVERFLOW); break; } /* doubling below, exact */ MPFR_BLOCK (flags, mpfr_mul_2ui (t, t, 1, MPFR_RNDN)); if (MPFR_OVERFLOW (flags)) { inexact = mpfr_overflow (y, rnd_mode, MPFR_SIGN (xt)); MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_OVERFLOW); break; } /* we have lost at most 3 bits of precision */ err = Nt - 3; if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, MPFR_PREC (y), rnd_mode))) { inexact = mpfr_set4 (y, t, rnd_mode, MPFR_SIGN (xt)); break; } err = Nt; /* double the precision */ } else { d = MPFR_GET_EXP (t); mpfr_ui_div (ti, 1, t, MPFR_RNDU); /* 1/exp(x) */ mpfr_sub (t, t, ti, MPFR_RNDN); /* exp(x) - 1/exp(x) */ mpfr_div_2ui (t, t, 1, MPFR_RNDN); /* 1/2(exp(x) - 1/exp(x)) */ /* it may be that t is zero (in fact, it can only occur when te=1, and thus ti=1 too) */ if (MPFR_IS_ZERO (t)) err = Nt; /* double the precision */ else { /* calculation of the error */ d = d - MPFR_GET_EXP (t) + 2; /* error estimate: err = Nt-(__gmpfr_ceil_log2(1+pow(2,d)));*/ err = Nt - (MAX (d, 0) + 1); if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, MPFR_PREC (y), rnd_mode))) { inexact = mpfr_set4 (y, t, rnd_mode, MPFR_SIGN (xt)); break; } } } /* actualisation of the precision */ Nt += err; MPFR_ZIV_NEXT (loop, Nt); MPFR_GROUP_REPREC_2 (group, Nt, t, ti); } MPFR_ZIV_FREE (loop); MPFR_GROUP_CLEAR (group); MPFR_SAVE_EXPO_FREE (expo); } return mpfr_check_range (y, inexact, rnd_mode); }
MpfrFloat MpfrFloat::cosh(const MpfrFloat& value) { MpfrFloat retval(MpfrFloat::kNoInitialization); mpfr_cosh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN); return retval; }
static void special (void) { mpfr_t x, y; int i; mpfr_init (x); mpfr_init (y); mpfr_set_nan (x); mpfr_cosh (y, x, GMP_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: cosh(NaN) != NaN\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_cosh (y, x, GMP_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error: cosh(+Inf) != +Inf\n"); exit (1); } mpfr_set_inf (x, -1); mpfr_cosh (y, x, GMP_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error: cosh(-Inf) != +Inf\n"); exit (1); } /* cosh(+/-0) = 1 */ mpfr_set_ui (x, 0, GMP_RNDN); mpfr_cosh (y, x, GMP_RNDN); if (mpfr_cmp_ui (y, 1)) { printf ("Error: cosh(+0) != 1\n"); exit (1); } mpfr_neg (x, x, GMP_RNDN); mpfr_cosh (y, x, GMP_RNDN); if (mpfr_cmp_ui (y, 1)) { printf ("Error: cosh(-0) != 1\n"); exit (1); } mpfr_set_prec (x, 32); mpfr_set_prec (y, 32); mpfr_set_str_binary (x, "0.1101110111111111001011101000101"); mpfr_set_str_binary (y, "1.0110011001110000101100011001001"); mpfr_cosh (x, x, GMP_RNDN); if (mpfr_cmp (x, y)) { printf ("Error: mpfr_cosh for prec=32 (1)\n"); exit (1); } mpfr_set_str_binary (x, "-0.1110111000011101010111100000101E-1"); mpfr_set_str_binary (y, "1.0001110000101111111111100110101"); mpfr_cosh (x, x, GMP_RNDN); if (mpfr_cmp (x, y)) { printf ("Error: mpfr_cosh for prec=32 (2)\n"); exit (1); } mpfr_set_prec (x, 2); mpfr_clear_flags (); mpfr_set_str_binary (x, "1E1000000000"); i = mpfr_cosh (x, x, GMP_RNDN); MPFR_ASSERTN (MPFR_IS_INF (x) && MPFR_SIGN (x) > 0); MPFR_ASSERTN (mpfr_overflow_p ()); MPFR_ASSERTN (i == 1); mpfr_clear_flags (); mpfr_set_str_binary (x, "-1E1000000000"); i = mpfr_cosh (x, x, GMP_RNDN); MPFR_ASSERTN (MPFR_IS_INF (x) && MPFR_SIGN (x) > 0); MPFR_ASSERTN (mpfr_overflow_p () && !mpfr_underflow_p ()); MPFR_ASSERTN (i == 1); mpfr_clear_flags (); mpfr_set_str_binary (x, "-1E1000000000"); i = mpfr_cosh (x, x, GMP_RNDD); MPFR_ASSERTN (!MPFR_IS_INF (x) && MPFR_SIGN (x) > 0); MPFR_ASSERTN (mpfr_overflow_p () && !mpfr_underflow_p ()); MPFR_ASSERTN (i == -1); mpfr_clear_flags (); mpfr_set_str_binary (x, "-1E1000000000"); i = mpfr_cosh (x, x, GMP_RNDU); MPFR_ASSERTN (MPFR_IS_INF (x) && MPFR_SIGN (x) > 0); MPFR_ASSERTN (mpfr_overflow_p () && !mpfr_underflow_p ()); MPFR_ASSERTN (i == 1); mpfr_clear (x); mpfr_clear (y); }
void bvisit(const Cosh &x) { apply(result_, *(x.get_arg())); mpfr_cosh(result_, result_, rnd_); }
int mpc_cos (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd) { mpfr_t x, y, z; mp_prec_t prec; int ok = 0; int inex_re, inex_im; /* special values */ if (!mpfr_number_p (MPC_RE (op)) || !mpfr_number_p (MPC_IM (op))) { if (mpfr_nan_p (MPC_RE (op))) { /* cos(NaN + i * NaN) = NaN + i * NaN */ /* cos(NaN - i * Inf) = +Inf + i * NaN */ /* cos(NaN + i * Inf) = +Inf + i * NaN */ /* cos(NaN - i * 0) = NaN - i * 0 */ /* cos(NaN + i * 0) = NaN + i * 0 */ /* cos(NaN + i * y) = NaN + i * NaN, when y != 0 */ if (mpfr_inf_p (MPC_IM (op))) mpfr_set_inf (MPC_RE (rop), +1); else mpfr_set_nan (MPC_RE (rop)); if (mpfr_zero_p (MPC_IM (op))) mpfr_set (MPC_IM (rop), MPC_IM (op), MPC_RND_IM (rnd)); else mpfr_set_nan (MPC_IM (rop)); } else if (mpfr_nan_p (MPC_IM (op))) { /* cos(-Inf + i * NaN) = NaN + i * NaN */ /* cos(+Inf + i * NaN) = NaN + i * NaN */ /* cos(-0 + i * NaN) = NaN - i * 0 */ /* cos(+0 + i * NaN) = NaN + i * 0 */ /* cos(x + i * NaN) = NaN + i * NaN, when x != 0 */ if (mpfr_zero_p (MPC_RE (op))) mpfr_set (MPC_IM (rop), MPC_RE (op), MPC_RND_IM (rnd)); else mpfr_set_nan (MPC_IM (rop)); mpfr_set_nan (MPC_RE (rop)); } else if (mpfr_inf_p (MPC_RE (op))) { /* cos(-Inf -i*Inf) = cos(+Inf +i*Inf) = -Inf +i*NaN */ /* cos(-Inf +i*Inf) = cos(+Inf -i*Inf) = +Inf +i*NaN */ /* cos(-Inf -i*0) = cos(+Inf +i*0) = NaN -i*0 */ /* cos(-Inf +i*0) = cos(+Inf -i*0) = NaN +i*0 */ /* cos(-Inf +i*y) = cos(+Inf +i*y) = NaN +i*NaN, when y != 0 */ /* SAME_SIGN is useful only if op == (+/-)Inf + i * (+/-)0, but, as MPC_RE(OP) might be erased (when ROP == OP), we compute it now */ const int same_sign = mpfr_signbit (MPC_RE (op)) == mpfr_signbit (MPC_IM (op)); if (mpfr_inf_p (MPC_IM (op))) mpfr_set_inf (MPC_RE (rop), (same_sign ? -1 : +1)); else mpfr_set_nan (MPC_RE (rop)); if (mpfr_zero_p (MPC_IM (op))) mpfr_setsign (MPC_IM (rop), MPC_IM (op), same_sign, MPC_RND_IM(rnd)); else mpfr_set_nan (MPC_IM (rop)); } else if (mpfr_zero_p (MPC_RE (op))) { /* cos(-0 -i*Inf) = cos(+0 +i*Inf) = +Inf -i*0 */ /* cos(-0 +i*Inf) = cos(+0 -i*Inf) = +Inf +i*0 */ const int same_sign = mpfr_signbit (MPC_RE (op)) == mpfr_signbit (MPC_IM (op)); mpfr_setsign (MPC_IM (rop), MPC_RE (op), same_sign, MPC_RND_IM (rnd)); mpfr_set_inf (MPC_RE (rop), +1); } else { /* cos(x -i*Inf) = +Inf*cos(x) +i*Inf*sin(x), when x != 0 */ /* cos(x +i*Inf) = +Inf*cos(x) -i*Inf*sin(x), when x != 0 */ mpfr_t c; mpfr_t s; mpfr_init (c); mpfr_init (s); mpfr_sin_cos (s, c, MPC_RE (op), GMP_RNDN); mpfr_set_inf (MPC_RE (rop), mpfr_sgn (c)); mpfr_set_inf (MPC_IM (rop), (mpfr_sgn (MPC_IM (op)) == mpfr_sgn (s) ? -1 : +1)); mpfr_clear (s); mpfr_clear (c); } return MPC_INEX (0, 0); /* always exact */ } if (mpfr_zero_p (MPC_RE (op))) { /* cos(-0 - i * y) = cos(+0 + i * y) = cosh(y) - i * 0 cos(-0 + i * y) = cos(+0 - i * y) = cosh(y) + i * 0, when y >= 0 */ /* When ROP == OP, the sign of 0 will be erased, so use it now */ const int imag_sign = mpfr_signbit (MPC_RE (op)) == mpfr_signbit (MPC_IM (op)); if (mpfr_zero_p (MPC_IM (op))) inex_re = mpfr_set_ui (MPC_RE (rop), 1, MPC_RND_RE (rnd)); else inex_re = mpfr_cosh (MPC_RE (rop), MPC_IM (op), MPC_RND_RE (rnd)); mpfr_set_ui (MPC_IM (rop), 0, MPC_RND_IM (rnd)); mpfr_setsign (MPC_IM (rop), MPC_IM (rop), imag_sign, MPC_RND_IM (rnd)); return MPC_INEX (inex_re, 0); } if (mpfr_zero_p (MPC_IM (op))) { /* cos(x +i*0) = cos(x) -i*0*sign(sin(x)) */ /* cos(x -i*0) = cos(x) +i*0*sign(sin(x)) */ mpfr_t sign; mpfr_init2 (sign, 2); mpfr_sin (sign, MPC_RE (op), GMP_RNDN); if (!mpfr_signbit (MPC_IM (op))) MPFR_CHANGE_SIGN (sign); inex_re = mpfr_cos (MPC_RE (rop), MPC_RE (op), MPC_RND_RE (rnd)); mpfr_set_ui (MPC_IM (rop), 0ul, GMP_RNDN); if (mpfr_signbit (sign)) MPFR_CHANGE_SIGN (MPC_IM (rop)); mpfr_clear (sign); return MPC_INEX (inex_re, 0); } /* ordinary (non-zero) numbers */ /* let op = a + i*b, then cos(op) = cos(a)*cosh(b) - i*sin(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(cos(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 = cos(a)*cosh(b)*(1+t)^3 with |t| <= 2^(-w), thus for w >= 2, r = cos(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 (x, 2); mpfr_init2 (y, 2); mpfr_init2 (z, 2); do { prec += mpc_ceil_log2 (prec) + 5; mpfr_set_prec (x, prec); mpfr_set_prec (y, prec); mpfr_set_prec (z, prec); mpfr_sin_cos (y, x, MPC_RE(op), GMP_RNDN); mpfr_cosh (z, MPC_IM(op), GMP_RNDN); mpfr_mul (x, x, z, GMP_RNDN); ok = mpfr_can_round (x, prec - 2, GMP_RNDN, GMP_RNDZ, MPFR_PREC(MPC_RE(rop)) + (MPC_RND_RE(rnd) == GMP_RNDN)); if (ok) /* compute imaginary part */ { mpfr_sinh (z, MPC_IM(op), GMP_RNDN); mpfr_mul (y, y, z, GMP_RNDN); mpfr_neg (y, y, GMP_RNDN); ok = mpfr_can_round (y, prec - 2, GMP_RNDN, GMP_RNDZ, MPFR_PREC(MPC_IM(rop)) + (MPC_RND_IM(rnd) == GMP_RNDN)); } } while (ok == 0); inex_re = mpfr_set (MPC_RE(rop), x, MPC_RND_RE(rnd)); inex_im = mpfr_set (MPC_IM(rop), y, MPC_RND_IM(rnd)); mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); return MPC_INEX (inex_re, inex_im); }