static void check_intmax (void) { #ifdef _MPFR_H_HAVE_INTMAX_T mpfr_t x; mpfr_init2 (x, sizeof(uintmax_t)*CHAR_BIT); /* Check NAN */ mpfr_set_nan(x); if (mpfr_fits_uintmax_p(x, GMP_RNDN)) ERROR1; if (mpfr_fits_intmax_p(x, GMP_RNDN)) ERROR1; /* Check INF */ mpfr_set_inf(x, 1); if (mpfr_fits_uintmax_p(x, GMP_RNDN)) ERROR1; if (mpfr_fits_intmax_p(x, GMP_RNDN)) ERROR1; /* Check Zero */ MPFR_SET_ZERO(x); if (!mpfr_fits_uintmax_p(x, GMP_RNDN)) ERROR2; if (!mpfr_fits_intmax_p(x, GMP_RNDN)) ERROR2; /* Check small op */ mpfr_set_str1 (x, "1@-1"); if (!mpfr_fits_uintmax_p(x, GMP_RNDN)) ERROR2; if (!mpfr_fits_intmax_p(x, GMP_RNDN)) ERROR2; /* Check all other values */ mpfr_set_uj (x, UINTMAX_MAX, GMP_RNDN); mpfr_add_ui (x, x, 1, GMP_RNDN); if (mpfr_fits_uintmax_p (x, GMP_RNDN)) ERROR1; mpfr_set_uj (x, UINTMAX_MAX, GMP_RNDN); if (!mpfr_fits_uintmax_p (x, GMP_RNDN)) ERROR2; mpfr_set_sj (x, INTMAX_MAX, GMP_RNDN); mpfr_add_ui (x, x, 1, GMP_RNDN); if (mpfr_fits_intmax_p (x, GMP_RNDN)) ERROR1; mpfr_set_sj (x, INTMAX_MAX, GMP_RNDN); if (!mpfr_fits_intmax_p (x, GMP_RNDN)) ERROR2; mpfr_set_sj (x, INTMAX_MIN, GMP_RNDN); if (!mpfr_fits_intmax_p (x, GMP_RNDN)) ERROR2; mpfr_sub_ui (x, x, 1, GMP_RNDN); if (mpfr_fits_intmax_p (x, GMP_RNDN)) ERROR1; mpfr_clear (x); #endif }
static void check_set_sj (void) { mpfr_t x; int inex; mpfr_init2 (x, sizeof(intmax_t)*CHAR_BIT-1); inex = mpfr_set_sj (x, -MPFR_INTMAX_MAX, MPFR_RNDN); inex |= mpfr_add_si (x, x, -1, MPFR_RNDN); if (inex || mpfr_sgn (x) >=0 || !mpfr_powerof2_raw (x) || MPFR_EXP (x) != (sizeof(intmax_t)*CHAR_BIT) ) ERROR("set_sj (-INTMAX_MAX)"); inex = mpfr_set_sj (x, 1742, MPFR_RNDN); if (inex || mpfr_cmp_ui (x, 1742)) ERROR ("set_sj (1742)"); mpfr_clear (x); }
static void check_erange (void) { mpfr_t x; uintmax_t dl; intmax_t d; /* Test for ERANGE flag + correct behaviour if overflow */ mpfr_init2 (x, 256); mpfr_set_uj (x, MPFR_UINTMAX_MAX, MPFR_RNDN); mpfr_clear_erangeflag (); dl = mpfr_get_uj (x, MPFR_RNDN); if (dl != MPFR_UINTMAX_MAX || mpfr_erangeflag_p ()) { printf ("ERROR for get_uj + ERANGE + UINTMAX_MAX (1)\n"); exit (1); } mpfr_add_ui (x, x, 1, MPFR_RNDN); dl = mpfr_get_uj (x, MPFR_RNDN); if (dl != MPFR_UINTMAX_MAX || !mpfr_erangeflag_p ()) { printf ("ERROR for get_uj + ERANGE + UINTMAX_MAX (2)\n"); exit (1); } mpfr_set_sj (x, -1, MPFR_RNDN); mpfr_clear_erangeflag (); dl = mpfr_get_uj (x, MPFR_RNDN); if (dl != 0 || !mpfr_erangeflag_p ()) { printf ("ERROR for get_uj + ERANGE + -1 \n"); exit (1); } mpfr_set_sj (x, MPFR_INTMAX_MAX, MPFR_RNDN); mpfr_clear_erangeflag (); d = mpfr_get_sj (x, MPFR_RNDN); if (d != MPFR_INTMAX_MAX || mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + ERANGE + INTMAX_MAX (1)\n"); exit (1); } mpfr_add_ui (x, x, 1, MPFR_RNDN); d = mpfr_get_sj (x, MPFR_RNDN); if (d != MPFR_INTMAX_MAX || !mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + ERANGE + INTMAX_MAX (2)\n"); exit (1); } mpfr_set_sj (x, MPFR_INTMAX_MIN, MPFR_RNDN); mpfr_clear_erangeflag (); d = mpfr_get_sj (x, MPFR_RNDN); if (d != MPFR_INTMAX_MIN || mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + ERANGE + INTMAX_MIN (1)\n"); exit (1); } mpfr_sub_ui (x, x, 1, MPFR_RNDN); d = mpfr_get_sj (x, MPFR_RNDN); if (d != MPFR_INTMAX_MIN || !mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + ERANGE + INTMAX_MIN (2)\n"); exit (1); } mpfr_set_nan (x); mpfr_clear_erangeflag (); d = mpfr_get_uj (x, MPFR_RNDN); if (d != 0 || !mpfr_erangeflag_p ()) { printf ("ERROR for get_uj + NaN\n"); exit (1); } mpfr_clear_erangeflag (); d = mpfr_get_sj (x, MPFR_RNDN); if (d != 0 || !mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + NaN\n"); exit (1); } mpfr_clear (x); }
/* We can't use fits_s.h <= mpfr_cmp_ui */ int mpfr_fits_intmax_p (mpfr_srcptr f, mpfr_rnd_t rnd) { mpfr_exp_t e; int prec; mpfr_t x, y; int neg; int res; if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f))) /* Zero always fit */ return MPFR_IS_ZERO (f) ? 1 : 0; /* now it fits if either (a) MINIMUM <= f <= MAXIMUM (b) or MINIMUM <= round(f, prec(slong), rnd) <= MAXIMUM */ e = MPFR_EXP (f); if (e < 1) return 1; /* |f| < 1: always fits */ neg = MPFR_IS_NEG (f); /* let EXTREMUM be MAXIMUM if f > 0, and MINIMUM if f < 0 */ /* first compute prec(EXTREMUM), this could be done at configure time, but the result can depend on neg (the loop is moved inside the "if" to give the compiler a better chance to compute prec statically) */ if (neg) { uintmax_t s; /* In C89, the division on negative integers isn't well-defined. */ s = SAFE_ABS (uintmax_t, MPFR_INTMAX_MIN); for (prec = 0; s != 0; s /= 2, prec ++); } else { intmax_t s; s = MPFR_INTMAX_MAX; for (prec = 0; s != 0; s /= 2, prec ++); } /* EXTREMUM needs prec bits, i.e. 2^(prec-1) <= |EXTREMUM| < 2^prec */ /* if e <= prec - 1, then f < 2^(prec-1) <= |EXTREMUM| */ if (e <= prec - 1) return 1; /* if e >= prec + 1, then f >= 2^prec > |EXTREMUM| */ if (e >= prec + 1) return 0; MPFR_ASSERTD (e == prec); /* hard case: first round to prec bits, then check */ mpfr_init2 (x, prec); mpfr_set (x, f, rnd); if (neg) { mpfr_init2 (y, prec); mpfr_set_sj (y, MPFR_INTMAX_MIN, MPFR_RNDN); res = mpfr_cmp (x, y) >= 0; mpfr_clear (y); } else { res = MPFR_GET_EXP (x) == e; } mpfr_clear (x); return res; }
static void check_intmax (void) { #ifdef _MPFR_H_HAVE_INTMAX_T mpfr_t x, y; int i, r; mpfr_init2 (x, sizeof (uintmax_t) * CHAR_BIT); mpfr_init2 (y, 8); RND_LOOP (r) { /* Check NAN */ mpfr_set_nan (x); if (mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r)) ERROR1 (52); if (mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (53); /* Check INF */ mpfr_set_inf (x, 1); if (mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r)) ERROR1 (54); if (mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (55); /* Check Zero */ MPFR_SET_ZERO (x); if (!mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r)) ERROR1 (56); if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (57); /* Check positive small op */ mpfr_set_str1 (x, "1@-1"); if (!mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r)) ERROR1 (58); if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (59); /* Check 17 */ mpfr_set_ui (x, 17, MPFR_RNDN); if (!mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r)) ERROR1 (60); if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (61); /* Check hugest */ mpfr_set_ui_2exp (x, 42, sizeof (uintmax_t) * 32, MPFR_RNDN); if (mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r)) ERROR1 (62); if (mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (63); /* Check all other values */ mpfr_set_uj (x, MPFR_UINTMAX_MAX, MPFR_RNDN); mpfr_add_ui (x, x, 1, MPFR_RNDN); if (mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r)) ERROR1 (64); mpfr_set_uj (x, MPFR_UINTMAX_MAX, MPFR_RNDN); if (!mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r)) ERROR1 (65); mpfr_set_sj (x, MPFR_INTMAX_MAX, MPFR_RNDN); mpfr_add_ui (x, x, 1, MPFR_RNDN); if (mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (66); mpfr_set_sj (x, MPFR_INTMAX_MAX, MPFR_RNDN); if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (67); mpfr_set_sj (x, MPFR_INTMAX_MIN, MPFR_RNDN); if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (68); mpfr_sub_ui (x, x, 1, MPFR_RNDN); if (mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (69); /* Check negative op */ for (i = 1; i <= 4; i++) { int inv; mpfr_set_si_2exp (x, -i, -2, MPFR_RNDN); mpfr_rint (y, x, (mpfr_rnd_t) r); inv = MPFR_NOTZERO (y); if (!mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r) ^ inv) ERROR1 (70); if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r)) ERROR1 (71); } } mpfr_clear (x); mpfr_clear (y); #endif }
/* We can't use fits_s.h as it uses mpfr_cmp_si */ int mpfr_fits_intmax_p (mpfr_srcptr f, mpfr_rnd_t rnd) { mpfr_flags_t saved_flags; mpfr_exp_t e; int prec; mpfr_t x, y; int neg; int res; if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f))) /* Zero always fit */ return MPFR_IS_ZERO (f) ? 1 : 0; /* now it fits if either (a) MINIMUM <= f <= MAXIMUM (b) or MINIMUM <= round(f, prec(slong), rnd) <= MAXIMUM */ e = MPFR_EXP (f); if (e < 1) return 1; /* |f| < 1: always fits */ neg = MPFR_IS_NEG (f); /* let EXTREMUM be MAXIMUM if f > 0, and MINIMUM if f < 0 */ /* first compute prec(EXTREMUM), this could be done at configure time, but the result can depend on neg (the loop is moved inside the "if" to give the compiler a better chance to compute prec statically) */ if (neg) { uintmax_t s; /* In C89, the division on negative integers isn't well-defined. */ s = SAFE_ABS (uintmax_t, MPFR_INTMAX_MIN); for (prec = 0; s != 0; s /= 2, prec ++); } else { intmax_t s; s = MPFR_INTMAX_MAX; for (prec = 0; s != 0; s /= 2, prec ++); } /* EXTREMUM needs prec bits, i.e. 2^(prec-1) <= |EXTREMUM| < 2^prec */ /* if e <= prec - 1, then f < 2^(prec-1) <= |EXTREMUM| */ if (e <= prec - 1) return 1; /* if e >= prec + 1, then f >= 2^prec > |EXTREMUM| */ if (e >= prec + 1) return 0; MPFR_ASSERTD (e == prec); /* hard case: first round to prec bits, then check */ saved_flags = __gmpfr_flags; mpfr_init2 (x, prec); /* for RNDF, it is necessary and sufficient to check it fits when rounding away from zero */ mpfr_set (x, f, (rnd == MPFR_RNDF) ? MPFR_RNDA : rnd); if (neg) { mpfr_init2 (y, prec); mpfr_set_sj (y, MPFR_INTMAX_MIN, MPFR_RNDN); res = mpfr_cmp (x, y) >= 0; mpfr_clear (y); } else { /* Warning! Due to the rounding, x can be an infinity. Here we use the fact that singular numbers have a special exponent field, thus well-defined and different from e, in which case this means that the number does not fit. That's why we use MPFR_EXP, not MPFR_GET_EXP. */ res = MPFR_EXP (x) == e; } mpfr_clear (x); __gmpfr_flags = saved_flags; return res; }