int mpfr_max (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd_mode) { if (MPFR_IS_NAN(x) && MPFR_IS_NAN(y) ) { MPFR_SET_NAN(z); MPFR_RET_NAN; } MPFR_CLEAR_NAN(z); if (MPFR_IS_NAN(x)) return mpfr_set(z, y, rnd_mode); if (MPFR_IS_NAN(y)) return mpfr_set(z, x, rnd_mode); if (MPFR_IS_FP(x) && MPFR_IS_ZERO(x) && MPFR_IS_FP(y) && MPFR_IS_ZERO(y)) { if (MPFR_SIGN(x) < 0) return mpfr_set(z, y, rnd_mode); else return mpfr_set(z, x, rnd_mode); } if (mpfr_cmp(x,y) <= 0) return mpfr_set(z, y, rnd_mode); else return mpfr_set(z, x, rnd_mode); }
/* compute remainder as in definition: r = x - n * y, where n = trunc(x/y). warning: may change flags. */ static int slow_fmod (mpfr_ptr r, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd) { mpfr_t q; int inexact; if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x) || MPFR_IS_SINGULAR (y))) { if (MPFR_IS_NAN (x) || MPFR_IS_NAN (y) || MPFR_IS_INF (x) || MPFR_IS_ZERO (y)) { MPFR_SET_NAN (r); MPFR_RET_NAN; } else /* either y is Inf and x is 0 or non-special, or x is 0 and y is non-special, in both cases the quotient is zero. */ return mpfr_set (r, x, rnd); } /* regular cases */ /* if 2^(ex-1) <= |x| < 2^ex, and 2^(ey-1) <= |y| < 2^ey, then |x/y| < 2^(ex-ey+1) */ mpfr_init2 (q, MAX (MPFR_PREC_MIN, mpfr_get_exp (x) - mpfr_get_exp (y) + 1)); mpfr_div (q, x, y, MPFR_RNDZ); mpfr_trunc (q, q); /* may change inexact flag */ mpfr_prec_round (q, mpfr_get_prec (q) + mpfr_get_prec (y), MPFR_RNDZ); inexact = mpfr_mul (q, q, y, MPFR_RNDZ); /* exact */ inexact = mpfr_sub (r, x, q, rnd); mpfr_clear (q); return inexact; }
int mpfr_max (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode) { if (MPFR_ARE_SINGULAR(x,y)) { if (MPFR_IS_NAN(x) && MPFR_IS_NAN(y) ) { MPFR_SET_NAN(z); MPFR_RET_NAN; } else if (MPFR_IS_NAN(x)) return mpfr_set(z, y, rnd_mode); else if (MPFR_IS_NAN(y)) return mpfr_set(z, x, rnd_mode); else if (MPFR_IS_ZERO(x) && MPFR_IS_ZERO(y)) { if (MPFR_IS_NEG(x)) return mpfr_set(z, y, rnd_mode); else return mpfr_set(z, x, rnd_mode); } } if (mpfr_cmp(x,y) <= 0) return mpfr_set(z, y, rnd_mode); else return mpfr_set(z, x, rnd_mode); }
int mpfr_cmpabs (mpfr_srcptr b, mpfr_srcptr c) { mp_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_ERANGE (); 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; } be = MPFR_GET_EXP (b); ce = MPFR_GET_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; }
/* When a * b is exact, the FMA is equivalent to the separate operations. */ static void test_exact (void) { char *val[] = { "@NaN@", "-@Inf@", "-2", "-1", "-0", "0", "1", "2", "@Inf@" }; int sv = sizeof (val) / sizeof (*val); int i, j, k; int rnd; mpfr_t a, b, c, r1, r2; mpfr_inits2 (8, a, b, c, r1, r2, (void *) 0); for (i = 0; i < sv; i++) for (j = 0; j < sv; j++) for (k = 0; k < sv; k++) RND_LOOP (rnd) { if (mpfr_set_str (a, val[i], 10, GMP_RNDN) || mpfr_set_str (b, val[j], 10, GMP_RNDN) || mpfr_set_str (c, val[k], 10, GMP_RNDN) || mpfr_mul (r1, a, b, rnd) || mpfr_add (r1, r1, c, rnd)) { printf ("test_exact internal error for (%d,%d,%d,%d)\n", i, j, k, rnd); exit (1); } if (mpfr_fma (r2, a, b, c, rnd)) { printf ("test_exact(%d,%d,%d,%d): mpfr_fma should be exact\n", i, j, k, rnd); exit (1); } if (MPFR_IS_NAN (r1)) { if (MPFR_IS_NAN (r2)) continue; printf ("test_exact(%d,%d,%d,%d): mpfr_fma should be NaN\n", i, j, k, rnd); exit (1); } if (mpfr_cmp (r1, r2) || MPFR_SIGN (r1) != MPFR_SIGN (r2)) { printf ("test_exact(%d,%d,%d,%d):\nexpected ", i, j, k, rnd); mpfr_out_str (stdout, 10, 0, r1, GMP_RNDN); printf ("\n got "); mpfr_out_str (stdout, 10, 0, r2, GMP_RNDN); printf ("\n"); exit (1); } } mpfr_clears (a, b, c, r1, r2, (void *) 0); }
/* Arguments: * spx: non-zero if px is a stringm zero if px is a MPFR number. * px: value of x (string or MPFR number). * sy: value of y (string). * rnd: rounding mode. * z1: expected result (null pointer if unknown pure FP value). * inex1: expected ternary value (if z1 is not a null pointer). * z2: computed result. * inex2: computed ternary value. * flags1: expected flags (computed flags in __gmpfr_flags). * s1, s2: strings about the context. */ static void cmpres (int spx, const void *px, const char *sy, mpfr_rnd_t rnd, mpfr_srcptr z1, int inex1, mpfr_srcptr z2, int inex2, unsigned int flags1, const char *s1, const char *s2) { unsigned int flags2 = __gmpfr_flags; if (flags1 == flags2) { /* Note: the test on the sign of z1 and z2 is needed in case they are both zeros. */ if (z1 == NULL) { if (MPFR_IS_PURE_FP (z2)) return; } else if (SAME_SIGN (inex1, inex2) && ((MPFR_IS_NAN (z1) && MPFR_IS_NAN (z2)) || ((MPFR_IS_NEG (z1) ^ MPFR_IS_NEG (z2)) == 0 && mpfr_equal_p (z1, z2)))) return; } printf ("Error in %s\nwith %s%s\nx = ", s1, s2, ext ? ", extended exponent range" : ""); if (spx) printf ("%s, ", (char *) px); else { mpfr_out_str (stdout, 16, 0, (mpfr_ptr) px, MPFR_RNDN); puts (","); } printf ("y = %s, %s\n", sy, mpfr_print_rnd_mode (rnd)); printf ("Expected "); if (z1 == NULL) { printf ("pure FP value, flags = %u\n", flags1); } else { mpfr_out_str (stdout, 16, 0, z1, MPFR_RNDN); printf (", inex = %d, flags = %u\n", SIGN (inex1), flags1); } printf ("Got "); mpfr_out_str (stdout, 16, 0, z2, MPFR_RNDN); printf (", inex = %d, flags = %u\n", SIGN (inex2), flags2); if (all_cmpres_errors != 0) all_cmpres_errors = -1; else exit (1); }
/* reldiff(b, c) = abs(b-c)/b */ void mpfr_reldiff (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) { mpfr_t b_copy; if (MPFR_ARE_SINGULAR (b, c)) { if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c)) { MPFR_SET_NAN(a); return; } else if (MPFR_IS_INF(b)) { if (MPFR_IS_INF (c) && (MPFR_SIGN (c) == MPFR_SIGN (b))) MPFR_SET_ZERO(a); else MPFR_SET_NAN(a); return; } else if (MPFR_IS_INF(c)) { MPFR_SET_SAME_SIGN (a, b); MPFR_SET_INF (a); return; } else if (MPFR_IS_ZERO(b)) /* reldiff = abs(c)/c = sign(c) */ { mpfr_set_si (a, MPFR_INT_SIGN (c), rnd_mode); return; } /* Fall through */ } if (a == b) { mpfr_init2 (b_copy, MPFR_PREC(b)); mpfr_set (b_copy, b, MPFR_RNDN); } mpfr_sub (a, b, c, rnd_mode); mpfr_abs (a, a, rnd_mode); /* for compatibility with MPF */ mpfr_div (a, a, (a == b) ? b_copy : b, rnd_mode); if (a == b) mpfr_clear (b_copy); }
/* sets x to x+sign(x)*ulp(x) */ int mpfr_add_one_ulp (mpfr_ptr x, mp_rnd_t rnd_mode) { mp_size_t xn; int sh; mp_limb_t *xp; if (MPFR_IS_NAN(x)) MPFR_RET_NAN; if (MPFR_IS_INF(x) || MPFR_IS_ZERO(x)) return 0; xn = 1 + (MPFR_PREC(x) - 1) / BITS_PER_MP_LIMB; sh = xn * BITS_PER_MP_LIMB - MPFR_PREC(x); xp = MPFR_MANT(x); if (mpn_add_1 (xp, xp, xn, MP_LIMB_T_ONE << sh)) /* got 1.0000... */ { mp_exp_t exp = MPFR_EXP(x); if (exp == __mpfr_emax) return mpfr_set_overflow(x, rnd_mode, MPFR_SIGN(x)); else { MPFR_EXP(x)++; xp[xn-1] = GMP_LIMB_HIGHBIT; } } return 0; }
int mpfr_ui_div (mpfr_ptr y, unsigned long int u, mpfr_srcptr x, mpfr_rnd_t rnd_mode) { mpfr_t uu; mp_limb_t up[1]; unsigned long cnt; MPFR_LOG_FUNC (("u=%lu x[%Pu]=%.*Rg rnd=%d", u, mpfr_get_prec(x), mpfr_log_prec, x, rnd_mode), ("y[%Pu]=%.*Rg", mpfr_get_prec(y), mpfr_log_prec, y)); 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)) /* u/Inf = 0 */ { MPFR_SET_ZERO(y); MPFR_SET_SAME_SIGN(y,x); MPFR_RET(0); } else /* u / 0 */ { MPFR_ASSERTD(MPFR_IS_ZERO(x)); if (u) { /* u > 0, so y = sign(x) * Inf */ MPFR_SET_SAME_SIGN(y, x); MPFR_SET_INF(y); mpfr_set_divby0 (); MPFR_RET(0); } else { /* 0 / 0 */ MPFR_SET_NAN(y); MPFR_RET_NAN; } } } else if (MPFR_LIKELY(u != 0)) { MPFR_TMP_INIT1(up, uu, GMP_NUMB_BITS); MPFR_ASSERTN(u == (mp_limb_t) u); count_leading_zeros(cnt, (mp_limb_t) u); up[0] = (mp_limb_t) u << cnt; MPFR_SET_EXP (uu, GMP_NUMB_BITS - cnt); return mpfr_div (y, uu, x, rnd_mode); } else /* u = 0, and x != 0 */ { MPFR_SET_ZERO(y); /* if u=0, then set y to 0 */ MPFR_SET_SAME_SIGN(y, x); /* u considered as +0: sign(+0/x) = sign(x) */ MPFR_RET(0); } }
int mpfr_frexp (mpfr_exp_t *exp, mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd) { int inex; if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(x))) { if (MPFR_IS_NAN(x)) { MPFR_SET_NAN(y); MPFR_RET_NAN; /* exp is unspecified */ } else if (MPFR_IS_INF(x)) { MPFR_SET_INF(y); MPFR_SET_SAME_SIGN(y,x); MPFR_RET(0); /* exp is unspecified */ } else { MPFR_SET_ZERO(y); MPFR_SET_SAME_SIGN(y,x); *exp = 0; MPFR_RET(0); } } inex = mpfr_set (y, x, rnd); *exp = MPFR_GET_EXP (y); MPFR_SET_EXP (y, 0); return mpfr_check_range (y, inex, rnd); }
static void consistency (void) { mpfr_t x, y, z1, z2; int i; mpfr_inits (x, y, z1, z2, (mpfr_ptr) 0); for (i = 0; i < 10000; i++) { mpfr_rnd_t rnd; mpfr_prec_t px, py, pz, p; int inex1, inex2; rnd = RND_RAND (); px = (randlimb () % 256) + 2; py = (randlimb () % 128) + 2; pz = (randlimb () % 256) + 2; mpfr_set_prec (x, px); mpfr_set_prec (y, py); mpfr_set_prec (z1, pz); mpfr_set_prec (z2, pz); mpfr_urandomb (x, RANDS); do mpfr_urandomb (y, RANDS); while (mpfr_zero_p (y)); inex1 = mpfr_div (z1, x, y, rnd); MPFR_ASSERTN (!MPFR_IS_NAN (z1)); p = MAX (MAX (px, py), pz); if (mpfr_prec_round (x, p, MPFR_RNDN) != 0 || mpfr_prec_round (y, p, MPFR_RNDN) != 0) { printf ("mpfr_prec_round error for i = %d\n", i); exit (1); } inex2 = mpfr_div (z2, x, y, rnd); MPFR_ASSERTN (!MPFR_IS_NAN (z2)); if (inex1 != inex2 || mpfr_cmp (z1, z2) != 0) { printf ("Consistency error for i = %d\n", i); exit (1); } } mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0); }
static void check_equal (mpfr_srcptr a, mpfr_srcptr a2, char *s, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t r) { if ((MPFR_IS_NAN (a) && MPFR_IS_NAN (a2)) || mpfr_equal_p (a, a2)) return; printf ("Error in %s\n", mpfr_print_rnd_mode (r)); printf ("b = "); mpfr_dump (b); printf ("c = "); mpfr_dump (c); printf ("mpfr_div result: "); mpfr_dump (a); printf ("%s result: ", s); mpfr_dump (a2); exit (1); }
int mpfr_dim (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode) { if (MPFR_IS_NAN(x) || MPFR_IS_NAN(y)) { MPFR_SET_NAN(z); MPFR_RET_NAN; } if (mpfr_cmp (x,y) > 0) return mpfr_sub (z, x, y, rnd_mode); else { MPFR_SET_ZERO(z); MPFR_SET_POS(z); MPFR_RET(0); } }
int mpfr_ui_div (mpfr_ptr y, unsigned long int u, mpfr_srcptr x, mp_rnd_t rnd_mode) { mpfr_t uu; mp_limb_t up[1]; unsigned long cnt; 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)) /* u/Inf = 0 */ { MPFR_SET_ZERO(y); MPFR_SET_SAME_SIGN(y,x); MPFR_RET(0); } else /* u / 0 */ { MPFR_ASSERTD(MPFR_IS_ZERO(x)); if (u) { /* u > 0, so y = sign(x) * Inf */ MPFR_SET_SAME_SIGN(y, x); MPFR_SET_INF(y); MPFR_RET(0); } else { /* 0 / 0 */ MPFR_SET_NAN(y); MPFR_RET_NAN; } } } else if (MPFR_LIKELY(u != 0)) { MPFR_TMP_INIT1(up, uu, BITS_PER_MP_LIMB); MPFR_ASSERTN(u == (mp_limb_t) u); count_leading_zeros(cnt, (mp_limb_t) u); up[0] = (mp_limb_t) u << cnt; MPFR_SET_EXP (uu, BITS_PER_MP_LIMB - cnt); return mpfr_div (y, uu, x, rnd_mode); } else /* u = 0, and x != 0 */ { MPFR_SET_ZERO(y); /* if u=0, then set y to 0 */ MPFR_SET_SAME_SIGN(y, x); /* u considered as +0: sign(+0/x) = sign(x) */ MPFR_RET(0); } }
int mpfr_custom_get_kind (mpfr_srcptr x) { if (MPFR_LIKELY (!MPFR_IS_SINGULAR (x))) return (int) MPFR_REGULAR_KIND * MPFR_INT_SIGN (x); if (MPFR_IS_INF (x)) return (int) MPFR_INF_KIND * MPFR_INT_SIGN (x); if (MPFR_IS_NAN (x)) return (int) MPFR_NAN_KIND; MPFR_ASSERTD (MPFR_IS_ZERO (x)); return (int) MPFR_ZERO_KIND * MPFR_INT_SIGN (x); }
/* * Check if x is a valid mpfr_t initializes by mpfr_init * Returns 0 if isn't valid */ int mpfr_check (mpfr_srcptr x) { mp_size_t s, i; mp_limb_t tmp; volatile mp_limb_t *xm; mpfr_prec_t prec; int rw; /* Check sign */ if (MPFR_SIGN(x) != MPFR_SIGN_POS && MPFR_SIGN(x) != MPFR_SIGN_NEG) return 0; /* Check precision */ prec = MPFR_PREC(x); if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) return 0; /* Check mantissa */ xm = MPFR_MANT(x); if (xm == NULL) return 0; /* Check size of mantissa */ s = MPFR_GET_ALLOC_SIZE(x); if (s <= 0 || s > MP_SIZE_T_MAX || prec > (mpfr_prec_t) s * GMP_NUMB_BITS) return 0; /* Acces all the mp_limb of the mantissa: may do a seg fault */ for (i = 0 ; i < s ; i++) tmp = xm[i]; /* Check singular numbers (do not use MPFR_IS_PURE_FP() in order to avoid any assertion checking, as this function mpfr_check() does something similar by returning a Boolean instead of doing an abort if the format is incorrect). */ if (MPFR_IS_SINGULAR (x)) return MPFR_IS_ZERO(x) || MPFR_IS_NAN(x) || MPFR_IS_INF(x); /* Check the most significant limb (its MSB must be 1) */ if ((xm[MPFR_LAST_LIMB(x)] & MPFR_LIMB_HIGHBIT) == 0) return 0; /* Check the least significant limb (the trailing bits must be 0) */ rw = prec % GMP_NUMB_BITS; if (rw != 0) { tmp = MPFR_LIMB_MASK (GMP_NUMB_BITS - rw); if ((xm[0] & tmp) != 0) return 0; } /* Check exponent range */ if (MPFR_EXP (x) < __gmpfr_emin || MPFR_EXP (x) > __gmpfr_emax) return 0; return 1; }
int mpfr_cmp_str (mpfr_srcptr x, const char *s, int base, mpfr_rnd_t rnd) { mpfr_t y; int res; MPFR_ASSERTN (!MPFR_IS_NAN (x)); mpfr_init2 (y, MPFR_PREC(x)); mpfr_set_str (y, s, base, rnd); res = mpfr_cmp (x,y); mpfr_clear (y); return res; }
double mpfr_get_d_2exp (long *expptr, mpfr_srcptr src, mpfr_rnd_t rnd_mode) { double ret; mpfr_exp_t exp; mpfr_t tmp; if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (src))) { int negative; *expptr = 0; if (MPFR_IS_NAN (src)) return MPFR_DBL_NAN; negative = MPFR_IS_NEG (src); if (MPFR_IS_INF (src)) return negative ? MPFR_DBL_INFM : MPFR_DBL_INFP; MPFR_ASSERTD (MPFR_IS_ZERO(src)); return negative ? DBL_NEG_ZERO : 0.0; } tmp[0] = *src; /* Hack copy mpfr_t */ MPFR_SET_EXP (tmp, 0); ret = mpfr_get_d (tmp, rnd_mode); if (MPFR_IS_PURE_FP(src)) { exp = MPFR_GET_EXP (src); /* rounding can give 1.0, adjust back to 0.5 <= abs(ret) < 1.0 */ if (ret == 1.0) { ret = 0.5; exp++; } else if (ret == -1.0) { ret = -0.5; exp++; } MPFR_ASSERTN ((ret >= 0.5 && ret < 1.0) || (ret <= -0.5 && ret > -1.0)); MPFR_ASSERTN (exp >= LONG_MIN && exp <= LONG_MAX); } else exp = 0; *expptr = exp; return ret; }
/* We can't use fits_u.h <= mpfr_cmp_ui */ int mpfr_fits_uintmax_p (mpfr_srcptr f, mp_rnd_t rnd) { mp_exp_t exp; mp_prec_t prec; uintmax_t s; mpfr_t x, y; int res; if (MPFR_IS_NAN(f) || MPFR_IS_INF(f) || MPFR_SIGN(f) < 0) return 0; /* does not fit */ if (MPFR_IS_ZERO(f)) return 1; /* zero always fits */ /* now it fits if (a) f <= MAXIMUM (b) round(f, prec(slong), rnd) <= MAXIMUM */ exp = MPFR_EXP(f); if (exp < 1) return 1; /* |f| < 1: always fits */ /* first compute prec(MAXIMUM) */ for (s = UINTMAX_MAX, prec = 0; s != 0; s /= 2, prec ++); /* MAXIMUM needs prec bits, i.e. 2^(prec-1) <= |MAXIMUM| < 2^prec */ /* if exp < prec - 1, then f < 2^(prec-1) < |MAXIMUM| */ if ((mpfr_prec_t) exp < prec - 1) return 1; /* if exp > prec + 1, then f >= 2^prec > MAXIMUM */ if ((mpfr_prec_t) exp > prec + 1) return 0; /* remains cases exp = prec-1 to prec+1 */ /* hard case: first round to prec bits, then check */ mpfr_init2 (x, prec); mpfr_init2 (y, prec); mpfr_set (x, f, rnd); res = mpfr_set_uj (y, UINTMAX_MAX, GMP_RNDN); MPFR_ASSERTD (res == 0); res = mpfr_cmp (x, y) <= 0; mpfr_clear (y); mpfr_clear (x); return res; }
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; }
static void check_nan_inf_mpq (void) { mpfr_t mpfr_value, mpfr_cmp; mpq_t mpq_value; int status; mpfr_init2 (mpfr_value, MPFR_PREC_MIN); mpq_init (mpq_value); mpq_set_si (mpq_value, 0, 0); mpz_set_si (mpq_denref (mpq_value), 0); status = mpfr_set_q (mpfr_value, mpq_value, MPFR_RNDN); if ((status != 0) || (!MPFR_IS_NAN (mpfr_value))) { mpfr_init2 (mpfr_cmp, MPFR_PREC_MIN); mpfr_set_nan (mpfr_cmp); printf ("mpfr_set_q with a NAN mpq value returned a wrong value :\n" " waiting for "); mpfr_print_binary (mpfr_cmp); printf (" got "); mpfr_print_binary (mpfr_value); printf ("\n trinary value is %d\n", status); exit (1); } mpq_set_si (mpq_value, -1, 0); mpz_set_si (mpq_denref (mpq_value), 0); status = mpfr_set_q (mpfr_value, mpq_value, MPFR_RNDN); if ((status != 0) || (!MPFR_IS_INF (mpfr_value)) || (MPFR_SIGN(mpfr_value) != mpq_sgn(mpq_value))) { mpfr_init2 (mpfr_cmp, MPFR_PREC_MIN); mpfr_set_inf (mpfr_cmp, -1); printf ("mpfr_set_q with a -INF mpq value returned a wrong value :\n" " waiting for "); mpfr_print_binary (mpfr_cmp); printf (" got "); mpfr_print_binary (mpfr_value); printf ("\n trinary value is %d\n", status); exit (1); } mpq_clear (mpq_value); mpfr_clear (mpfr_value); }
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); } }
void mpfr_fprint_binary (FILE *stream, mpfr_srcptr x) { if (MPFR_IS_NAN (x)) { fprintf (stream, "@NaN@"); return; } if (MPFR_SIGN (x) < 0) fprintf (stream, "-"); if (MPFR_IS_INF (x)) fprintf (stream, "@Inf@"); else if (MPFR_IS_ZERO (x)) fprintf (stream, "0"); else { mp_limb_t *mx; mp_prec_t px; mp_size_t n; mx = MPFR_MANT (x); px = MPFR_PREC (x); fprintf (stream, "0."); for (n = (px - 1) / BITS_PER_MP_LIMB; ; n--) { mp_limb_t wd, t; MPFR_ASSERTN (n >= 0); wd = mx[n]; for (t = MPFR_LIMB_HIGHBIT; t != 0; t >>= 1) { putc ((wd & t) == 0 ? '0' : '1', stream); if (--px == 0) { mp_exp_t ex; ex = MPFR_GET_EXP (x); MPFR_ASSERTN (ex >= LONG_MIN && ex <= LONG_MAX); fprintf (stream, "E%ld", (long) ex); return; } } } } }
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); }
static void check_sgn(void) { mpfr_t x; int i, s1, s2; mpfr_init(x); for(i = 0 ; i < 100 ; i++) { mpfr_urandomb (x, RANDS); if (i&1) { MPFR_SET_POS(x); s2 = 1; } else { MPFR_SET_NEG(x); s2 = -1; } s1 = mpfr_sgn(x); if (s1 < -1 || s1 > 1) { printf("Error for sgn: out of range.\n"); goto lexit; } else if (MPFR_IS_NAN(x) || MPFR_IS_ZERO(x)) { if (s1 != 0) { printf("Error for sgn: Nan or Zero should return 0.\n"); goto lexit; } } else if (s1 != s2) { printf("Error for sgn. Return %d instead of %d.\n", s1, s2); goto lexit; } } mpfr_clear(x); return; lexit: mpfr_clear(x); exit(1); }
int mpfr_erfc (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd) { int inex; mpfr_t tmp; mpfr_exp_t te, err; mpfr_prec_t prec; mpfr_exp_t emin = mpfr_get_emin (); 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), ("y[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (y), mpfr_log_prec, y, inex)); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) { if (MPFR_IS_NAN (x)) { MPFR_SET_NAN (y); MPFR_RET_NAN; } /* erfc(+inf) = 0+, erfc(-inf) = 2 erfc (0) = 1 */ else if (MPFR_IS_INF (x)) return mpfr_set_ui (y, MPFR_IS_POS (x) ? 0 : 2, rnd); else return mpfr_set_ui (y, 1, rnd); } if (MPFR_SIGN (x) > 0) { /* by default, emin = 1-2^30, thus the smallest representable number is 1/2*2^emin = 2^(-2^30): for x >= 27282, erfc(x) < 2^(-2^30-1), and for x >= 1787897414, erfc(x) < 2^(-2^62-1). */ if ((emin >= -1073741823 && mpfr_cmp_ui (x, 27282) >= 0) || mpfr_cmp_ui (x, 1787897414) >= 0) { /* May be incorrect if MPFR_EMAX_MAX >= 2^62. */ MPFR_ASSERTN ((MPFR_EMAX_MAX >> 31) >> 31 == 0); return mpfr_underflow (y, (rnd == MPFR_RNDN) ? MPFR_RNDZ : rnd, 1); } }
int mpfr_ui_sub (mpfr_ptr y, unsigned long int u, mpfr_srcptr x, mpfr_rnd_t rnd_mode) { mpfr_t uu; mp_limb_t up[1]; unsigned long cnt; MPFR_LOG_FUNC (("u=%lu x[%Pu]=%.*Rg rnd=%d", u, mpfr_get_prec(x), mpfr_log_prec, x, rnd_mode), ("y[%Pu]=%.*Rg", mpfr_get_prec(y), mpfr_log_prec, y)); if (MPFR_UNLIKELY (u == 0)) return mpfr_neg (y, x, rnd_mode); 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)) { /* u - Inf = -Inf and u - -Inf = +Inf */ MPFR_SET_INF(y); MPFR_SET_OPPOSITE_SIGN(y,x); MPFR_RET(0); /* +/-infinity is exact */ } else /* x is zero */ /* u - 0 = u */ return mpfr_set_ui(y, u, rnd_mode); } else { MPFR_TMP_INIT1 (up, uu, GMP_NUMB_BITS); MPFR_ASSERTN(u == (mp_limb_t) u); count_leading_zeros (cnt, (mp_limb_t) u); *up = (mp_limb_t) u << cnt; MPFR_SET_EXP (uu, GMP_NUMB_BITS - cnt); return mpfr_sub (y, uu, x, rnd_mode); } }
void checknan (double x, double y, mp_rnd_t rnd_mode, unsigned int px, unsigned int py, unsigned int pz) { double z2; mpfr_t xx, yy, zz; mpfr_init2(xx, px); mpfr_init2(yy, py); mpfr_init2(zz, pz); mpfr_set_d(xx, x, rnd_mode); mpfr_set_d(yy, y, rnd_mode); mpfr_add(zz, xx, yy, rnd_mode); #ifdef MPFR_HAVE_FESETROUND mpfr_set_machine_rnd_mode(rnd_mode); #endif if (MPFR_IS_NAN(zz) == 0) { printf("Error, not an MPFR_NAN for xx = %1.20e, y = %1.20e\n", x, y); exit(1); } z2 = mpfr_get_d1 (zz); if (!isnan(z2)) { printf("Error, not a NaN after conversion, xx = %1.20e yy = %1.20e, got %1.20e\n", x, y, z2); exit(1); } mpfr_clear(xx); mpfr_clear(yy); mpfr_clear(zz); }
int main (int argc, char *argv[]) { double x, z; mpfr_t w; unsigned long k; mpfr_init2(w, 53); mpfr_set_inf (w, 1); mpfr_mul_2exp (w, w, 10, GMP_RNDZ); if (!MPFR_IS_INF(w)) { fprintf(stderr, "Inf != Inf"); exit(-1); } mpfr_set_nan (w); mpfr_mul_2exp (w, w, 10, GMP_RNDZ); if (!MPFR_IS_NAN(w)) { fprintf(stderr, "NaN != NaN"); exit(-1); } SEED_RAND (time(NULL)); for (k = 0; k < 100000; k++) { x = DBL_RAND (); mpfr_set_d (w, x, 0); mpfr_mul_2exp (w, w, 10, GMP_RNDZ); if (x != (z = mpfr_get_d1 (w)/1024)) { fprintf(stderr, "%f != %f\n", x, z); return -1; } mpfr_set_d(w, x, 0); mpfr_div_2exp(w, w, 10, GMP_RNDZ); if (x != (z = mpfr_get_d1 (w)*1024)) { fprintf(stderr, "%f != %f\n", x, z); mpfr_clear(w); return -1; } } mpfr_clear(w); return 0; }
int mpfr_ui_sub (mpfr_ptr y, unsigned long int u, mpfr_srcptr x, mp_rnd_t rnd_mode) { mpfr_t uu; mp_limb_t up[1]; unsigned long cnt; if (MPFR_UNLIKELY (u == 0)) return mpfr_neg (y, x, rnd_mode); 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)) { /* u - Inf = -Inf and u - -Inf = +Inf */ MPFR_SET_INF(y); MPFR_SET_OPPOSITE_SIGN(y,x); MPFR_RET(0); /* +/-infinity is exact */ } else /* x is zero */ /* u - 0 = u */ return mpfr_set_ui(y, u, rnd_mode); } else { MPFR_TMP_INIT1 (up, uu, BITS_PER_MP_LIMB); MPFR_ASSERTN(u == (mp_limb_t) u); count_leading_zeros (cnt, (mp_limb_t) u); *up = (mp_limb_t) u << cnt; MPFR_SET_EXP (uu, BITS_PER_MP_LIMB - cnt); return mpfr_sub (y, uu, x, rnd_mode); } }