//------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_float::asinh() { #ifdef KNUMBER_USE_MPFR mpfr_t mpfr; mpfr_init_set_f(mpfr, mpf_, rounding_mode); mpfr_asinh(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< ::asinh>(x); #endif }
int mpc_asin (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd) { mpfr_prec_t p, p_re, p_im, incr_p = 0; mpfr_rnd_t rnd_re, rnd_im; mpc_t z1; int inex; /* special values */ if (mpfr_nan_p (mpc_realref (op)) || mpfr_nan_p (mpc_imagref (op))) { if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op))) { mpfr_set_nan (mpc_realref (rop)); mpfr_set_inf (mpc_imagref (rop), mpfr_signbit (mpc_imagref (op)) ? -1 : +1); } else if (mpfr_zero_p (mpc_realref (op))) { mpfr_set (mpc_realref (rop), mpc_realref (op), GMP_RNDN); mpfr_set_nan (mpc_imagref (rop)); } else { mpfr_set_nan (mpc_realref (rop)); mpfr_set_nan (mpc_imagref (rop)); } return 0; } if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op))) { int inex_re; if (mpfr_inf_p (mpc_realref (op))) { int inf_im = mpfr_inf_p (mpc_imagref (op)); inex_re = set_pi_over_2 (mpc_realref (rop), (mpfr_signbit (mpc_realref (op)) ? -1 : 1), MPC_RND_RE (rnd)); mpfr_set_inf (mpc_imagref (rop), (mpfr_signbit (mpc_imagref (op)) ? -1 : 1)); if (inf_im) mpfr_div_2ui (mpc_realref (rop), mpc_realref (rop), 1, GMP_RNDN); } else { mpfr_set_zero (mpc_realref (rop), (mpfr_signbit (mpc_realref (op)) ? -1 : 1)); inex_re = 0; mpfr_set_inf (mpc_imagref (rop), (mpfr_signbit (mpc_imagref (op)) ? -1 : 1)); } return MPC_INEX (inex_re, 0); } /* pure real argument */ if (mpfr_zero_p (mpc_imagref (op))) { int inex_re; int inex_im; int s_im; s_im = mpfr_signbit (mpc_imagref (op)); if (mpfr_cmp_ui (mpc_realref (op), 1) > 0) { if (s_im) inex_im = -mpfr_acosh (mpc_imagref (rop), mpc_realref (op), INV_RND (MPC_RND_IM (rnd))); else inex_im = mpfr_acosh (mpc_imagref (rop), mpc_realref (op), MPC_RND_IM (rnd)); inex_re = set_pi_over_2 (mpc_realref (rop), (mpfr_signbit (mpc_realref (op)) ? -1 : 1), MPC_RND_RE (rnd)); if (s_im) mpc_conj (rop, rop, MPC_RNDNN); } else if (mpfr_cmp_si (mpc_realref (op), -1) < 0) { mpfr_t minus_op_re; minus_op_re[0] = mpc_realref (op)[0]; MPFR_CHANGE_SIGN (minus_op_re); if (s_im) inex_im = -mpfr_acosh (mpc_imagref (rop), minus_op_re, INV_RND (MPC_RND_IM (rnd))); else inex_im = mpfr_acosh (mpc_imagref (rop), minus_op_re, MPC_RND_IM (rnd)); inex_re = set_pi_over_2 (mpc_realref (rop), (mpfr_signbit (mpc_realref (op)) ? -1 : 1), MPC_RND_RE (rnd)); if (s_im) mpc_conj (rop, rop, MPC_RNDNN); } else { inex_im = mpfr_set_ui (mpc_imagref (rop), 0, MPC_RND_IM (rnd)); if (s_im) mpfr_neg (mpc_imagref (rop), mpc_imagref (rop), GMP_RNDN); inex_re = mpfr_asin (mpc_realref (rop), mpc_realref (op), MPC_RND_RE (rnd)); } return MPC_INEX (inex_re, inex_im); } /* pure imaginary argument */ if (mpfr_zero_p (mpc_realref (op))) { int inex_im; int s; s = mpfr_signbit (mpc_realref (op)); mpfr_set_ui (mpc_realref (rop), 0, GMP_RNDN); if (s) mpfr_neg (mpc_realref (rop), mpc_realref (rop), GMP_RNDN); inex_im = mpfr_asinh (mpc_imagref (rop), mpc_imagref (op), MPC_RND_IM (rnd)); return MPC_INEX (0, inex_im); } /* regular complex: asin(z) = -i*log(i*z+sqrt(1-z^2)) */ p_re = mpfr_get_prec (mpc_realref(rop)); p_im = mpfr_get_prec (mpc_imagref(rop)); rnd_re = MPC_RND_RE(rnd); rnd_im = MPC_RND_IM(rnd); p = p_re >= p_im ? p_re : p_im; mpc_init2 (z1, p); while (1) { mpfr_exp_t ex, ey, err; p += mpc_ceil_log2 (p) + 3 + incr_p; /* incr_p is zero initially */ incr_p = p / 2; mpfr_set_prec (mpc_realref(z1), p); mpfr_set_prec (mpc_imagref(z1), p); /* z1 <- z^2 */ mpc_sqr (z1, op, MPC_RNDNN); /* err(x) <= 1/2 ulp(x), err(y) <= 1/2 ulp(y) */ /* z1 <- 1-z1 */ ex = mpfr_get_exp (mpc_realref(z1)); mpfr_ui_sub (mpc_realref(z1), 1, mpc_realref(z1), GMP_RNDN); mpfr_neg (mpc_imagref(z1), mpc_imagref(z1), GMP_RNDN); ex = ex - mpfr_get_exp (mpc_realref(z1)); ex = (ex <= 0) ? 0 : ex; /* err(x) <= 2^ex * ulp(x) */ ex = ex + mpfr_get_exp (mpc_realref(z1)) - p; /* err(x) <= 2^ex */ ey = mpfr_get_exp (mpc_imagref(z1)) - p - 1; /* err(y) <= 2^ey */ ex = (ex >= ey) ? ex : ey; /* err(x), err(y) <= 2^ex, i.e., the norm of the error is bounded by |h|<=2^(ex+1/2) */ /* z1 <- sqrt(z1): if z1 = z + h, then sqrt(z1) = sqrt(z) + h/2/sqrt(t) */ ey = mpfr_get_exp (mpc_realref(z1)) >= mpfr_get_exp (mpc_imagref(z1)) ? mpfr_get_exp (mpc_realref(z1)) : mpfr_get_exp (mpc_imagref(z1)); /* we have |z1| >= 2^(ey-1) thus 1/|z1| <= 2^(1-ey) */ mpc_sqrt (z1, z1, MPC_RNDNN); ex = (2 * ex + 1) - 2 - (ey - 1); /* |h^2/4/|t| <= 2^ex */ ex = (ex + 1) / 2; /* ceil(ex/2) */ /* express ex in terms of ulp(z1) */ ey = mpfr_get_exp (mpc_realref(z1)) <= mpfr_get_exp (mpc_imagref(z1)) ? mpfr_get_exp (mpc_realref(z1)) : mpfr_get_exp (mpc_imagref(z1)); ex = ex - ey + p; /* take into account the rounding error in the mpc_sqrt call */ err = (ex <= 0) ? 1 : ex + 1; /* err(x) <= 2^err * ulp(x), err(y) <= 2^err * ulp(y) */ /* z1 <- i*z + z1 */ ex = mpfr_get_exp (mpc_realref(z1)); ey = mpfr_get_exp (mpc_imagref(z1)); mpfr_sub (mpc_realref(z1), mpc_realref(z1), mpc_imagref(op), GMP_RNDN); mpfr_add (mpc_imagref(z1), mpc_imagref(z1), mpc_realref(op), GMP_RNDN); if (mpfr_cmp_ui (mpc_realref(z1), 0) == 0 || mpfr_cmp_ui (mpc_imagref(z1), 0) == 0) continue; ex -= mpfr_get_exp (mpc_realref(z1)); /* cancellation in x */ ey -= mpfr_get_exp (mpc_imagref(z1)); /* cancellation in y */ ex = (ex >= ey) ? ex : ey; /* maximum cancellation */ err += ex; err = (err <= 0) ? 1 : err + 1; /* rounding error in sub/add */ /* z1 <- log(z1): if z1 = z + h, then log(z1) = log(z) + h/t with |t| >= min(|z1|,|z|) */ ex = mpfr_get_exp (mpc_realref(z1)); ey = mpfr_get_exp (mpc_imagref(z1)); ex = (ex >= ey) ? ex : ey; err += ex - p; /* revert to absolute error <= 2^err */ mpc_log (z1, z1, GMP_RNDN); err -= ex - 1; /* 1/|t| <= 1/|z| <= 2^(1-ex) */ /* express err in terms of ulp(z1) */ ey = mpfr_get_exp (mpc_realref(z1)) <= mpfr_get_exp (mpc_imagref(z1)) ? mpfr_get_exp (mpc_realref(z1)) : mpfr_get_exp (mpc_imagref(z1)); err = err - ey + p; /* take into account the rounding error in the mpc_log call */ err = (err <= 0) ? 1 : err + 1; /* z1 <- -i*z1 */ mpfr_swap (mpc_realref(z1), mpc_imagref(z1)); mpfr_neg (mpc_imagref(z1), mpc_imagref(z1), GMP_RNDN); if (mpfr_can_round (mpc_realref(z1), p - err, GMP_RNDN, GMP_RNDZ, p_re + (rnd_re == GMP_RNDN)) && mpfr_can_round (mpc_imagref(z1), p - err, GMP_RNDN, GMP_RNDZ, p_im + (rnd_im == GMP_RNDN))) break; } inex = mpc_set (rop, z1, rnd); mpc_clear (z1); return inex; }
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; }
MpfrFloat MpfrFloat::asinh(const MpfrFloat& value) { MpfrFloat retval(MpfrFloat::kNoInitialization); mpfr_asinh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN); return retval; }
static void special (void) { mpfr_t x, y, z; mpfr_init (x); mpfr_init (y); MPFR_SET_INF(x); mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_asinh (x, y, MPFR_RNDN); if (MPFR_IS_INF(x) || MPFR_IS_NAN(x) ) { printf ("Inf flag not clears in asinh!\n"); exit (1); } MPFR_SET_NAN(x); mpfr_asinh (x, y, MPFR_RNDN); if (MPFR_IS_NAN(x) || MPFR_IS_INF(x)) { printf ("NAN flag not clears in asinh!\n"); exit (1); } /* asinh(+0) = +0, asinh(-0) = -0 */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_asinh (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) < 0) { printf ("Error: mpfr_asinh(+0) <> +0\n"); exit (1); } mpfr_neg (x, x, MPFR_RNDN); mpfr_asinh (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) > 0) { printf ("Error: mpfr_asinh(-0) <> -0\n"); exit (1); } MPFR_SET_NAN(x); mpfr_asinh (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: mpfr_asinh(NaN) <> NaN\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_asinh (y, x, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error: mpfr_asinh(+Inf) <> +Inf\n"); exit (1); } mpfr_set_inf (x, -1); mpfr_asinh (y, x, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) > 0) { printf ("Error: mpfr_asinh(-Inf) <> -Inf\n"); exit (1); } mpfr_set_prec (x, 32); mpfr_set_prec (y, 32); mpfr_set_str_binary (x, "0.1010100100111011001111100101E-1"); mpfr_asinh (x, x, MPFR_RNDN); mpfr_set_str_binary (y, "0.10100110010010101101010011011101E-1"); if (!mpfr_equal_p (x, y)) { printf ("Error: mpfr_asinh (1)\n"); exit (1); } mpfr_set_str_binary (x, "-.10110011011010111110010001100001"); mpfr_asinh (x, x, MPFR_RNDN); mpfr_set_str_binary (y, "-.10100111010000111001011100110011"); if (!mpfr_equal_p (x, y)) { printf ("Error: mpfr_asinh (2)\n"); exit (1); } mpfr_set_prec (x, 33); mpfr_set_prec (y, 43); mpfr_set_str_binary (x, "0.111001101100000110011001010000101"); mpfr_asinh (y, x, MPFR_RNDZ); mpfr_init2 (z, 43); mpfr_set_str_binary (z, "0.1100111101010101101010101110000001000111001"); if (!mpfr_equal_p (y, z)) { printf ("Error: mpfr_asinh (3)\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_set_prec (y, 2); mpfr_set_str (x, "1.8000000000009@-6", 16, MPFR_RNDN); mpfr_asinh (y, x, MPFR_RNDZ); mpfr_set_prec (z, 2); mpfr_set_str (z, "1.0@-6", 16, MPFR_RNDN); if (!mpfr_equal_p (y, z)) { printf ("Error: mpfr_asinh (4)\n"); exit (1); } mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); }
int mpc_acos (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd) { int inex_re, inex_im, inex; mpfr_prec_t p_re, p_im, p; mpc_t z1; mpfr_t pi_over_2; mpfr_exp_t e1, e2; mpfr_rnd_t rnd_im; mpc_rnd_t rnd1; inex_re = 0; inex_im = 0; /* special values */ if (mpfr_nan_p (mpc_realref (op)) || mpfr_nan_p (mpc_imagref (op))) { if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op))) { mpfr_set_inf (mpc_imagref (rop), mpfr_signbit (mpc_imagref (op)) ? +1 : -1); mpfr_set_nan (mpc_realref (rop)); } else if (mpfr_zero_p (mpc_realref (op))) { inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd)); mpfr_set_nan (mpc_imagref (rop)); } else { mpfr_set_nan (mpc_realref (rop)); mpfr_set_nan (mpc_imagref (rop)); } return MPC_INEX (inex_re, 0); } if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op))) { if (mpfr_inf_p (mpc_realref (op))) { if (mpfr_inf_p (mpc_imagref (op))) { if (mpfr_sgn (mpc_realref (op)) > 0) { inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd)); mpfr_div_2ui (mpc_realref (rop), mpc_realref (rop), 1, GMP_RNDN); } else { /* the real part of the result is 3*pi/4 a = o(pi) error(a) < 1 ulp(a) b = o(3*a) error(b) < 2 ulp(b) c = b/4 exact thus 1 bit is lost */ mpfr_t x; mpfr_prec_t prec; int ok; mpfr_init (x); prec = mpfr_get_prec (mpc_realref (rop)); p = prec; do { p += mpc_ceil_log2 (p); mpfr_set_prec (x, p); mpfr_const_pi (x, GMP_RNDD); mpfr_mul_ui (x, x, 3, GMP_RNDD); ok = mpfr_can_round (x, p - 1, GMP_RNDD, MPC_RND_RE (rnd), prec+(MPC_RND_RE (rnd) == GMP_RNDN)); } while (ok == 0); inex_re = mpfr_div_2ui (mpc_realref (rop), x, 2, MPC_RND_RE (rnd)); mpfr_clear (x); } } else { if (mpfr_sgn (mpc_realref (op)) > 0) mpfr_set_ui (mpc_realref (rop), 0, GMP_RNDN); else inex_re = mpfr_const_pi (mpc_realref (rop), MPC_RND_RE (rnd)); } } else inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd)); mpfr_set_inf (mpc_imagref (rop), mpfr_signbit (mpc_imagref (op)) ? +1 : -1); return MPC_INEX (inex_re, 0); } /* pure real argument */ if (mpfr_zero_p (mpc_imagref (op))) { int s_im; s_im = mpfr_signbit (mpc_imagref (op)); if (mpfr_cmp_ui (mpc_realref (op), 1) > 0) { if (s_im) inex_im = mpfr_acosh (mpc_imagref (rop), mpc_realref (op), MPC_RND_IM (rnd)); else inex_im = -mpfr_acosh (mpc_imagref (rop), mpc_realref (op), INV_RND (MPC_RND_IM (rnd))); mpfr_set_ui (mpc_realref (rop), 0, GMP_RNDN); } else if (mpfr_cmp_si (mpc_realref (op), -1) < 0) { mpfr_t minus_op_re; minus_op_re[0] = mpc_realref (op)[0]; MPFR_CHANGE_SIGN (minus_op_re); if (s_im) inex_im = mpfr_acosh (mpc_imagref (rop), minus_op_re, MPC_RND_IM (rnd)); else inex_im = -mpfr_acosh (mpc_imagref (rop), minus_op_re, INV_RND (MPC_RND_IM (rnd))); inex_re = mpfr_const_pi (mpc_realref (rop), MPC_RND_RE (rnd)); } else { inex_re = mpfr_acos (mpc_realref (rop), mpc_realref (op), MPC_RND_RE (rnd)); mpfr_set_ui (mpc_imagref (rop), 0, MPC_RND_IM (rnd)); } if (!s_im) mpc_conj (rop, rop, MPC_RNDNN); return MPC_INEX (inex_re, inex_im); } /* pure imaginary argument */ if (mpfr_zero_p (mpc_realref (op))) { inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd)); inex_im = -mpfr_asinh (mpc_imagref (rop), mpc_imagref (op), INV_RND (MPC_RND_IM (rnd))); mpc_conj (rop,rop, MPC_RNDNN); return MPC_INEX (inex_re, inex_im); } /* regular complex argument: acos(z) = Pi/2 - asin(z) */ p_re = mpfr_get_prec (mpc_realref(rop)); p_im = mpfr_get_prec (mpc_imagref(rop)); p = p_re; mpc_init3 (z1, p, p_im); /* we round directly the imaginary part to p_im, with rounding mode opposite to rnd_im */ rnd_im = MPC_RND_IM(rnd); /* the imaginary part of asin(z) has the same sign as Im(z), thus if Im(z) > 0 and rnd_im = RNDZ, we want to round the Im(asin(z)) to -Inf so that -Im(asin(z)) is rounded to zero */ if (rnd_im == GMP_RNDZ) rnd_im = mpfr_sgn (mpc_imagref(op)) > 0 ? GMP_RNDD : GMP_RNDU; else rnd_im = rnd_im == GMP_RNDU ? GMP_RNDD : rnd_im == GMP_RNDD ? GMP_RNDU : rnd_im; /* both RNDZ and RNDA map to themselves for -asin(z) */ rnd1 = MPC_RND (GMP_RNDN, rnd_im); mpfr_init2 (pi_over_2, p); for (;;) { p += mpc_ceil_log2 (p) + 3; mpfr_set_prec (mpc_realref(z1), p); mpfr_set_prec (pi_over_2, p); set_pi_over_2 (pi_over_2, +1, GMP_RNDN); e1 = 1; /* Exp(pi_over_2) */ inex = mpc_asin (z1, op, rnd1); /* asin(z) */ MPC_ASSERT (mpfr_sgn (mpc_imagref(z1)) * mpfr_sgn (mpc_imagref(op)) > 0); inex_im = MPC_INEX_IM(inex); /* inex_im is in {-1, 0, 1} */ e2 = mpfr_get_exp (mpc_realref(z1)); mpfr_sub (mpc_realref(z1), pi_over_2, mpc_realref(z1), GMP_RNDN); if (!mpfr_zero_p (mpc_realref(z1))) { /* the error on x=Re(z1) is bounded by 1/2 ulp(x) + 2^(e1-p-1) + 2^(e2-p-1) */ e1 = e1 >= e2 ? e1 + 1 : e2 + 1; /* the error on x is bounded by 1/2 ulp(x) + 2^(e1-p-1) */ e1 -= mpfr_get_exp (mpc_realref(z1)); /* the error on x is bounded by 1/2 ulp(x) [1 + 2^e1] */ e1 = e1 <= 0 ? 0 : e1; /* the error on x is bounded by 2^e1 * ulp(x) */ mpfr_neg (mpc_imagref(z1), mpc_imagref(z1), GMP_RNDN); /* exact */ inex_im = -inex_im; if (mpfr_can_round (mpc_realref(z1), p - e1, GMP_RNDN, GMP_RNDZ, p_re + (MPC_RND_RE(rnd) == GMP_RNDN))) break; } } inex = mpc_set (rop, z1, rnd); inex_re = MPC_INEX_RE(inex); mpc_clear (z1); mpfr_clear (pi_over_2); return MPC_INEX(inex_re, inex_im); }
void bvisit(const ASinh &x) { apply(result_, *(x.get_arg())); mpfr_asinh(result_, result_, rnd_); }