int mpfr_rint (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode) { int sign; int rnd_away; mpfr_exp_t exp; if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) )) { if (MPFR_IS_NAN(u)) { MPFR_SET_NAN(r); MPFR_RET_NAN; } MPFR_SET_SAME_SIGN(r, u); if (MPFR_IS_INF(u)) { MPFR_SET_INF(r); MPFR_RET(0); /* infinity is exact */ } else /* now u is zero */ { MPFR_ASSERTD(MPFR_IS_ZERO(u)); MPFR_SET_ZERO(r); MPFR_RET(0); /* zero is exact */ } } MPFR_SET_SAME_SIGN (r, u); /* Does nothing if r==u */ sign = MPFR_INT_SIGN (u); exp = MPFR_GET_EXP (u); rnd_away = rnd_mode == MPFR_RNDD ? sign < 0 : rnd_mode == MPFR_RNDU ? sign > 0 : rnd_mode == MPFR_RNDZ ? 0 : rnd_mode == MPFR_RNDA ? 1 : -1; /* round to nearest-even (RNDN) or nearest-away (RNDNA) */ /* rnd_away: 1 if round away from zero, 0 if round to zero, -1 if not decided yet. */ if (MPFR_UNLIKELY (exp <= 0)) /* 0 < |u| < 1 ==> round |u| to 0 or 1 */ { /* Note: in the MPFR_RNDN mode, 0.5 must be rounded to 0. */ if (rnd_away != 0 && (rnd_away > 0 || (exp == 0 && (rnd_mode == MPFR_RNDNA || !mpfr_powerof2_raw (u))))) { mp_limb_t *rp; mp_size_t rm; rp = MPFR_MANT(r); rm = (MPFR_PREC(r) - 1) / GMP_NUMB_BITS; rp[rm] = MPFR_LIMB_HIGHBIT; MPN_ZERO(rp, rm); MPFR_SET_EXP (r, 1); /* |r| = 1 */ MPFR_RET(sign > 0 ? 2 : -2); } else { MPFR_SET_ZERO(r); /* r = 0 */ MPFR_RET(sign > 0 ? -2 : 2); } } else /* exp > 0, |u| >= 1 */ { mp_limb_t *up, *rp; mp_size_t un, rn, ui; int sh, idiff; int uflags; /* * uflags will contain: * _ 0 if u is an integer representable in r, * _ 1 if u is an integer not representable in r, * _ 2 if u is not an integer. */ up = MPFR_MANT(u); rp = MPFR_MANT(r); un = MPFR_LIMB_SIZE(u); rn = MPFR_LIMB_SIZE(r); MPFR_UNSIGNED_MINUS_MODULO (sh, MPFR_PREC (r)); MPFR_SET_EXP (r, exp); /* Does nothing if r==u */ if ((exp - 1) / GMP_NUMB_BITS >= un) { ui = un; idiff = 0; uflags = 0; /* u is an integer, representable or not in r */ } else { mp_size_t uj; ui = (exp - 1) / GMP_NUMB_BITS + 1; /* #limbs of the int part */ MPFR_ASSERTD (un >= ui); uj = un - ui; /* lowest limb of the integer part */ idiff = exp % GMP_NUMB_BITS; /* #int-part bits in up[uj] or 0 */ uflags = idiff == 0 || (up[uj] << idiff) == 0 ? 0 : 2; if (uflags == 0) while (uj > 0) if (up[--uj] != 0) { uflags = 2; break; } } if (ui > rn) { /* More limbs in the integer part of u than in r. Just round u with the precision of r. */ MPFR_ASSERTD (rp != up && un > rn); MPN_COPY (rp, up + (un - rn), rn); /* r != u */ if (rnd_away < 0) { /* This is a rounding to nearest mode (MPFR_RNDN or MPFR_RNDNA). Decide the rounding direction here. */ if (rnd_mode == MPFR_RNDN && (rp[0] & (MPFR_LIMB_ONE << sh)) == 0) { /* halfway cases rounded toward zero */ mp_limb_t a, b; /* a: rounding bit and some of the following bits */ /* b: boundary for a (weight of the rounding bit in a) */ if (sh != 0) { a = rp[0] & ((MPFR_LIMB_ONE << sh) - 1); b = MPFR_LIMB_ONE << (sh - 1); } else { a = up[un - rn - 1]; b = MPFR_LIMB_HIGHBIT; } rnd_away = a > b; if (a == b) { mp_size_t i; for (i = un - rn - 1 - (sh == 0); i >= 0; i--) if (up[i] != 0) { rnd_away = 1; break; } } } else /* halfway cases rounded away from zero */ rnd_away = /* rounding bit */ ((sh != 0 && (rp[0] & (MPFR_LIMB_ONE << (sh - 1))) != 0) || (sh == 0 && (up[un - rn - 1] & MPFR_LIMB_HIGHBIT) != 0)); } if (uflags == 0) { /* u is an integer; determine if it is representable in r */ if (sh != 0 && rp[0] << (GMP_NUMB_BITS - sh) != 0) uflags = 1; /* u is not representable in r */ else { mp_size_t i; for (i = un - rn - 1; i >= 0; i--) if (up[i] != 0) { uflags = 1; /* u is not representable in r */ break; } } } } else /* ui <= rn */ { mp_size_t uj, rj; int ush; uj = un - ui; /* lowest limb of the integer part in u */ rj = rn - ui; /* lowest limb of the integer part in r */ if (MPFR_LIKELY (rp != up)) MPN_COPY(rp + rj, up + uj, ui); /* Ignore the lowest rj limbs, all equal to zero. */ rp += rj; rn = ui; /* number of fractional bits in whole rp[0] */ ush = idiff == 0 ? 0 : GMP_NUMB_BITS - idiff; if (rj == 0 && ush < sh) { /* If u is an integer (uflags == 0), we need to determine if it is representable in r, i.e. if its sh - ush bits in the non-significant part of r are all 0. */ if (uflags == 0 && (rp[0] & ((MPFR_LIMB_ONE << sh) - (MPFR_LIMB_ONE << ush))) != 0) uflags = 1; /* u is an integer not representable in r */ } else /* The integer part of u fits in r, we'll round to it. */ sh = ush; if (rnd_away < 0) { /* This is a rounding to nearest mode. Decide the rounding direction here. */ if (uj == 0 && sh == 0) rnd_away = 0; /* rounding bit = 0 (not represented in u) */ else if (rnd_mode == MPFR_RNDN && (rp[0] & (MPFR_LIMB_ONE << sh)) == 0) { /* halfway cases rounded toward zero */ mp_limb_t a, b; /* a: rounding bit and some of the following bits */ /* b: boundary for a (weight of the rounding bit in a) */ if (sh != 0) { a = rp[0] & ((MPFR_LIMB_ONE << sh) - 1); b = MPFR_LIMB_ONE << (sh - 1); } else { MPFR_ASSERTD (uj >= 1); /* see above */ a = up[uj - 1]; b = MPFR_LIMB_HIGHBIT; } rnd_away = a > b; if (a == b) { mp_size_t i; for (i = uj - 1 - (sh == 0); i >= 0; i--) if (up[i] != 0) { rnd_away = 1; break; } } } else /* halfway cases rounded away from zero */ rnd_away = /* rounding bit */ ((sh != 0 && (rp[0] & (MPFR_LIMB_ONE << (sh - 1))) != 0) || (sh == 0 && (MPFR_ASSERTD (uj >= 1), up[uj - 1] & MPFR_LIMB_HIGHBIT) != 0)); } /* Now we can make the low rj limbs to 0 */ MPN_ZERO (rp-rj, rj); } if (sh != 0) rp[0] &= MP_LIMB_T_MAX << sh; /* If u is a representable integer, there is no rounding. */ if (uflags == 0) MPFR_RET(0); MPFR_ASSERTD (rnd_away >= 0); /* rounding direction is defined */ if (rnd_away && mpn_add_1(rp, rp, rn, MPFR_LIMB_ONE << sh)) { if (exp == __gmpfr_emax) return mpfr_overflow(r, rnd_mode, MPFR_SIGN(r)) >= 0 ? uflags : -uflags; else { MPFR_SET_EXP(r, exp + 1); rp[rn-1] = MPFR_LIMB_HIGHBIT; } } MPFR_RET (rnd_away ^ (sign < 0) ? uflags : -uflags); } /* exp > 0, |u| >= 1 */ }
int mpfr_frac (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode) { mpfr_exp_t re, ue; mpfr_prec_t uq; mp_size_t un, tn, t0; mp_limb_t *up, *tp, k; int sh; mpfr_t tmp; mpfr_ptr t; int inex; MPFR_SAVE_EXPO_DECL (expo); /* Special cases */ if (MPFR_UNLIKELY(MPFR_IS_NAN(u))) { MPFR_SET_NAN(r); MPFR_RET_NAN; } else if (MPFR_UNLIKELY(MPFR_IS_INF(u) || mpfr_integer_p (u))) { MPFR_SET_SAME_SIGN(r, u); MPFR_SET_ZERO(r); MPFR_RET(0); /* zero is exact */ } ue = MPFR_GET_EXP (u); if (ue <= 0) /* |u| < 1 */ return mpfr_set (r, u, rnd_mode); /* Now |u| >= 1, meaning that an overflow is not possible. */ uq = MPFR_PREC(u); un = (uq - 1) / GMP_NUMB_BITS; /* index of most significant limb */ un -= (mp_size_t) (ue / GMP_NUMB_BITS); /* now the index of the MSL containing bits of the fractional part */ up = MPFR_MANT(u); sh = ue % GMP_NUMB_BITS; k = up[un] << sh; /* the first bit of the fractional part is the MSB of k */ if (k != 0) { int cnt; count_leading_zeros(cnt, k); /* first bit 1 of the fractional part -> MSB of the number */ re = -cnt; sh += cnt; MPFR_ASSERTN (sh < GMP_NUMB_BITS); k <<= cnt; } else { re = sh - GMP_NUMB_BITS; /* searching for the first bit 1 (exists since u isn't an integer) */ while (up[--un] == 0) re -= GMP_NUMB_BITS; MPFR_ASSERTN(un >= 0); k = up[un]; count_leading_zeros(sh, k); re -= sh; k <<= sh; } /* The exponent of r will be re */ /* un: index of the limb of u that contains the first bit 1 of the FP */ t = (mp_size_t) (MPFR_PREC(r) - 1) / GMP_NUMB_BITS < un ? (mpfr_init2 (tmp, (un + 1) * GMP_NUMB_BITS), tmp) : r; /* t has enough precision to contain the fractional part of u */ /* If we use a temporary variable, we take the non-significant bits of u into account, because of the mpn_lshift below. */ MPFR_SET_SAME_SIGN(t, u); /* Put the fractional part of u into t */ tn = (MPFR_PREC(t) - 1) / GMP_NUMB_BITS; MPFR_ASSERTN(tn >= un); t0 = tn - un; tp = MPFR_MANT(t); if (sh == 0) MPN_COPY_DECR(tp + t0, up, un + 1); else /* warning: un may be 0 here */ tp[tn] = k | ((un) ? mpn_lshift (tp + t0, up, un, sh) : (mp_limb_t) 0); if (t0 > 0) MPN_ZERO(tp, t0); MPFR_SAVE_EXPO_MARK (expo); if (t != r) { /* t is tmp */ MPFR_EXP (t) = 0; /* should be re, but not necessarily in the range */ inex = mpfr_set (r, t, rnd_mode); /* no underflow */ mpfr_clear (t); MPFR_EXP (r) += re; } else { /* There may be remaining non-significant bits in t (= r). */ int carry; MPFR_EXP (r) = re; carry = mpfr_round_raw (tp, tp, (mpfr_prec_t) (tn + 1) * GMP_NUMB_BITS, MPFR_IS_NEG (r), MPFR_PREC (r), rnd_mode, &inex); if (carry) { tp[tn] = MPFR_LIMB_HIGHBIT; MPFR_EXP (r) ++; } } MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (r, inex, rnd_mode); }
int mpfr_atanh (mpfr_ptr y, mpfr_srcptr xt , mpfr_rnd_t rnd_mode) { int inexact; mpfr_t x, t, te; mpfr_prec_t Nx, Ny, Nt; mpfr_exp_t err; MPFR_ZIV_DECL (loop); MPFR_SAVE_EXPO_DECL (expo); 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)); /* Special cases */ if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (xt))) { /* atanh(NaN) = NaN, and atanh(+/-Inf) = NaN since tanh gives a result between -1 and 1 */ if (MPFR_IS_NAN (xt) || MPFR_IS_INF (xt)) { MPFR_SET_NAN (y); MPFR_RET_NAN; } else /* necessarily xt is 0 */ { MPFR_ASSERTD (MPFR_IS_ZERO (xt)); MPFR_SET_ZERO (y); /* atanh(0) = 0 */ MPFR_SET_SAME_SIGN (y,xt); MPFR_RET (0); } } /* atanh (x) = NaN as soon as |x| > 1, and arctanh(+/-1) = +/-Inf */ if (MPFR_UNLIKELY (MPFR_GET_EXP (xt) > 0)) { if (MPFR_GET_EXP (xt) == 1 && mpfr_powerof2_raw (xt)) { MPFR_SET_INF (y); MPFR_SET_SAME_SIGN (y, xt); MPFR_SET_DIVBY0 (); MPFR_RET (0); } MPFR_SET_NAN (y); MPFR_RET_NAN; } /* atanh(x) = x + x^3/3 + ... so the error is < 2^(3*EXP(x)-1) */ MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, xt, -2 * MPFR_GET_EXP (xt), 1, 1, rnd_mode, {}); MPFR_SAVE_EXPO_MARK (expo); /* Compute initial precision */ Nx = MPFR_PREC (xt); MPFR_TMP_INIT_ABS (x, xt); Ny = MPFR_PREC (y); Nt = MAX (Nx, Ny); /* the optimal number of bits : see algorithms.ps */ Nt = Nt + MPFR_INT_CEIL_LOG2 (Nt) + 4; /* initialize of intermediary variable */ mpfr_init2 (t, Nt); mpfr_init2 (te, Nt); /* First computation of cosh */ MPFR_ZIV_INIT (loop, Nt); for (;;) { /* compute atanh */ mpfr_ui_sub (te, 1, x, MPFR_RNDU); /* (1-xt)*/ mpfr_add_ui (t, x, 1, MPFR_RNDD); /* (xt+1)*/ mpfr_div (t, t, te, MPFR_RNDN); /* (1+xt)/(1-xt)*/ mpfr_log (t, t, MPFR_RNDN); /* ln((1+xt)/(1-xt))*/ mpfr_div_2ui (t, t, 1, MPFR_RNDN); /* (1/2)*ln((1+xt)/(1-xt))*/ /* error estimate: see algorithms.tex */ /* FIXME: this does not correspond to the value in algorithms.tex!!! */ /* err=Nt-__gmpfr_ceil_log2(1+5*pow(2,1-MPFR_EXP(t)));*/ err = Nt - (MAX (4 - MPFR_GET_EXP (t), 0) + 1); if (MPFR_LIKELY (MPFR_IS_ZERO (t) || MPFR_CAN_ROUND (t, err, Ny, rnd_mode))) break; /* reactualisation of the precision */ MPFR_ZIV_NEXT (loop, Nt); mpfr_set_prec (t, Nt); mpfr_set_prec (te, Nt); } MPFR_ZIV_FREE (loop); inexact = mpfr_set4 (y, t, rnd_mode, MPFR_SIGN (xt)); mpfr_clear(t); mpfr_clear(te); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (y, inexact, rnd_mode); }
int mpfr_sin (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode) { mpfr_t c, xr; mpfr_srcptr xx; mpfr_exp_t expx, err; mpfr_prec_t precy, m; int inexact, sign, reduce; MPFR_ZIV_DECL (loop); 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)); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) { if (MPFR_IS_NAN (x) || MPFR_IS_INF (x)) { MPFR_SET_NAN (y); MPFR_RET_NAN; } else /* x is zero */ { MPFR_ASSERTD (MPFR_IS_ZERO (x)); MPFR_SET_ZERO (y); MPFR_SET_SAME_SIGN (y, x); MPFR_RET (0); } } /* sin(x) = x - x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */ MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -2 * MPFR_GET_EXP (x), 2, 0, rnd_mode, {}); MPFR_SAVE_EXPO_MARK (expo); /* Compute initial precision */ precy = MPFR_PREC (y); if (precy >= MPFR_SINCOS_THRESHOLD) return mpfr_sin_fast (y, x, rnd_mode); m = precy + MPFR_INT_CEIL_LOG2 (precy) + 13; expx = MPFR_GET_EXP (x); mpfr_init (c); mpfr_init (xr); MPFR_ZIV_INIT (loop, m); for (;;) { /* first perform argument reduction modulo 2*Pi (if needed), also helps to determine the sign of sin(x) */ if (expx >= 2) /* If Pi < x < 4, we need to reduce too, to determine the sign of sin(x). For 2 <= |x| < Pi, we could avoid the reduction. */ { reduce = 1; /* As expx + m - 1 will silently be converted into mpfr_prec_t in the mpfr_set_prec call, the assert below may be useful to avoid undefined behavior. */ MPFR_ASSERTN (expx + m - 1 <= MPFR_PREC_MAX); mpfr_set_prec (c, expx + m - 1); mpfr_set_prec (xr, m); mpfr_const_pi (c, MPFR_RNDN); mpfr_mul_2ui (c, c, 1, MPFR_RNDN); mpfr_remainder (xr, x, c, MPFR_RNDN); /* The analysis is similar to that of cos.c: |xr - x - 2kPi| <= 2^(2-m). Thus we can decide the sign of sin(x) if xr is at distance at least 2^(2-m) of both 0 and +/-Pi. */ mpfr_div_2ui (c, c, 1, MPFR_RNDN); /* Since c approximates Pi with an error <= 2^(2-expx-m) <= 2^(-m), it suffices to check that c - |xr| >= 2^(2-m). */ if (MPFR_SIGN (xr) > 0) mpfr_sub (c, c, xr, MPFR_RNDZ); else mpfr_add (c, c, xr, MPFR_RNDZ); if (MPFR_IS_ZERO(xr) || MPFR_GET_EXP(xr) < (mpfr_exp_t) 3 - (mpfr_exp_t) m || MPFR_IS_ZERO(c) || MPFR_GET_EXP(c) < (mpfr_exp_t) 3 - (mpfr_exp_t) m) goto ziv_next; /* |xr - x - 2kPi| <= 2^(2-m), thus |sin(xr) - sin(x)| <= 2^(2-m) */ xx = xr; } else /* the input argument is already reduced */ { reduce = 0; xx = x; } sign = MPFR_SIGN(xx); /* now that the argument is reduced, precision m is enough */ mpfr_set_prec (c, m); mpfr_cos (c, xx, MPFR_RNDZ); /* can't be exact */ mpfr_nexttoinf (c); /* now c = cos(x) rounded away */ mpfr_mul (c, c, c, MPFR_RNDU); /* away */ mpfr_ui_sub (c, 1, c, MPFR_RNDZ); mpfr_sqrt (c, c, MPFR_RNDZ); if (MPFR_IS_NEG_SIGN(sign)) MPFR_CHANGE_SIGN(c); /* Warning: c may be 0! */ if (MPFR_UNLIKELY (MPFR_IS_ZERO (c))) { /* Huge cancellation: increase prec a lot! */ m = MAX (m, MPFR_PREC (x)); m = 2 * m; } else { /* the absolute error on c is at most 2^(3-m-EXP(c)), plus 2^(2-m) if there was an argument reduction. Since EXP(c) <= 1, 3-m-EXP(c) >= 2-m, thus the error is at most 2^(3-m-EXP(c)) in case of argument reduction. */ err = 2 * MPFR_GET_EXP (c) + (mpfr_exp_t) m - 3 - (reduce != 0); if (MPFR_CAN_ROUND (c, err, precy, rnd_mode)) break; /* check for huge cancellation (Near 0) */ if (err < (mpfr_exp_t) MPFR_PREC (y)) m += MPFR_PREC (y) - err; /* Check if near 1 */ if (MPFR_GET_EXP (c) == 1) m += m; } ziv_next: /* Else generic increase */ MPFR_ZIV_NEXT (loop, m); } MPFR_ZIV_FREE (loop); inexact = mpfr_set (y, c, rnd_mode); /* inexact cannot be 0, since this would mean that c was representable within the target precision, but in that case mpfr_can_round will fail */ mpfr_clear (c); mpfr_clear (xr); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (y, inexact, rnd_mode); }