uintmax_t mpfr_get_uj (mpfr_srcptr f, mpfr_rnd_t rnd) { uintmax_t r; mpfr_prec_t prec; mpfr_t x; if (MPFR_UNLIKELY (!mpfr_fits_uintmax_p (f, rnd))) { MPFR_SET_ERANGEFLAG (); return MPFR_IS_NAN (f) || MPFR_IS_NEG (f) ? (uintmax_t) 0 : MPFR_UINTMAX_MAX; } if (MPFR_IS_ZERO (f)) return (uintmax_t) 0; /* determine the precision of uintmax_t */ for (r = MPFR_UINTMAX_MAX, prec = 0; r != 0; r /= 2, prec++) { } /* Now, r = 0. */ mpfr_init2 (x, prec); mpfr_rint (x, f, rnd); MPFR_ASSERTN (MPFR_IS_FP (x)); if (MPFR_NOTZERO (x)) { mp_limb_t *xp; int sh, n; /* An int should be sufficient in this context. */ MPFR_ASSERTN (MPFR_IS_POS (x)); xp = MPFR_MANT (x); sh = MPFR_GET_EXP (x); MPFR_ASSERTN ((mpfr_prec_t) sh <= prec); for (n = MPFR_LIMB_SIZE(x) - 1; n >= 0; n--) { sh -= GMP_NUMB_BITS; r += (sh >= 0 ? (uintmax_t) xp[n] << sh : (uintmax_t) xp[n] >> (- sh)); } } mpfr_clear (x); return r; }
int (mpfr_sgn) (mpfr_srcptr a) { if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a))) { if (MPFR_LIKELY (MPFR_IS_ZERO (a))) return 0; if (MPFR_UNLIKELY (MPFR_IS_NAN (a))) { MPFR_SET_ERANGEFLAG (); return 0; } /* Remains infinity, handled by the return below. */ } return MPFR_INT_SIGN (a); }
int mpfr_get_z (mpz_ptr z, mpfr_srcptr f, mpfr_rnd_t rnd) { int inex; mpfr_t r; mpfr_exp_t exp; MPFR_SAVE_EXPO_DECL (expo); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f))) { if (MPFR_UNLIKELY (MPFR_NOTZERO (f))) MPFR_SET_ERANGEFLAG (); mpz_set_ui (z, 0); /* The ternary value is 0 even for infinity. Giving the rounding direction in this case would not make much sense anyway, and the direction would not necessarily match rnd. */ return 0; } MPFR_SAVE_EXPO_MARK (expo); exp = MPFR_GET_EXP (f); /* if exp <= 0, then |f|<1, thus |o(f)|<=1 */ MPFR_ASSERTN (exp < 0 || exp <= MPFR_PREC_MAX); mpfr_init2 (r, (exp < (mpfr_exp_t) MPFR_PREC_MIN ? MPFR_PREC_MIN : (mpfr_prec_t) exp)); inex = mpfr_rint (r, f, rnd); MPFR_ASSERTN (inex != 1 && inex != -1); /* integral part of f is representable in r */ MPFR_ASSERTN (MPFR_IS_FP (r)); /* The flags from mpfr_rint are the wanted ones. In particular, it sets the inexact flag when necessary. */ MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); exp = mpfr_get_z_2exp (z, r); if (exp >= 0) mpz_mul_2exp (z, z, exp); else mpz_fdiv_q_2exp (z, z, -exp); mpfr_clear (r); MPFR_SAVE_EXPO_FREE (expo); return inex; }
/* Since MPFR-3.0, return the usual inexact value. The erange flag is set if an error occurred in the conversion (y is NaN, +Inf, or -Inf that have no equivalent in mpf) */ int mpfr_get_f (mpf_ptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode) { int inex; mp_size_t sx, sy; mpfr_prec_t precx, precy; mp_limb_t *xp; int sh; if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(y))) { if (MPFR_IS_ZERO(y)) { mpf_set_ui (x, 0); return 0; } else if (MPFR_IS_NAN (y)) { MPFR_SET_ERANGEFLAG (); return 0; } else /* y is plus infinity (resp. minus infinity), set x to the maximum value (resp. the minimum value) in precision PREC(x) */ { int i; mp_limb_t *xp; MPFR_SET_ERANGEFLAG (); /* To this day, [mp_exp_t] and mp_size_t are #defined as the same type */ EXP (x) = MP_SIZE_T_MAX; sx = PREC (x); SIZ (x) = sx; xp = PTR (x); for (i = 0; i < sx; i++) xp[i] = MPFR_LIMB_MAX; if (MPFR_IS_POS (y)) return -1; else { mpf_neg (x, x); return +1; } } } sx = PREC(x); /* number of limbs of the mantissa of x */ precy = MPFR_PREC(y); precx = (mpfr_prec_t) sx * GMP_NUMB_BITS; sy = MPFR_LIMB_SIZE (y); xp = PTR (x); /* since mpf numbers are represented in base 2^GMP_NUMB_BITS, we loose -EXP(y) % GMP_NUMB_BITS bits in the most significant limb */ sh = MPFR_GET_EXP(y) % GMP_NUMB_BITS; sh = sh <= 0 ? - sh : GMP_NUMB_BITS - sh; MPFR_ASSERTD (sh >= 0); if (precy + sh <= precx) /* we can copy directly */ { mp_size_t ds; MPFR_ASSERTN (sx >= sy); ds = sx - sy; if (sh != 0) { mp_limb_t out; out = mpn_rshift (xp + ds, MPFR_MANT(y), sy, sh); MPFR_ASSERTN (ds > 0 || out == 0); if (ds > 0) xp[--ds] = out; } else MPN_COPY (xp + ds, MPFR_MANT (y), sy); if (ds > 0) MPN_ZERO (xp, ds); EXP(x) = (MPFR_GET_EXP(y) + sh) / GMP_NUMB_BITS; inex = 0; } else /* we have to round to precx - sh bits */ { mpfr_t z; mp_size_t sz; /* Recall that precx = (mpfr_prec_t) sx * GMP_NUMB_BITS, thus removing sh bits (sh < GMP_NUMB_BITSS) won't reduce the number of limbs. */ mpfr_init2 (z, precx - sh); sz = MPFR_LIMB_SIZE (z); MPFR_ASSERTN (sx == sz); inex = mpfr_set (z, y, rnd_mode); /* warning, sh may change due to rounding, but then z is a power of two, thus we can safely ignore its last bit which is 0 */ sh = MPFR_GET_EXP(z) % GMP_NUMB_BITS; sh = sh <= 0 ? - sh : GMP_NUMB_BITS - sh; MPFR_ASSERTD (sh >= 0); if (sh != 0) { mp_limb_t out; out = mpn_rshift (xp, MPFR_MANT(z), sz, sh); /* If sh hasn't changed, it is the number of the non-significant bits in the lowest limb of z. Therefore out == 0. */ MPFR_ASSERTD (out == 0); (void) out; /* avoid a warning */ } else MPN_COPY (xp, MPFR_MANT(z), sz); EXP(x) = (MPFR_GET_EXP(z) + sh) / GMP_NUMB_BITS; mpfr_clear (z); } /* set size and sign */ SIZ(x) = (MPFR_FROM_SIGN_TO_INT(MPFR_SIGN(y)) < 0) ? -sx : sx; return inex; }
int mpfr_cmpabs (mpfr_srcptr b, mpfr_srcptr c) { mpfr_exp_t be, ce; mp_size_t bn, cn; mp_limb_t *bp, *cp; if (MPFR_ARE_SINGULAR (b, c)) { if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c)) { MPFR_SET_ERANGEFLAG (); return 0; } else if (MPFR_IS_INF (b)) return ! MPFR_IS_INF (c); else if (MPFR_IS_INF (c)) return -1; else if (MPFR_IS_ZERO (c)) return ! MPFR_IS_ZERO (b); else /* b == 0 */ return -1; } MPFR_ASSERTD (MPFR_IS_PURE_FP (b)); MPFR_ASSERTD (MPFR_IS_PURE_FP (c)); /* Now that we know that b and c are pure FP numbers (i.e. they have a meaningful exponent), we use MPFR_EXP instead of MPFR_GET_EXP to allow exponents outside the current exponent range. For instance, this is useful for mpfr_pow, which compares values to __gmpfr_one. This is for internal use only! For compatibility with other MPFR versions, the user must still provide values that are representable in the current exponent range. */ be = MPFR_EXP (b); ce = MPFR_EXP (c); if (be > ce) return 1; if (be < ce) return -1; /* exponents are equal */ bn = MPFR_LIMB_SIZE(b)-1; cn = MPFR_LIMB_SIZE(c)-1; bp = MPFR_MANT(b); cp = MPFR_MANT(c); for ( ; bn >= 0 && cn >= 0; bn--, cn--) { if (bp[bn] > cp[cn]) return 1; if (bp[bn] < cp[cn]) return -1; } for ( ; bn >= 0; bn--) if (bp[bn]) return 1; for ( ; cn >= 0; cn--) if (cp[cn]) return -1; return 0; }
int mpfr_cmp_ui_2exp (mpfr_srcptr b, unsigned long int i, mpfr_exp_t f) { if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(b) )) { if (MPFR_IS_NAN (b)) { MPFR_SET_ERANGEFLAG (); return 0; } else if (MPFR_IS_INF(b)) return MPFR_INT_SIGN (b); else /* since b cannot be NaN, b=0 here */ return i != 0 ? -1 : 0; } if (MPFR_IS_NEG (b)) return -1; /* now b > 0 */ else if (MPFR_UNLIKELY(i == 0)) return 1; else /* b > 0, i > 0 */ { mpfr_exp_t e; int k; mp_size_t bn; mp_limb_t c, *bp; /* i must be representable in a mp_limb_t */ MPFR_ASSERTN(i == (mp_limb_t) i); e = MPFR_GET_EXP (b); /* 2^(e-1) <= b < 2^e */ if (e <= f) return -1; if (f < MPFR_EMAX_MAX - GMP_NUMB_BITS && e > f + GMP_NUMB_BITS) return 1; /* now f < e <= f + GMP_NUMB_BITS */ c = (mp_limb_t) i; count_leading_zeros(k, c); if ((int) (e - f) > GMP_NUMB_BITS - k) return 1; if ((int) (e - f) < GMP_NUMB_BITS - k) return -1; /* now b and i*2^f have the same exponent */ c <<= k; bn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS; bp = MPFR_MANT(b); if (bp[bn] > c) return 1; if (bp[bn] < c) return -1; /* most significant limbs agree, check remaining limbs from b */ while (bn > 0) if (bp[--bn] != 0) return 1; return 0; } }
int mpfr_cmp_si_2exp (mpfr_srcptr b, long int i, mpfr_exp_t f) { int si; si = i < 0 ? -1 : 1; /* sign of i */ if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (b))) { if (MPFR_IS_INF(b)) return MPFR_INT_SIGN(b); else if (MPFR_IS_ZERO(b)) return i != 0 ? -si : 0; /* NAN */ MPFR_SET_ERANGEFLAG (); return 0; } else if (MPFR_SIGN(b) != si || i == 0) return MPFR_INT_SIGN (b); else /* b and i are of same sign si */ { mpfr_exp_t e; unsigned long ai; int k; mp_size_t bn; mp_limb_t c, *bp; ai = SAFE_ABS(unsigned long, i); /* ai must be representable in a mp_limb_t */ MPFR_ASSERTN(ai == (mp_limb_t) ai); e = MPFR_GET_EXP (b); /* 2^(e-1) <= b < 2^e */ if (e <= f) return -si; if (f < MPFR_EMAX_MAX - GMP_NUMB_BITS && e > f + GMP_NUMB_BITS) return si; /* now f < e <= f + GMP_NUMB_BITS */ c = (mp_limb_t) ai; count_leading_zeros(k, c); if ((int) (e - f) > GMP_NUMB_BITS - k) return si; if ((int) (e - f) < GMP_NUMB_BITS - k) return -si; /* now b and i*2^f have the same exponent */ c <<= k; bn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS; bp = MPFR_MANT(b); if (bp[bn] > c) return si; if (bp[bn] < c) return -si; /* most significant limbs agree, check remaining limbs from b */ while (bn > 0) if (bp[--bn]) return si; return 0; } }
MPFR_HOT_FUNCTION_ATTR int mpfr_cmp3 (mpfr_srcptr b, mpfr_srcptr c, int s) { mpfr_exp_t be, ce; mp_size_t bn, cn; mp_limb_t *bp, *cp; s = MPFR_MULT_SIGN( s , MPFR_SIGN(c) ); if (MPFR_ARE_SINGULAR(b, c)) { if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c)) { MPFR_SET_ERANGEFLAG (); return 0; } else if (MPFR_IS_INF(b)) { if (MPFR_IS_INF(c) && s == MPFR_SIGN(b) ) return 0; else return MPFR_SIGN(b); } else if (MPFR_IS_INF(c)) return -s; else if (MPFR_IS_ZERO(b)) return MPFR_IS_ZERO(c) ? 0 : -s; else /* necessarily c=0 */ return MPFR_SIGN(b); } /* b and c are real numbers */ if (s != MPFR_SIGN(b)) return MPFR_SIGN(b); /* now signs are equal */ be = MPFR_GET_EXP (b); ce = MPFR_GET_EXP (c); if (be > ce) return s; if (be < ce) return -s; /* both signs and exponents are equal */ bn = MPFR_LAST_LIMB (b); cn = MPFR_LAST_LIMB (c); bp = MPFR_MANT(b); cp = MPFR_MANT(c); for ( ; bn >= 0 && cn >= 0; bn--, cn--) { if (bp[bn] > cp[cn]) return s; if (bp[bn] < cp[cn]) return -s; } for ( ; bn >= 0; bn--) if (bp[bn]) return s; for ( ; cn >= 0; cn--) if (cp[cn]) return -s; return 0; }