int mpc_atanh (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd) { /* atanh(op) = -i*atan(i*op) */ int inex; mpfr_t tmp; mpc_t z, a; MPC_RE (z)[0] = MPC_IM (op)[0]; MPC_IM (z)[0] = MPC_RE (op)[0]; MPFR_CHANGE_SIGN (MPC_RE (z)); /* Note reversal of precisions due to later multiplication by -i */ mpc_init3 (a, MPC_PREC_IM(rop), MPC_PREC_RE(rop)); inex = mpc_atan (a, z, RNDC (INV_RND (MPC_RND_IM (rnd)), MPC_RND_RE (rnd))); /* change a to -i*a, i.e., x+i*y to y-i*x */ tmp[0] = MPC_RE (a)[0]; MPC_RE (a)[0] = MPC_IM (a)[0]; MPC_IM (a)[0] = tmp[0]; MPFR_CHANGE_SIGN (MPC_IM (a)); mpc_set (rop, a, rnd); mpc_clear (a); return MPC_INEX (MPC_INEX_IM (inex), -MPC_INEX_RE (inex)); }
int mpc_asinh (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd) { /* asinh(op) = -i*asin(i*op) */ int inex; mpc_t z, a; mpfr_t tmp; /* z = i*op */ MPC_RE (z)[0] = MPC_IM (op)[0]; MPC_IM (z)[0] = MPC_RE (op)[0]; MPFR_CHANGE_SIGN (MPC_RE (z)); /* Note reversal of precisions due to later multiplication by -i */ mpc_init3 (a, MPC_PREC_IM(rop), MPC_PREC_RE(rop)); inex = mpc_asin (a, z, RNDC (INV_RND (MPC_RND_IM (rnd)), MPC_RND_RE (rnd))); /* if a = asin(i*op) = x+i*y, and we want y-i*x */ /* change a to -i*a */ tmp[0] = MPC_RE (a)[0]; MPC_RE (a)[0] = MPC_IM (a)[0]; MPC_IM (a)[0] = tmp[0]; MPFR_CHANGE_SIGN (MPC_IM (a)); mpc_set (rop, a, MPC_RNDNN); /* exact */ mpc_clear (a); return MPC_INEX (MPC_INEX_IM (inex), -MPC_INEX_RE (inex)); }
static int mpc_sin_cos_real (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 real */ { int inex_sin_re = 0, inex_cos_re = 0; /* Until further notice, assume computations exact; in particular, by definition, for not computed values. */ mpfr_t s, c; int inex_s, inex_c; int sign_im_op = mpfr_signbit (MPC_IM (op)); /* sin(x +-0*i) = sin(x) +-0*i*sign(cos(x)) */ /* cos(x +-i*0) = cos(x) -+i*0*sign(sin(x)) */ if (rop_sin != 0) mpfr_init2 (s, MPC_PREC_RE (rop_sin)); else mpfr_init2 (s, 2); /* We need only the sign. */ if (rop_cos != NULL) mpfr_init2 (c, MPC_PREC_RE (rop_cos)); else mpfr_init2 (c, 2); inex_s = mpfr_sin (s, MPC_RE (op), MPC_RND_RE (rnd_sin)); inex_c = mpfr_cos (c, MPC_RE (op), MPC_RND_RE (rnd_cos)); /* We cannot use mpfr_sin_cos since we may need two distinct rounding modes and the exact return values. If we need only the sign, an arbitrary rounding mode will work. */ if (rop_sin != NULL) { mpfr_set (MPC_RE (rop_sin), s, GMP_RNDN); /* exact */ inex_sin_re = inex_s; mpfr_set_ui (MPC_IM (rop_sin), 0ul, GMP_RNDN); if ( ( sign_im_op && !mpfr_signbit (c)) || (!sign_im_op && mpfr_signbit (c))) MPFR_CHANGE_SIGN (MPC_IM (rop_sin)); /* FIXME: simpler implementation with mpfr-3: mpfr_set_zero (MPC_IM (rop_sin), ( ( mpfr_signbit (MPC_IM(op)) && !mpfr_signbit(c)) || (!mpfr_signbit (MPC_IM(op)) && mpfr_signbit(c)) ? -1 : 1); there is no need to use the variable sign_im_op then, needed now in the case rop_sin == op */ } if (rop_cos != NULL) { mpfr_set (MPC_RE (rop_cos), c, GMP_RNDN); /* exact */ inex_cos_re = inex_c; mpfr_set_ui (MPC_IM (rop_cos), 0ul, GMP_RNDN); if ( ( sign_im_op && mpfr_signbit (s)) || (!sign_im_op && !mpfr_signbit (s))) MPFR_CHANGE_SIGN (MPC_IM (rop_cos)); /* FIXME: see previous MPFR_CHANGE_SIGN */ } mpfr_clear (s); mpfr_clear (c); return MPC_INEX12 (MPC_INEX (inex_sin_re, 0), MPC_INEX (inex_cos_re, 0)); }
int mpc_mul_i (mpc_ptr a, mpc_srcptr b, int sign, mpc_rnd_t rnd) /* if sign is >= 0, multiply by i, otherwise by -i */ { int inex_re, inex_im; mpfr_t tmp; /* Treat the most probable case of compatible precisions first */ if ( MPFR_PREC (MPC_RE (b)) == MPFR_PREC (MPC_IM (a)) && MPFR_PREC (MPC_IM (b)) == MPFR_PREC (MPC_RE (a))) { if (a == b) mpfr_swap (MPC_RE (a), MPC_IM (a)); else { mpfr_set (MPC_RE (a), MPC_IM (b), GMP_RNDN); mpfr_set (MPC_IM (a), MPC_RE (b), GMP_RNDN); } if (sign >= 0) MPFR_CHANGE_SIGN (MPC_RE (a)); else MPFR_CHANGE_SIGN (MPC_IM (a)); inex_re = 0; inex_im = 0; } else { if (a == b) { mpfr_init2 (tmp, MPFR_PREC (MPC_RE (a))); if (sign >= 0) { inex_re = mpfr_neg (tmp, MPC_IM (b), MPC_RND_RE (rnd)); inex_im = mpfr_set (MPC_IM (a), MPC_RE (b), MPC_RND_IM (rnd)); } else { inex_re = mpfr_set (tmp, MPC_IM (b), MPC_RND_RE (rnd)); inex_im = mpfr_neg (MPC_IM (a), MPC_RE (b), MPC_RND_IM (rnd)); } mpfr_clear (MPC_RE (a)); MPC_RE (a)[0] = tmp [0]; } else if (sign >= 0) { inex_re = mpfr_neg (MPC_RE (a), MPC_IM (b), MPC_RND_RE (rnd)); inex_im = mpfr_set (MPC_IM (a), MPC_RE (b), MPC_RND_IM (rnd)); } else { inex_re = mpfr_set (MPC_RE (a), MPC_IM (b), MPC_RND_RE (rnd)); inex_im = mpfr_neg (MPC_IM (a), MPC_RE (b), MPC_RND_IM (rnd)); } } return MPC_INEX(inex_re, inex_im); }
int mpc_acosh (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd) { /* acosh(z) = NaN + i*NaN, if z=0+i*NaN -i*acos(z), if sign(Im(z)) = - i*acos(z), if sign(Im(z)) = + http://functions.wolfram.com/ElementaryFunctions/ArcCosh/27/02/03/01/01/ */ mpc_t a; mpfr_t tmp; int inex; if (mpfr_zero_p (MPC_RE (op)) && mpfr_nan_p (MPC_IM (op))) { mpfr_set_nan (MPC_RE (rop)); mpfr_set_nan (MPC_IM (rop)); return 0; } /* Note reversal of precisions due to later multiplication by i or -i */ mpc_init3 (a, MPC_PREC_IM(rop), MPC_PREC_RE(rop)); if (mpfr_signbit (MPC_IM (op))) { inex = mpc_acos (a, op, RNDC (INV_RND (MPC_RND_IM (rnd)), MPC_RND_RE (rnd))); /* change a to -i*a, i.e., -y+i*x to x+i*y */ tmp[0] = MPC_RE (a)[0]; MPC_RE (a)[0] = MPC_IM (a)[0]; MPC_IM (a)[0] = tmp[0]; MPFR_CHANGE_SIGN (MPC_IM (a)); inex = MPC_INEX (MPC_INEX_IM (inex), -MPC_INEX_RE (inex)); } else { inex = mpc_acos (a, op, RNDC (MPC_RND_IM (rnd), INV_RND(MPC_RND_RE (rnd)))); /* change a to i*a, i.e., y-i*x to x+i*y */ tmp[0] = MPC_RE (a)[0]; MPC_RE (a)[0] = MPC_IM (a)[0]; MPC_IM (a)[0] = tmp[0]; MPFR_CHANGE_SIGN (MPC_RE (a)); inex = MPC_INEX (-MPC_INEX_IM (inex), MPC_INEX_RE (inex)); } mpc_set (rop, a, rnd); mpc_clear (a); return inex; }
int mpfr_set_underflow (mpfr_ptr x, mp_rnd_t rnd_mode, int sign) { int inex; MPFR_CLEAR_FLAGS(x); if ((rnd_mode == GMP_RNDU && sign > 0) || (rnd_mode == GMP_RNDD && sign < 0)) { mp_size_t xn; mp_limb_t *xp; MPFR_EXP(x) = __mpfr_emin; xn = (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB; xp = MPFR_MANT(x); xp[xn] = GMP_LIMB_HIGHBIT; MPN_ZERO(xp, xn); inex = 1; } else { MPFR_SET_ZERO(x); inex = -1; } if (MPFR_SIGN(x) != sign) MPFR_CHANGE_SIGN(x); __mpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW; return sign > 0 ? inex : -inex; }
int mpfr_set_overflow (mpfr_ptr x, mp_rnd_t rnd_mode, int sign) { int inex; MPFR_CLEAR_FLAGS(x); if ((rnd_mode == GMP_RNDU && sign < 0) || (rnd_mode == GMP_RNDD && sign > 0)) { mp_size_t xn, i; int sh; mp_limb_t *xp; MPFR_EXP(x) = __mpfr_emax; xn = 1 + (MPFR_PREC(x) - 1) / BITS_PER_MP_LIMB; sh = xn * BITS_PER_MP_LIMB - MPFR_PREC(x); xp = MPFR_MANT(x); xp[0] = MP_LIMB_T_MAX << sh; for (i = 1; i < xn; i++) xp[i] = MP_LIMB_T_MAX; inex = -1; } else { MPFR_SET_INF(x); inex = 1; } if (MPFR_SIGN(x) != sign) MPFR_CHANGE_SIGN(x); __mpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW; return sign > 0 ? inex : -inex; }
/* Input: p - an integer Output: fills tc[1..p], tc[i] = bernoulli(2i)/(2i)! tc[1]=1/12, tc[2]=-1/720, tc[3]=1/30240, ... */ static void mpfr_zeta_c (int p, mpfr_t *tc) { mpfr_t d; int k, l; if (p > 0) { mpfr_init2 (d, MPFR_PREC (tc[1])); mpfr_div_ui (tc[1], __gmpfr_one, 12, GMP_RNDN); for (k = 2; k <= p; k++) { mpfr_set_ui (d, k-1, GMP_RNDN); mpfr_div_ui (d, d, 12*k+6, GMP_RNDN); for (l=2; l < k; l++) { mpfr_div_ui (d, d, 4*(2*k-2*l+3)*(2*k-2*l+2), GMP_RNDN); mpfr_add (d, d, tc[l], GMP_RNDN); } mpfr_div_ui (tc[k], d, 24, GMP_RNDN); MPFR_CHANGE_SIGN (tc[k]); } mpfr_clear (d); } }
int mpfr_neg (mpfr_ptr a, mpfr_srcptr b, mp_rnd_t rnd_mode) { if (a != b) return mpfr_set4 (a, b, rnd_mode, -MPFR_SIGN(b)); else { MPFR_CHANGE_SIGN(a); MPFR_RET(0); } }
int mpfr_set_si (mpfr_ptr x, long i, mp_rnd_t rnd_mode) { int inex; mp_size_t xn; unsigned int cnt, nbits; mp_limb_t ai, *xp; MPFR_CLEAR_FLAGS(x); if (i == 0) { MPFR_SET_ZERO(x); MPFR_SET_POS(x); MPFR_RET(0); } xn = (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB; ai = SAFE_ABS(long, i); count_leading_zeros(cnt, ai); xp = MPFR_MANT(x); xp[xn] = ai << cnt; /* don't forget to put zero in lower limbs */ MPN_ZERO(xp, xn); /* set sign */ if ((i < 0) ^ (MPFR_SIGN(x) < 0)) MPFR_CHANGE_SIGN(x); MPFR_EXP(x) = nbits = BITS_PER_MP_LIMB - cnt; inex = mpfr_check_range(x, rnd_mode); if (inex) return inex; /* underflow or overflow */ /* round if MPFR_PREC(x) smaller than length of i */ if (MPFR_PREC(x) < nbits) { int carry; carry = mpfr_round_raw(xp+xn, xp+xn, nbits, (i < 0), MPFR_PREC(x), rnd_mode, &inex); if (carry) { mp_exp_t exp = MPFR_EXP(x); if (exp == __mpfr_emax) return mpfr_set_overflow(x, rnd_mode, (i < 0 ? -1 : 1)); MPFR_EXP(x)++; xp[xn] = GMP_LIMB_HIGHBIT; } } MPFR_RET(inex); }
int mpfr_si_sub (mpfr_ptr y, long int u, mpfr_srcptr x, mpfr_rnd_t rnd_mode) { if (u >= 0) return mpfr_ui_sub (y, u, x, rnd_mode); else { int res = -mpfr_add_ui (y, x, -u, MPFR_INVERT_RND (rnd_mode)); MPFR_CHANGE_SIGN (y); return res; } }
int mpfr_mul_si (mpfr_ptr y, mpfr_srcptr x, long int u, mpfr_rnd_t rnd_mode) { int res; if (u >= 0) res = mpfr_mul_ui (y, x, u, rnd_mode); else { res = -mpfr_mul_ui (y, x, -u, MPFR_INVERT_RND (rnd_mode)); MPFR_CHANGE_SIGN (y); } return res; }
int mpc_cosh (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd) { /* cosh(op) = cos(i*op) */ mpc_t z; /* z = i*op without copying significand */ MPC_RE (z)[0] = MPC_IM (op)[0]; MPC_IM (z)[0] = MPC_RE (op)[0]; MPFR_CHANGE_SIGN (MPC_RE (z)); return mpc_cos (rop, z, rnd); }
int mpfr_set_sj_2exp (mpfr_t x, intmax_t j, intmax_t e, mp_rnd_t rnd) { if (j>=0) return mpfr_set_uj_2exp (x, j, e, rnd); else { int inex; inex = mpfr_set_uj_2exp (x, - (uintmax_t) j, e, MPFR_INVERT_RND (rnd)); MPFR_CHANGE_SIGN (x); return -inex; } }
int mpfr_si_div (mpfr_ptr y, long int u, mpfr_srcptr x,mp_rnd_t rnd_mode) { int res; if (u >= 0) res = mpfr_ui_div (y, u, x, rnd_mode); else { res = -mpfr_ui_div (y, -u, x, MPFR_INVERT_RND(rnd_mode)); MPFR_CHANGE_SIGN (y); } return res; }
int mpfr_neg (mpfr_ptr a, mpfr_srcptr b, mpfr_rnd_t rnd_mode) { if (MPFR_UNLIKELY(a != b)) return mpfr_set4 (a, b, rnd_mode, -MPFR_SIGN(b)); else if (MPFR_UNLIKELY(MPFR_IS_NAN (b))) { MPFR_RET_NAN; } else { MPFR_CHANGE_SIGN(a); MPFR_RET(0); } }
/* set f to the integer z */ int mpfr_set_z (mpfr_ptr f, mpz_srcptr z, mp_rnd_t rnd_mode) { mp_size_t fn, zn, dif; int k, sign_z, inex; mp_limb_t *fp, *zp; mp_exp_t exp; MPFR_CLEAR_FLAGS (f); /* z cannot be NaN nor Inf */ sign_z = mpz_cmp_ui (z, 0); if (sign_z == 0) { MPFR_SET_ZERO(f); MPFR_SET_POS(f); MPFR_RET(0); } fp = MPFR_MANT(f); fn = 1 + (MPFR_PREC(f) - 1) / BITS_PER_MP_LIMB; zn = ABS(SIZ(z)); dif = zn - fn; zp = PTR(z); count_leading_zeros(k, zp[zn-1]); exp = (mp_prec_t) zn * BITS_PER_MP_LIMB - k; /* The exponent will be exp or exp + 1 (due to rounding) */ if (exp > __mpfr_emax) return mpfr_set_overflow(f, rnd_mode, sign_z); if (exp + 1 < __mpfr_emin) return mpfr_set_underflow(f, rnd_mode, sign_z); if (MPFR_SIGN(f) * sign_z < 0) MPFR_CHANGE_SIGN(f); if (dif >= 0) { mp_limb_t cc; int sh; /* number has to be truncated */ if (k != 0) { mpn_lshift(fp, zp + dif, fn, k); if (dif != 0) fp[0] += zp[dif - 1] >> (BITS_PER_MP_LIMB - k); }
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 pi_div_2ui (mpfr_ptr dest, int i, int neg, mpfr_rnd_t rnd_mode) { int inexact; MPFR_SAVE_EXPO_DECL (expo); MPFR_SAVE_EXPO_MARK (expo); if (neg) /* -PI/2^i */ { inexact = - mpfr_const_pi (dest, MPFR_INVERT_RND (rnd_mode)); MPFR_CHANGE_SIGN (dest); } else /* PI/2^i */ { inexact = mpfr_const_pi (dest, rnd_mode); } mpfr_div_2ui (dest, dest, i, rnd_mode); /* exact */ MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (dest, inexact, rnd_mode); }
int mpfr_asin (mpfr_ptr asin, mpfr_srcptr x, mpfr_rnd_t rnd_mode) { mpfr_t xp; int compared, inexact; mpfr_prec_t prec; mpfr_exp_t xp_exp; MPFR_SAVE_EXPO_DECL (expo); MPFR_ZIV_DECL (loop); MPFR_LOG_FUNC ( ("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode), ("asin[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (asin), mpfr_log_prec, asin, inexact)); /* Special cases */ if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) { if (MPFR_IS_NAN (x) || MPFR_IS_INF (x)) { MPFR_SET_NAN (asin); MPFR_RET_NAN; } else /* x = 0 */ { MPFR_ASSERTD (MPFR_IS_ZERO (x)); MPFR_SET_ZERO (asin); MPFR_SET_SAME_SIGN (asin, x); MPFR_RET (0); /* exact result */ } } /* asin(x) = x + x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */ MPFR_FAST_COMPUTE_IF_SMALL_INPUT (asin, x, -2 * MPFR_GET_EXP (x), 2, 1, rnd_mode, {}); /* Set x_p=|x| (x is a normal number) */ mpfr_init2 (xp, MPFR_PREC (x)); inexact = mpfr_abs (xp, x, MPFR_RNDN); MPFR_ASSERTD (inexact == 0); compared = mpfr_cmp_ui (xp, 1); MPFR_SAVE_EXPO_MARK (expo); if (MPFR_UNLIKELY (compared >= 0)) { mpfr_clear (xp); if (compared > 0) /* asin(x) = NaN for |x| > 1 */ { MPFR_SAVE_EXPO_FREE (expo); MPFR_SET_NAN (asin); MPFR_RET_NAN; } else /* x = 1 or x = -1 */ { if (MPFR_IS_POS (x)) /* asin(+1) = Pi/2 */ inexact = mpfr_const_pi (asin, rnd_mode); else /* asin(-1) = -Pi/2 */ { inexact = -mpfr_const_pi (asin, MPFR_INVERT_RND(rnd_mode)); MPFR_CHANGE_SIGN (asin); } mpfr_div_2ui (asin, asin, 1, rnd_mode); } } else { /* Compute exponent of 1 - ABS(x) */ mpfr_ui_sub (xp, 1, xp, MPFR_RNDD); MPFR_ASSERTD (MPFR_GET_EXP (xp) <= 0); MPFR_ASSERTD (MPFR_GET_EXP (x) <= 0); xp_exp = 2 - MPFR_GET_EXP (xp); /* Set up initial prec */ prec = MPFR_PREC (asin) + 10 + xp_exp; /* use asin(x) = atan(x/sqrt(1-x^2)) */ MPFR_ZIV_INIT (loop, prec); for (;;) { mpfr_set_prec (xp, prec); mpfr_sqr (xp, x, MPFR_RNDN); mpfr_ui_sub (xp, 1, xp, MPFR_RNDN); mpfr_sqrt (xp, xp, MPFR_RNDN); mpfr_div (xp, x, xp, MPFR_RNDN); mpfr_atan (xp, xp, MPFR_RNDN); if (MPFR_LIKELY (MPFR_CAN_ROUND (xp, prec - xp_exp, MPFR_PREC (asin), rnd_mode))) break; MPFR_ZIV_NEXT (loop, prec); } MPFR_ZIV_FREE (loop); inexact = mpfr_set (asin, xp, rnd_mode); mpfr_clear (xp); } MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (asin, inexact, rnd_mode); }
int mpfr_cbrt (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode) { mpz_t m; mpfr_exp_t e, r, sh; mpfr_prec_t n, size_m, tmp; int inexact, negative; MPFR_SAVE_EXPO_DECL (expo); MPFR_LOG_FUNC ( ("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode), ("y[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (y), mpfr_log_prec, y, inexact)); /* special values */ if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) { if (MPFR_IS_NAN (x)) { MPFR_SET_NAN (y); MPFR_RET_NAN; } else if (MPFR_IS_INF (x)) { MPFR_SET_INF (y); MPFR_SET_SAME_SIGN (y, x); MPFR_RET (0); } /* case 0: cbrt(+/- 0) = +/- 0 */ else /* x is necessarily 0 */ { MPFR_ASSERTD (MPFR_IS_ZERO (x)); MPFR_SET_ZERO (y); MPFR_SET_SAME_SIGN (y, x); MPFR_RET (0); } } /* General case */ MPFR_SAVE_EXPO_MARK (expo); mpz_init (m); e = mpfr_get_z_2exp (m, x); /* x = m * 2^e */ if ((negative = MPFR_IS_NEG(x))) mpz_neg (m, m); r = e % 3; if (r < 0) r += 3; /* x = (m*2^r) * 2^(e-r) = (m*2^r) * 2^(3*q) */ MPFR_MPZ_SIZEINBASE2 (size_m, m); n = MPFR_PREC (y) + (rnd_mode == MPFR_RNDN); /* we want 3*n-2 <= size_m + 3*sh + r <= 3*n i.e. 3*sh + size_m + r <= 3*n */ sh = (3 * (mpfr_exp_t) n - (mpfr_exp_t) size_m - r) / 3; sh = 3 * sh + r; if (sh >= 0) { mpz_mul_2exp (m, m, sh); e = e - sh; } else if (r > 0) { mpz_mul_2exp (m, m, r); e = e - r; } /* invariant: x = m*2^e, with e divisible by 3 */ /* we reuse the variable m to store the cube root, since it is not needed any more: we just need to know if the root is exact */ inexact = mpz_root (m, m, 3) == 0; MPFR_MPZ_SIZEINBASE2 (tmp, m); sh = tmp - n; if (sh > 0) /* we have to flush to 0 the last sh bits from m */ { inexact = inexact || ((mpfr_exp_t) mpz_scan1 (m, 0) < sh); mpz_fdiv_q_2exp (m, m, sh); e += 3 * sh; } if (inexact) { if (negative) rnd_mode = MPFR_INVERT_RND (rnd_mode); if (rnd_mode == MPFR_RNDU || rnd_mode == MPFR_RNDA || (rnd_mode == MPFR_RNDN && mpz_tstbit (m, 0))) inexact = 1, mpz_add_ui (m, m, 1); else inexact = -1; } /* either inexact is not zero, and the conversion is exact, i.e. inexact is not changed; or inexact=0, and inexact is set only when rnd_mode=MPFR_RNDN and bit (n+1) from m is 1 */ inexact += mpfr_set_z (y, m, MPFR_RNDN); MPFR_SET_EXP (y, MPFR_GET_EXP (y) + e / 3); if (negative) { MPFR_CHANGE_SIGN (y); inexact = -inexact; } mpz_clear (m); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (y, inexact, rnd_mode); }
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; }
int main (int argc, char *argv[]) { mpfr_t x, y; unsigned long int n; tests_start_mpfr (); mpfr_init (x); mpfr_init (y); n = randlimb (); MPFR_SET_INF(x); mpfr_ui_pow (y, n, x, MPFR_RNDN); if(!MPFR_IS_INF(y)) { printf ("evaluation of function in INF does not return INF\n"); exit (1); } MPFR_CHANGE_SIGN(x); mpfr_ui_pow (y, n, x, MPFR_RNDN); if(!MPFR_IS_ZERO(y)) { printf ("evaluation of function in -INF does not return 0"); exit (1); } MPFR_SET_NAN(x); mpfr_ui_pow (y, n, x, MPFR_RNDN); if(!MPFR_IS_NAN(y)) { printf ("evaluation of function in NAN does not return NAN"); exit (1); } test1 (); { mpfr_t z, t; mpfr_prec_t prec; mpfr_rnd_t rnd; unsigned int n; mpfr_prec_t p0=2, p1=100; unsigned int N=20; mpfr_init2 (z, 38); mpfr_init2 (t, 6); /* check exact power */ mpfr_set_str_binary (t, "0.110000E5"); mpfr_ui_pow (z, 3, t, MPFR_RNDN); mpfr_set_prec (x, 2); mpfr_set_prec (y, 2); mpfr_set_str (x, "-0.5", 10, MPFR_RNDZ); mpfr_ui_pow (y, 4, x, MPFR_RNDD); if (mpfr_cmp_ui_2exp(y, 1, -1)) { fprintf (stderr, "Error for 4^(-0.5), prec=2, MPFR_RNDD\n"); fprintf (stderr, "expected 0.5, got "); mpfr_out_str (stderr, 2, 0, y, MPFR_RNDN); fprintf (stderr, "\n"); exit (1); } /* problem found by Kevin on spe175.testdrive.compaq.com (03 Sep 2003), ia64 under HP-UX */ mpfr_set_prec (x, 2); mpfr_set_prec (y, 2); mpfr_set_str (x, "0.5", 10, MPFR_RNDN); mpfr_ui_pow (y, 398441521, x, MPFR_RNDN); if (mpfr_cmp_ui_2exp(y, 1, 14)) { fprintf (stderr, "Error for 398441521^(0.5), prec=2, MPFR_RNDN\n"); fprintf (stderr, "expected 1.0e14, got "); mpfr_out_str (stderr, 2, 0, y, MPFR_RNDN); fprintf (stderr, "\n"); exit (1); } mpfr_clear (z); mpfr_clear (t); mpfr_set_prec (x, 2); mpfr_set_str (x, "0.5", 10, MPFR_RNDN); check1 (x, 2, 398441521, MPFR_RNDN); /* 398441521 = 19961^2 */ /* generic test */ for (prec = p0; prec <= p1; prec++) { mpfr_set_prec (x, prec); for (n=0; n<N; n++) { int nt; nt = randlimb () & INT_MAX; mpfr_urandomb (x, RANDS); rnd = RND_RAND (); check1 (x, prec, nt, rnd); } } } mpfr_clear (x); mpfr_clear (y); tests_end_mpfr (); return 0; }
static void special_atan2 (void) { mpfr_t x, y, z; mpfr_inits2 (4, x, y, z, (mpfr_ptr) 0); /* Anything with NAN should be set to NAN */ mpfr_set_ui (y, 0, MPFR_RNDN); mpfr_set_nan (x); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_NAN (z)); mpfr_swap (x, y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_NAN (z)); /* 0+ 0+ --> 0+ */ mpfr_set_ui (y, 0, MPFR_RNDN); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_POS (z)); /* 0- 0+ --> 0- */ MPFR_CHANGE_SIGN (y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_NEG (z)); /* 0- 0- --> -PI */ MPFR_CHANGE_SIGN (x); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "-3.1415", 10, MPFR_RNDN) == 0); /* 0+ 0- --> +PI */ MPFR_CHANGE_SIGN (y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "3.1415", 10, MPFR_RNDN) == 0); /* 0+ -1 --> PI */ mpfr_set_si (x, -1, MPFR_RNDN); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "3.1415", 10, MPFR_RNDN) == 0); /* 0- -1 --> -PI */ MPFR_CHANGE_SIGN (y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "-3.1415", 10, MPFR_RNDN) == 0); /* 0- +1 --> 0- */ mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_NEG (z)); /* 0+ +1 --> 0+ */ MPFR_CHANGE_SIGN (y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_POS (z)); /* +1 0+ --> PI/2 */ mpfr_swap (x, y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "1.57075", 10, MPFR_RNDN) == 0); /* +1 0- --> PI/2 */ MPFR_CHANGE_SIGN (x); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "1.57075", 10, MPFR_RNDN) == 0); /* -1 0- --> -PI/2 */ MPFR_CHANGE_SIGN (y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "-1.57075", 10, MPFR_RNDN) == 0); /* -1 0+ --> -PI/2 */ MPFR_CHANGE_SIGN (x); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "-1.57075", 10, MPFR_RNDN) == 0); /* -1 +INF --> -0 */ MPFR_SET_INF (x); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_NEG (z)); /* +1 +INF --> +0 */ MPFR_CHANGE_SIGN (y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_POS (z)); /* +1 -INF --> +PI */ MPFR_CHANGE_SIGN (x); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "3.1415", 10, MPFR_RNDN) == 0); /* -1 -INF --> -PI */ MPFR_CHANGE_SIGN (y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "-3.1415", 10, MPFR_RNDN) == 0); /* -INF -1 --> -PI/2 */ mpfr_swap (x, y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "-1.57075", 10, MPFR_RNDN) == 0); /* +INF -1 --> PI/2 */ MPFR_CHANGE_SIGN (y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "1.57075", 10, MPFR_RNDN) == 0); /* +INF -INF --> 3*PI/4 */ MPFR_SET_INF (x); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "2.356194490192344928", 10, MPFR_RNDN) == 0); /* +INF +INF --> PI/4 */ MPFR_CHANGE_SIGN (x); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "0.785375", 10, MPFR_RNDN) == 0); /* -INF +INF --> -PI/4 */ MPFR_CHANGE_SIGN (y); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "-0.785375", 10, MPFR_RNDN) == 0); /* -INF -INF --> -3*PI/4 */ MPFR_CHANGE_SIGN (x); mpfr_atan2 (z, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_str (z, "-2.356194490192344928", 10, MPFR_RNDN) == 0); mpfr_set_prec (z, 905); /* exercises Ziv's loop */ mpfr_atan2 (z, y, x, MPFR_RNDZ); MPFR_ASSERTN (mpfr_cmp_str (z, "-2.35619449019234492884698253745962716314787704953132936573120844423086230471465674897102611900658780098661106488496172998532038345716293667379401955609636083808771307702645389082916973346721171619778647332160823174945008459635673617534008737395340143185923642519259526145784", 10, MPFR_RNDN) == 0); mpfr_clears (x, y, z, (mpfr_ptr) 0); }
static void special (void) { mpfr_t x, y; int i; mpfr_init (x); mpfr_init (y); /* root(NaN) = NaN */ mpfr_set_nan (x); mpfr_root (y, x, 17, GMP_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: root(NaN,17) <> NaN\n"); exit (1); } /* root(+Inf) = +Inf */ mpfr_set_inf (x, 1); mpfr_root (y, x, 42, GMP_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error: root(+Inf,42) <> +Inf\n"); exit (1); } /* root(-Inf, 17) = -Inf */ mpfr_set_inf (x, -1); mpfr_root (y, x, 17, GMP_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) > 0) { printf ("Error: root(-Inf,17) <> -Inf\n"); exit (1); } /* root(-Inf, 42) = NaN */ mpfr_set_inf (x, -1); mpfr_root (y, x, 42, GMP_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: root(-Inf,42) <> -Inf\n"); exit (1); } /* root(+/-0) = +/-0 */ mpfr_set_ui (x, 0, GMP_RNDN); mpfr_root (y, x, 17, GMP_RNDN); if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) < 0) { printf ("Error: root(+0,17) <> +0\n"); exit (1); } mpfr_neg (x, x, GMP_RNDN); mpfr_root (y, x, 42, GMP_RNDN); if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) > 0) { printf ("Error: root(-0,42) <> -0\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_set_str (x, "8.39005285514734966412e-01", 10, GMP_RNDN); mpfr_root (x, x, 3, GMP_RNDN); if (mpfr_cmp_str1 (x, "9.43166207799662426048e-01")) { printf ("Error in root3 (1)\n"); printf ("expected 9.43166207799662426048e-01\n"); printf ("got "); mpfr_dump (x); exit (1); } mpfr_set_prec (x, 32); mpfr_set_prec (y, 32); mpfr_set_str_binary (x, "0.10000100001100101001001001011001"); mpfr_root (x, x, 3, GMP_RNDN); mpfr_set_str_binary (y, "0.11001101011000100111000111111001"); if (mpfr_cmp (x, y)) { printf ("Error in root3 (2)\n"); exit (1); } mpfr_set_prec (x, 32); mpfr_set_prec (y, 32); mpfr_set_str_binary (x, "-0.1100001110110000010101011001011"); mpfr_root (x, x, 3, GMP_RNDD); mpfr_set_str_binary (y, "-0.11101010000100100101000101011001"); if (mpfr_cmp (x, y)) { printf ("Error in root3 (3)\n"); exit (1); } mpfr_set_prec (x, 82); mpfr_set_prec (y, 27); mpfr_set_str_binary (x, "0.1010001111011101011011000111001011001101100011110110010011011011011010011001100101e-7"); mpfr_root (y, x, 3, GMP_RNDD); mpfr_set_str_binary (x, "0.101011110001110001000100011E-2"); if (mpfr_cmp (x, y)) { printf ("Error in root3 (4)\n"); exit (1); } mpfr_set_prec (x, 204); mpfr_set_prec (y, 38); mpfr_set_str_binary (x, "0.101000000001101000000001100111111011111001110110100001111000100110100111001101100111110001110001011011010110010011100101111001111100001010010100111011101100000011011000101100010000000011000101001010001001E-5"); mpfr_root (y, x, 3, GMP_RNDD); mpfr_set_str_binary (x, "0.10001001111010011011101000010110110010E-1"); if (mpfr_cmp (x, y)) { printf ("Error in root3 (5)\n"); exit (1); } /* Worst case found on 2006-11-25 */ mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_str_binary (x, "1.0100001101101101001100110001001000000101001101100011E28"); mpfr_root (y, x, 35, GMP_RNDN); mpfr_set_str_binary (x, "1.1100000010110101100011101011000010100001101100100011E0"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_root (y, x, 35, GMP_RNDN) for\n" "x = 1.0100001101101101001100110001001000000101001101100011E28\n" "Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } /* Worst cases found on 2006-11-26 */ mpfr_set_str_binary (x, "1.1111010011101110001111010110000101110000110110101100E17"); mpfr_root (y, x, 36, GMP_RNDD); mpfr_set_str_binary (x, "1.0110100111010001101001010111001110010100111111000010E0"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_root (y, x, 36, GMP_RNDD) for\n" "x = 1.1111010011101110001111010110000101110000110110101100E17\n" "Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_str_binary (x, "1.1100011101101101100010110001000001110001111110010000E23"); mpfr_root (y, x, 36, GMP_RNDU); mpfr_set_str_binary (x, "1.1001010100001110000110111111100011011101110011000100E0"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_root (y, x, 36, GMP_RNDU) for\n" "x = 1.1100011101101101100010110001000001110001111110010000E23\n" "Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } /* Check for k = 1 */ mpfr_set_ui (x, 17, GMP_RNDN); i = mpfr_root (y, x, 1, GMP_RNDN); if (mpfr_cmp_ui (x, 17) || i != 0) { printf ("Error in root (17^(1/1))\n"); exit (1); } #if 0 /* Check for k == 0: For 0 <= x < 1 => +0. For x = 1 => 1. For x > 1, => +Inf. For x < 0 => NaN. */ i = mpfr_root (y, x, 0, GMP_RNDN); if (!MPFR_IS_INF (y) || !MPFR_IS_POS (y) || i != 0) { printf ("Error in root 17^(1/0)\n"); exit (1); } mpfr_set_ui (x, 1, GMP_RNDN); i = mpfr_root (y, x, 0, GMP_RNDN); if (mpfr_cmp_ui (y, 1) || i != 0) { printf ("Error in root 1^(1/0)\n"); exit (1); } mpfr_set_ui (x, 0, GMP_RNDN); i = mpfr_root (y, x, 0, GMP_RNDN); if (!MPFR_IS_ZERO (y) || !MPFR_IS_POS (y) || i != 0) { printf ("Error in root 0+^(1/0)\n"); exit (1); } MPFR_CHANGE_SIGN (x); i = mpfr_root (y, x, 0, GMP_RNDN); if (!MPFR_IS_ZERO (y) || !MPFR_IS_POS (y) || i != 0) { printf ("Error in root 0-^(1/0)\n"); exit (1); } mpfr_set_ui_2exp (x, 17, -5, GMP_RNDD); i = mpfr_root (y, x, 0, GMP_RNDN); if (!MPFR_IS_ZERO (y) || !MPFR_IS_POS (y) || i != 0) { printf ("Error in root (17/2^5)^(1/0)\n"); exit (1); } #endif mpfr_set_ui (x, 0, GMP_RNDN); i = mpfr_root (y, x, 0, GMP_RNDN); if (!MPFR_IS_NAN (y) || i != 0) { printf ("Error in root 0+^(1/0)\n"); exit (1); } /* Check for k==2 */ mpfr_set_si (x, -17, GMP_RNDD); i = mpfr_root (y, x, 2, GMP_RNDN); if (!MPFR_IS_NAN (y) || i != 0) { printf ("Error in root (-17)^(1/2)\n"); exit (1); } mpfr_clear (x); mpfr_clear (y); }
int main (int argc, char *argv[]) { mpfr_t x, y; mpfr_exp_t emin, emax; tests_start_mpfr (); special_overflow (); emax_m_eps (); exp_range (); mpfr_init (x); mpfr_init (y); mpfr_set_ui (x, 4, MPFR_RNDN); mpfr_exp2 (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 16) != 0) { printf ("Error for 2^4, MPFR_RNDN\n"); exit (1); } mpfr_exp2 (y, x, MPFR_RNDD); if (mpfr_cmp_ui (y, 16) != 0) { printf ("Error for 2^4, MPFR_RNDD\n"); exit (1); } mpfr_exp2 (y, x, MPFR_RNDU); if (mpfr_cmp_ui (y, 16) != 0) { printf ("Error for 2^4, MPFR_RNDU\n"); exit (1); } mpfr_set_si (x, -4, MPFR_RNDN); mpfr_exp2 (y, x, MPFR_RNDN); if (mpfr_cmp_ui_2exp (y, 1, -4) != 0) { printf ("Error for 2^(-4), MPFR_RNDN\n"); exit (1); } mpfr_exp2 (y, x, MPFR_RNDD); if (mpfr_cmp_ui_2exp (y, 1, -4) != 0) { printf ("Error for 2^(-4), MPFR_RNDD\n"); exit (1); } mpfr_exp2 (y, x, MPFR_RNDU); if (mpfr_cmp_ui_2exp (y, 1, -4) != 0) { printf ("Error for 2^(-4), MPFR_RNDU\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_str (x, /*-1683977482443233.0 / 2199023255552.0*/ "-7.6578429909351734750089235603809357e2", 10, MPFR_RNDN); mpfr_exp2 (y, x, MPFR_RNDN); if (mpfr_cmp_str1 (y, "2.991959870867646566478e-231")) { printf ("Error for x=-1683977482443233/2^41\n"); exit (1); } mpfr_set_prec (x, 10); mpfr_set_prec (y, 10); /* save emin */ emin = mpfr_get_emin (); set_emin (-10); mpfr_set_si (x, -12, MPFR_RNDN); mpfr_exp2 (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) < 0) { printf ("Error for x=emin-2, RNDN\n"); printf ("Expected +0\n"); printf ("Got "); mpfr_print_binary (y); puts (""); exit (1); } /* restore emin */ set_emin (emin); /* save emax */ emax = mpfr_get_emax (); set_emax (10); mpfr_set_ui (x, 11, MPFR_RNDN); mpfr_exp2 (y, x, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error for x=emax+1, RNDN\n"); exit (1); } /* restore emax */ set_emax (emax); MPFR_SET_INF(x); MPFR_SET_POS(x); mpfr_exp2 (y, x, MPFR_RNDN); if(!MPFR_IS_INF(y)) { printf ("evaluation of function in INF does not return INF\n"); exit (1); } MPFR_CHANGE_SIGN(x); mpfr_exp2 (y, x, MPFR_RNDN); if(!MPFR_IS_ZERO(y)) { printf ("evaluation of function in -INF does not return 0\n"); exit (1); } MPFR_SET_NAN(x); mpfr_exp2 (y, x, MPFR_RNDN); if(!MPFR_IS_NAN(y)) { printf ("evaluation of function in NaN does not return NaN\n"); exit (1); } if ((mpfr_uexp_t) 8 << 31 != 0 || mpfr_get_emax () <= (mpfr_uexp_t) 100000 * 100000) { /* emax <= 10000000000 */ mpfr_set_prec (x, 40); mpfr_set_prec (y, 40); mpfr_set_str (x, "10000000000.5", 10, MPFR_RNDN); mpfr_clear_flags (); mpfr_exp2 (y, x, MPFR_RNDN); if (!(MPFR_IS_INF (y) && MPFR_IS_POS (y) && mpfr_overflow_p ())) { printf ("exp2(10000000000.5) should overflow.\n"); exit (1); } } mpfr_set_prec (x, 2); mpfr_set_prec (y, 2); mpfr_set_str_binary (x, "-1.0E-26"); mpfr_exp2 (y, x, MPFR_RNDD); mpfr_set_str_binary (x, "1.1E-1"); if (mpfr_cmp (x, y)) { printf ("Error for exp(-2^(-26)) for prec=2\n"); exit (1); } test_generic (2, 100, 100); mpfr_clear (x); mpfr_clear (y); overflowed_exp2_0 (); data_check ("data/exp2", mpfr_exp2, "mpfr_exp2"); tests_end_mpfr (); return 0; }
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; }
int mpfr_sub (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) { MPFR_LOG_FUNC (("b[%#R]=%R c[%#R]=%R rnd=%d", b, b, c, c, rnd_mode), ("a[%#R]=%R", a, a)); if (MPFR_ARE_SINGULAR (b,c)) { if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c)) { MPFR_SET_NAN (a); MPFR_RET_NAN; } else if (MPFR_IS_INF (b)) { if (!MPFR_IS_INF (c) || MPFR_SIGN (b) != MPFR_SIGN(c)) { MPFR_SET_INF (a); MPFR_SET_SAME_SIGN (a, b); MPFR_RET (0); /* exact */ } else { MPFR_SET_NAN (a); /* Inf - Inf */ MPFR_RET_NAN; } } else if (MPFR_IS_INF (c)) { MPFR_SET_INF (a); MPFR_SET_OPPOSITE_SIGN (a, c); MPFR_RET (0); /* exact */ } else if (MPFR_IS_ZERO (b)) { if (MPFR_IS_ZERO (c)) { int sign = rnd_mode != MPFR_RNDD ? ((MPFR_IS_NEG(b) && MPFR_IS_POS(c)) ? -1 : 1) : ((MPFR_IS_POS(b) && MPFR_IS_NEG(c)) ? 1 : -1); MPFR_SET_SIGN (a, sign); MPFR_SET_ZERO (a); MPFR_RET(0); /* 0 - 0 is exact */ } else return mpfr_neg (a, c, rnd_mode); } else { MPFR_ASSERTD (MPFR_IS_ZERO (c)); return mpfr_set (a, b, rnd_mode); } } MPFR_ASSERTD (MPFR_IS_PURE_FP (b) && MPFR_IS_PURE_FP (c)); if (MPFR_LIKELY (MPFR_SIGN (b) == MPFR_SIGN (c))) { /* signs are equal, it's a real subtraction */ if (MPFR_LIKELY (MPFR_PREC (a) == MPFR_PREC (b) && MPFR_PREC (b) == MPFR_PREC (c))) return mpfr_sub1sp (a, b, c, rnd_mode); else return mpfr_sub1 (a, b, c, rnd_mode); } else { /* signs differ, it's an addition */ if (MPFR_GET_EXP (b) < MPFR_GET_EXP (c)) { /* exchange rounding modes toward +/- infinity */ int inexact; rnd_mode = MPFR_INVERT_RND (rnd_mode); if (MPFR_LIKELY (MPFR_PREC (a) == MPFR_PREC (b) && MPFR_PREC (b) == MPFR_PREC (c))) inexact = mpfr_add1sp (a, c, b, rnd_mode); else inexact = mpfr_add1 (a, c, b, rnd_mode); MPFR_CHANGE_SIGN (a); return -inexact; } else { if (MPFR_LIKELY (MPFR_PREC (a) == MPFR_PREC (b) && MPFR_PREC (b) == MPFR_PREC (c))) return mpfr_add1sp (a, b, c, rnd_mode); else return mpfr_add1 (a, b, c, rnd_mode); } } }
/* return mpfr_cmp (mpc_abs (a), mpc_abs (b)) */ int mpc_cmp_abs (mpc_srcptr a, mpc_srcptr b) { mpc_t z1, z2; mpfr_t n1, n2; mpfr_prec_t prec; int inex1, inex2, ret; /* Handle numbers containing one NaN as mpfr_cmp. */ if ( mpfr_nan_p (mpc_realref (a)) || mpfr_nan_p (mpc_imagref (a)) || mpfr_nan_p (mpc_realref (b)) || mpfr_nan_p (mpc_imagref (b))) { mpfr_t nan; mpfr_init (nan); mpfr_set_nan (nan); ret = mpfr_cmp (nan, nan); mpfr_clear (nan); return ret; } /* Handle infinities. */ if (mpc_inf_p (a)) if (mpc_inf_p (b)) return 0; else return 1; else if (mpc_inf_p (b)) return -1; /* Replace all parts of a and b by their absolute values, then order them by size. */ z1 [0] = a [0]; z2 [0] = b [0]; if (mpfr_signbit (mpc_realref (a))) MPFR_CHANGE_SIGN (mpc_realref (z1)); if (mpfr_signbit (mpc_imagref (a))) MPFR_CHANGE_SIGN (mpc_imagref (z1)); if (mpfr_signbit (mpc_realref (b))) MPFR_CHANGE_SIGN (mpc_realref (z2)); if (mpfr_signbit (mpc_imagref (b))) MPFR_CHANGE_SIGN (mpc_imagref (z2)); if (mpfr_cmp (mpc_realref (z1), mpc_imagref (z1)) > 0) mpfr_swap (mpc_realref (z1), mpc_imagref (z1)); if (mpfr_cmp (mpc_realref (z2), mpc_imagref (z2)) > 0) mpfr_swap (mpc_realref (z2), mpc_imagref (z2)); /* Handle cases in which only one part differs. */ if (mpfr_cmp (mpc_realref (z1), mpc_realref (z2)) == 0) return mpfr_cmp (mpc_imagref (z1), mpc_imagref (z2)); if (mpfr_cmp (mpc_imagref (z1), mpc_imagref (z2)) == 0) return mpfr_cmp (mpc_realref (z1), mpc_realref (z2)); /* Implement the algorithm in algorithms.tex. */ mpfr_init (n1); mpfr_init (n2); prec = MPC_MAX (50, MPC_MAX (MPC_MAX_PREC (z1), MPC_MAX_PREC (z2)) / 100); do { mpfr_set_prec (n1, prec); mpfr_set_prec (n2, prec); inex1 = mpc_norm (n1, z1, MPFR_RNDD); inex2 = mpc_norm (n2, z2, MPFR_RNDD); ret = mpfr_cmp (n1, n2); if (ret != 0) goto end; else if (inex1 == 0) /* n1 = norm(z1) */ if (inex2) /* n2 < norm(z2) */ { ret = -1; goto end; } else /* n2 = norm(z2) */ { ret = 0; goto end; } else /* n1 < norm(z1) */ if (inex2 == 0) { ret = 1; goto end; } prec *= 2; } while (1); end: mpfr_clear (n1); mpfr_clear (n2); return ret; }
/* (y, z) <- (sin(x), cos(x)), return value is 0 iff both results are exact ie, iff x = 0 */ int mpfr_sin_cos (mpfr_ptr y, mpfr_ptr z, mpfr_srcptr x, mp_rnd_t rnd_mode) { mp_prec_t prec, m; int neg, reduce; mpfr_t c, xr; mpfr_srcptr xx; mp_exp_t err, expx; MPFR_ZIV_DECL (loop); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) { if (MPFR_IS_NAN(x) || MPFR_IS_INF(x)) { MPFR_SET_NAN (y); MPFR_SET_NAN (z); MPFR_RET_NAN; } else /* x is zero */ { MPFR_ASSERTD (MPFR_IS_ZERO (x)); MPFR_SET_ZERO (y); MPFR_SET_SAME_SIGN (y, x); /* y = 0, thus exact, but z is inexact in case of underflow or overflow */ return mpfr_set_ui (z, 1, rnd_mode); } } MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode), ("sin[%#R]=%R cos[%#R]=%R", y, y, z, z)); prec = MAX (MPFR_PREC (y), MPFR_PREC (z)); m = prec + MPFR_INT_CEIL_LOG2 (prec) + 13; expx = MPFR_GET_EXP (x); mpfr_init (c); mpfr_init (xr); MPFR_ZIV_INIT (loop, m); for (;;) { /* the following is copied from sin.c */ if (expx >= 2) /* reduce the argument */ { reduce = 1; mpfr_set_prec (c, expx + m - 1); mpfr_set_prec (xr, m); mpfr_const_pi (c, GMP_RNDN); mpfr_mul_2ui (c, c, 1, GMP_RNDN); mpfr_remainder (xr, x, c, GMP_RNDN); mpfr_div_2ui (c, c, 1, GMP_RNDN); if (MPFR_SIGN (xr) > 0) mpfr_sub (c, c, xr, GMP_RNDZ); else mpfr_add (c, c, xr, GMP_RNDZ); if (MPFR_IS_ZERO(xr) || MPFR_EXP(xr) < (mp_exp_t) 3 - (mp_exp_t) m || MPFR_EXP(c) < (mp_exp_t) 3 - (mp_exp_t) m) goto next_step; xx = xr; } else /* the input argument is already reduced */ { reduce = 0; xx = x; } neg = MPFR_IS_NEG (xx); /* gives sign of sin(x) */ mpfr_set_prec (c, m); mpfr_cos (c, xx, GMP_RNDZ); /* If no argument reduction was performed, the error is at most ulp(c), otherwise it is at most ulp(c) + 2^(2-m). Since |c| < 1, we have ulp(c) <= 2^(-m), thus the error is bounded by 2^(3-m) in that later case. */ if (reduce == 0) err = m; else err = MPFR_GET_EXP (c) + (mp_exp_t) (m - 3); if (!mpfr_can_round (c, err, GMP_RNDN, rnd_mode, MPFR_PREC (z) + (rnd_mode == GMP_RNDN))) goto next_step; mpfr_set (z, c, rnd_mode); mpfr_sqr (c, c, GMP_RNDU); mpfr_ui_sub (c, 1, c, GMP_RNDN); err = 2 + (- MPFR_GET_EXP (c)) / 2; mpfr_sqrt (c, c, GMP_RNDN); if (neg) MPFR_CHANGE_SIGN (c); /* the absolute error on c is at most 2^(err-m), which we must put in the form 2^(EXP(c)-err). If there was an argument reduction, we need to add 2^(2-m); since err >= 2, the error is bounded by 2^(err+1-m) in that case. */ err = MPFR_GET_EXP (c) + (mp_exp_t) m - (err + reduce); if (mpfr_can_round (c, err, GMP_RNDN, rnd_mode, MPFR_PREC (y) + (rnd_mode == GMP_RNDN))) break; /* check for huge cancellation */ if (err < (mp_exp_t) MPFR_PREC (y)) m += MPFR_PREC (y) - err; /* Check if near 1 */ if (MPFR_GET_EXP (c) == 1 && MPFR_MANT (c)[MPFR_LIMB_SIZE (c)-1] == MPFR_LIMB_HIGHBIT) m += m; next_step: MPFR_ZIV_NEXT (loop, m); mpfr_set_prec (c, m); } MPFR_ZIV_FREE (loop); mpfr_set (y, c, rnd_mode); mpfr_clear (c); mpfr_clear (xr); MPFR_RET (1); /* Always inexact */ }