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); }
static mpfr_prec_t get_prec_max (mpfr_t *tab, unsigned long n, mpfr_prec_t f) { mpfr_prec_t res; mpfr_exp_t min, max; unsigned long i; i = 0; while (MPFR_IS_ZERO (tab[i])) { i++; if (i == n) return MPFR_PREC_MIN; /* all values are 0 */ } if (! mpfr_check (tab[i])) { printf ("tab[%lu] is not valid.\n", i); exit (1); } MPFR_ASSERTN (MPFR_IS_FP (tab[i])); min = max = MPFR_GET_EXP(tab[i]); for (i++; i < n; i++) { if (! mpfr_check (tab[i])) { printf ("tab[%lu] is not valid.\n", i); exit (1); } MPFR_ASSERTN (MPFR_IS_FP (tab[i])); if (! MPFR_IS_ZERO (tab[i])) { if (MPFR_GET_EXP(tab[i]) > max) max = MPFR_GET_EXP(tab[i]); if (MPFR_GET_EXP(tab[i]) < min) min = MPFR_GET_EXP(tab[i]); } } res = max - min; res += f; res += __gmpfr_ceil_log2 (n) + 1; return res; }
int mpfr_check_range (mpfr_ptr x, mp_rnd_t rnd_mode) { if (MPFR_IS_FP(x) && MPFR_NOTZERO(x)) { /* x is a non-zero FP */ mp_exp_t exp = MPFR_EXP(x); if (exp < __mpfr_emin) return mpfr_set_underflow(x, rnd_mode, MPFR_SIGN(x)); if (exp > __mpfr_emax) return mpfr_set_overflow(x, rnd_mode, MPFR_SIGN(x)); } return 0; }
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_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; }
void mpfr_get_z (mpz_ptr z, mpfr_srcptr f, mp_rnd_t rnd) { mpfr_t r; mp_exp_t exp = MPFR_EXP (f); /* if exp <= 0, then |f|<1, thus |o(f)|<=1 */ MPFR_ASSERTN (exp < 0 || exp <= MPFR_PREC_MAX); mpfr_init2 (r, (exp < (mp_exp_t) MPFR_PREC_MIN ? MPFR_PREC_MIN : (mpfr_prec_t) exp)); mpfr_rint (r, f, rnd); MPFR_ASSERTN (MPFR_IS_FP (r) ); exp = mpfr_get_z_exp (z, r); if (exp >= 0) mpz_mul_2exp (z, z, exp); else mpz_div_2exp (z, z, -exp); mpfr_clear (r); }
int mpfr_div_2si (mpfr_ptr y, mpfr_srcptr x, long int n, mp_rnd_t rnd_mode) { int inexact; inexact = y != x ? mpfr_set (y, x, rnd_mode) : 0; if (MPFR_IS_FP(y) && MPFR_NOTZERO(y)) { if (n > 0 && (__mpfr_emin > MPFR_EMAX_MAX - n || MPFR_EXP(y) < __mpfr_emin + n)) return mpfr_set_underflow (y, rnd_mode, MPFR_SIGN(y)); if (n < 0 && (__mpfr_emax < MPFR_EMIN_MIN - n || MPFR_EXP(y) > __mpfr_emax + n)) return mpfr_set_overflow (y, rnd_mode, MPFR_SIGN(y)); MPFR_EXP(y) -= n; } return inexact; }
mp_exp_t mpfr_get_z_exp (mpz_ptr z, mpfr_srcptr f) { mp_size_t fn; int sh; MPFR_ASSERTD (MPFR_IS_FP (f)); if (MPFR_UNLIKELY (MPFR_IS_ZERO (f))) { mpz_set_ui (z, 0); return __gmpfr_emin; } fn = MPFR_LIMB_SIZE(f); /* check whether allocated space for z is enough */ if (MPFR_UNLIKELY (ALLOC (z) < fn)) MPZ_REALLOC (z, fn); MPFR_UNSIGNED_MINUS_MODULO (sh, MPFR_PREC (f)); if (MPFR_LIKELY (sh)) mpn_rshift (PTR (z), MPFR_MANT (f), fn, sh); else MPN_COPY (PTR (z), MPFR_MANT (f), fn); SIZ(z) = MPFR_IS_NEG (f) ? -fn : fn; /* Test if the result is representable. Later, we could choose to return MPFR_EXP_MIN if it isn't, or perhaps MPFR_EXP_MAX to signal an error. The mantissa would still be meaningful. */ MPFR_ASSERTD ((mp_exp_unsigned_t) MPFR_GET_EXP (f) - MPFR_EXP_MIN >= (mp_exp_unsigned_t) MPFR_PREC(f)); return MPFR_GET_EXP (f) - MPFR_PREC (f); }
static void check_max(void) { mpfr_t xx, yy, zz; mpfr_exp_t emin; mpfr_init2(xx, 4); mpfr_init2(yy, 4); mpfr_init2(zz, 4); mpfr_set_str1 (xx, "0.68750"); mpfr_mul_2si(xx, xx, MPFR_EMAX_DEFAULT/2, MPFR_RNDN); mpfr_set_str1 (yy, "0.68750"); mpfr_mul_2si(yy, yy, MPFR_EMAX_DEFAULT - MPFR_EMAX_DEFAULT/2 + 1, MPFR_RNDN); mpfr_clear_flags(); test_mul(zz, xx, yy, MPFR_RNDU); if (!(mpfr_overflow_p() && MPFR_IS_INF(zz))) { printf("check_max failed (should be an overflow)\n"); exit(1); } mpfr_clear_flags(); test_mul(zz, xx, yy, MPFR_RNDD); if (mpfr_overflow_p() || MPFR_IS_INF(zz)) { printf("check_max failed (should NOT be an overflow)\n"); exit(1); } mpfr_set_str1 (xx, "0.93750"); mpfr_mul_2si(xx, xx, MPFR_EMAX_DEFAULT, MPFR_RNDN); if (!(MPFR_IS_FP(xx) && MPFR_IS_FP(zz))) { printf("check_max failed (internal error)\n"); exit(1); } if (mpfr_cmp(xx, zz) != 0) { printf("check_max failed: got "); mpfr_out_str(stdout, 2, 0, zz, MPFR_RNDZ); printf(" instead of "); mpfr_out_str(stdout, 2, 0, xx, MPFR_RNDZ); printf("\n"); exit(1); } /* check underflow */ emin = mpfr_get_emin (); set_emin (0); mpfr_set_str_binary (xx, "0.1E0"); mpfr_set_str_binary (yy, "0.1E0"); test_mul (zz, xx, yy, MPFR_RNDN); /* exact result is 0.1E-1, which should round to 0 */ MPFR_ASSERTN(mpfr_cmp_ui (zz, 0) == 0 && MPFR_IS_POS(zz)); set_emin (emin); /* coverage test for mpfr_powerof2_raw */ emin = mpfr_get_emin (); set_emin (0); mpfr_set_prec (xx, mp_bits_per_limb + 1); mpfr_set_str_binary (xx, "0.1E0"); mpfr_nextabove (xx); mpfr_set_str_binary (yy, "0.1E0"); test_mul (zz, xx, yy, MPFR_RNDN); /* exact result is just above 0.1E-1, which should round to minfloat */ MPFR_ASSERTN(mpfr_cmp (zz, yy) == 0); set_emin (emin); mpfr_clear(xx); mpfr_clear(yy); mpfr_clear(zz); }
int mpfr_number_p (mpfr_srcptr x) { return MPFR_IS_FP(x); }
static void underflows (void) { mpfr_t x, y, z; int err = 0; int inexact; int i; mp_exp_t emin; mpfr_init2 (x, 64); mpfr_init2 (y, 64); mpfr_set_ui (x, 1, GMP_RNDN); mpfr_set_exp (x, mpfr_get_emin()); for (i = 3; i < 10; i++) { mpfr_set_ui (y, i, GMP_RNDN); mpfr_div_2ui (y, y, 1, GMP_RNDN); test_pow (y, x, y, GMP_RNDN); if (!MPFR_IS_FP(y) || mpfr_cmp_ui (y, 0)) { printf ("Error in mpfr_pow for "); mpfr_out_str (stdout, 2, 0, x, GMP_RNDN); printf (" ^ (%d/2)\nGot ", i); mpfr_out_str (stdout, 2, 0, y, GMP_RNDN); printf (" instead of 0.\n"); exit (1); } } mpfr_init2 (z, 55); mpfr_set_str (x, "0.110011010011101001110001110100010000110111101E0", 2, GMP_RNDN); mpfr_set_str (y, "0.101110010011111001011010100011011100111110011E40", 2, GMP_RNDN); mpfr_clear_flags (); inexact = mpfr_pow (z, x, y, GMP_RNDU); if (!mpfr_underflow_p ()) { printf ("Underflow flag is not set for special underflow test.\n"); err = 1; } if (inexact <= 0) { printf ("Ternary value is wrong for special underflow test.\n"); err = 1; } mpfr_set_ui (x, 0, GMP_RNDN); mpfr_nextabove (x); if (mpfr_cmp (x, z) != 0) { printf ("Wrong value for special underflow test.\nGot "); mpfr_out_str (stdout, 2, 0, z, GMP_RNDN); printf ("\ninstead of "); mpfr_out_str (stdout, 2, 2, x, GMP_RNDN); printf ("\n"); err = 1; } if (err) exit (1); /* MPFR currently (2006-08-19) segfaults on the following code (and possibly makes other programs crash due to the lack of memory), because y is converted into an mpz_t, and the required precision is too high. */ mpfr_set_prec (x, 2); mpfr_set_prec (y, 2); mpfr_set_prec (z, 12); mpfr_set_ui_2exp (x, 3, -2, GMP_RNDN); mpfr_set_ui_2exp (y, 1, mpfr_get_emax () - 1, GMP_RNDN); mpfr_clear_flags (); mpfr_pow (z, x, y, GMP_RNDN); if (!mpfr_underflow_p () || MPFR_NOTZERO (z)) { printf ("Underflow test with large y fails.\n"); exit (1); } emin = mpfr_get_emin (); mpfr_set_emin (-256); mpfr_set_prec (x, 2); mpfr_set_prec (y, 2); mpfr_set_prec (z, 12); mpfr_set_ui_2exp (x, 3, -2, GMP_RNDN); mpfr_set_ui_2exp (y, 1, 38, GMP_RNDN); mpfr_clear_flags (); inexact = mpfr_pow (z, x, y, GMP_RNDN); if (!mpfr_underflow_p () || MPFR_NOTZERO (z) || inexact >= 0) { printf ("Bad underflow detection for 0.75^(2^38). Obtained:\n" "Underflow flag... %-3s (should be 'yes')\n" "Zero result...... %-3s (should be 'yes')\n" "Inexact value.... %-3d (should be negative)\n", mpfr_underflow_p () ? "yes" : "no", MPFR_IS_ZERO (z) ? "yes" : "no", inexact); exit (1); } mpfr_set_emin (emin); emin = mpfr_get_emin (); mpfr_set_emin (-256); mpfr_set_prec (x, 2); mpfr_set_prec (y, 40); mpfr_set_prec (z, 12); mpfr_set_ui_2exp (x, 3, -1, GMP_RNDN); mpfr_set_si_2exp (y, -1, 38, GMP_RNDN); for (i = 0; i < 4; i++) { if (i == 2) mpfr_neg (x, x, GMP_RNDN); mpfr_clear_flags (); inexact = mpfr_pow (z, x, y, GMP_RNDN); if (!mpfr_underflow_p () || MPFR_NOTZERO (z) || (i == 3 ? (inexact <= 0) : (inexact >= 0))) { printf ("Bad underflow detection for ("); mpfr_out_str (stdout, 10, 0, x, GMP_RNDN); printf (")^(-2^38-%d). Obtained:\n" "Overflow flag.... %-3s (should be 'no')\n" "Underflow flag... %-3s (should be 'yes')\n" "Zero result...... %-3s (should be 'yes')\n" "Inexact value.... %-3d (should be %s)\n", i, mpfr_overflow_p () ? "yes" : "no", mpfr_underflow_p () ? "yes" : "no", MPFR_IS_ZERO (z) ? "yes" : "no", inexact, i == 3 ? "positive" : "negative"); exit (1); } inexact = mpfr_sub_ui (y, y, 1, GMP_RNDN); MPFR_ASSERTN (inexact == 0); } mpfr_set_emin (emin); mpfr_clears (x, y, z, (void *) 0); }
static void test_urandomb (long nbtests, mpfr_prec_t prec, int verbose) { mpfr_t x; int *tab, size_tab, k, sh, xn; double d, av = 0, var = 0, chi2 = 0, th; mpfr_exp_t emin; size_tab = (nbtests >= 1000 ? nbtests / 50 : 20); tab = (int *) calloc (size_tab, sizeof(int)); if (tab == NULL) { fprintf (stderr, "trandom: can't allocate memory in test_urandomb\n"); exit (1); } mpfr_init2 (x, prec); xn = 1 + (prec - 1) / mp_bits_per_limb; sh = xn * mp_bits_per_limb - prec; for (k = 0; k < nbtests; k++) { mpfr_urandomb (x, RANDS); MPFR_ASSERTN (MPFR_IS_FP (x)); /* check that lower bits are zero */ if (MPFR_NOTZERO(x) && (MPFR_MANT(x)[0] & MPFR_LIMB_MASK(sh))) { printf ("Error: mpfr_urandomb() returns invalid numbers:\n"); mpfr_dump (x); exit (1); } d = mpfr_get_d1 (x); av += d; var += d*d; tab[(int)(size_tab * d)]++; } /* coverage test */ emin = mpfr_get_emin (); set_emin (1); /* the generated number in [0,1[ is not in the exponent range, except if it is zero */ k = mpfr_urandomb (x, RANDS); if (MPFR_IS_ZERO(x) == 0 && (k == 0 || mpfr_nan_p (x) == 0)) { printf ("Error in mpfr_urandomb, expected NaN, got "); mpfr_dump (x); exit (1); } set_emin (emin); mpfr_clear (x); if (!verbose) { free(tab); return; } av /= nbtests; var = (var / nbtests) - av * av; th = (double)nbtests / size_tab; printf("Average = %.5f\nVariance = %.5f\n", av, var); printf("Repartition for urandomb. Each integer should be close to %d.\n", (int)th); for (k = 0; k < size_tab; k++) { chi2 += (tab[k] - th) * (tab[k] - th) / th; printf("%d ", tab[k]); if (((k+1) & 7) == 0) printf("\n"); } printf("\nChi2 statistics value (with %d degrees of freedom) : %.5f\n\n", size_tab - 1, chi2); free(tab); return; }
int main (int argc, char *argv[]) { long nbtests; mpfr_prec_t prec; int verbose = 0; tests_start_mpfr (); if (argc > 1) verbose = 1; nbtests = 10000; if (argc > 1) { long a = atol(argv[1]); if (a != 0) nbtests = a; } if (argc <= 2) prec = 1000; else prec = atol(argv[2]); test_urandomb (nbtests, prec, verbose); if (argc == 1) /* check also small precision */ { test_urandomb (nbtests, 2, 0); } #ifndef MPFR_USE_MINI_GMP /* Since these tests assume a deterministic random generator, and this is not implemented in mini-gmp, we omit them with mini-gmp. */ bug20100914 (); #if __MPFR_GMP(4,2,0) /* Get a non-zero fixed-point number whose first 32 bits are 0 with the default GMP PRNG. This corresponds to the case cnt == 0 && k != 0 in src/urandomb.c (fixed in r8762) with the 32-bit ABI. */ { gmp_randstate_t s; mpfr_t x; char *str = "0.1010111100000000000000000000000000000000E-32"; int k; gmp_randinit_default (s); gmp_randseed_ui (s, 4518); mpfr_init2 (x, 40); for (k = 0; k < 575123; k++) { mpfr_urandomb (x, s); MPFR_ASSERTN (MPFR_IS_FP (x)); } if (mpfr_cmp_str (x, str, 2, MPFR_RNDN) != 0) { printf ("Error in test_urandomb:\n"); printf ("Expected %s\n", str); printf ("Got "); mpfr_dump (x); exit (1); } mpfr_clear (x); gmp_randclear (s); } #endif #endif tests_end_mpfr (); return 0; }
static void tst (void) { int sv = sizeof (val) / sizeof (*val); int i, j; int rnd; mpfr_t x, y, z, tmp; mpfr_inits2 (53, x, y, z, tmp, (mpfr_ptr) 0); for (i = 0; i < sv; i++) for (j = 0; j < sv; j++) RND_LOOP (rnd) { int exact, inex; unsigned int flags; if (my_setstr (x, val[i]) || my_setstr (y, val[j])) { printf ("internal error for (%d,%d,%d)\n", i, j, rnd); exit (1); } mpfr_clear_flags (); inex = mpfr_pow (z, x, y, (mpfr_rnd_t) rnd); flags = __gmpfr_flags; if (! MPFR_IS_NAN (z) && mpfr_nanflag_p ()) err ("got NaN flag without NaN value", i, j, rnd, z, inex); if (MPFR_IS_NAN (z) && ! mpfr_nanflag_p ()) err ("got NaN value without NaN flag", i, j, rnd, z, inex); if (inex != 0 && ! mpfr_inexflag_p ()) err ("got non-zero ternary value without inexact flag", i, j, rnd, z, inex); if (inex == 0 && mpfr_inexflag_p ()) err ("got null ternary value with inexact flag", i, j, rnd, z, inex); if (i >= 3 && j >= 3) { if (mpfr_underflow_p ()) err ("got underflow", i, j, rnd, z, inex); if (mpfr_overflow_p ()) err ("got overflow", i, j, rnd, z, inex); exact = MPFR_IS_SINGULAR (z) || (mpfr_mul_2ui (tmp, z, 16, MPFR_RNDN), mpfr_integer_p (tmp)); if (exact && inex != 0) err ("got exact value with ternary flag different from 0", i, j, rnd, z, inex); if (! exact && inex == 0) err ("got inexact value with ternary flag equal to 0", i, j, rnd, z, inex); } if (MPFR_IS_ZERO (x) && ! MPFR_IS_NAN (y) && MPFR_NOTZERO (y)) { if (MPFR_IS_NEG (y) && ! MPFR_IS_INF (z)) err ("expected an infinity", i, j, rnd, z, inex); if (MPFR_IS_POS (y) && ! MPFR_IS_ZERO (z)) err ("expected a zero", i, j, rnd, z, inex); if ((MPFR_IS_NEG (x) && is_odd (y)) ^ MPFR_IS_NEG (z)) err ("wrong sign", i, j, rnd, z, inex); } if (! MPFR_IS_NAN (x) && mpfr_cmp_si (x, -1) == 0) { /* x = -1 */ if (! (MPFR_IS_INF (y) || mpfr_integer_p (y)) && ! MPFR_IS_NAN (z)) err ("expected NaN", i, j, rnd, z, inex); if ((MPFR_IS_INF (y) || (mpfr_integer_p (y) && ! is_odd (y))) && ! mpfr_equal_p (z, __gmpfr_one)) err ("expected 1", i, j, rnd, z, inex); if (is_odd (y) && (MPFR_IS_NAN (z) || mpfr_cmp_si (z, -1) != 0)) err ("expected -1", i, j, rnd, z, inex); } if ((mpfr_equal_p (x, __gmpfr_one) || MPFR_IS_ZERO (y)) && ! mpfr_equal_p (z, __gmpfr_one)) err ("expected 1", i, j, rnd, z, inex); if (MPFR_IS_PURE_FP (x) && MPFR_IS_NEG (x) && MPFR_IS_FP (y) && ! mpfr_integer_p (y) && ! MPFR_IS_NAN (z)) err ("expected NaN", i, j, rnd, z, inex); if (MPFR_IS_INF (y) && MPFR_NOTZERO (x)) { int cmpabs1 = mpfr_cmpabs (x, __gmpfr_one); if ((MPFR_IS_NEG (y) ? (cmpabs1 < 0) : (cmpabs1 > 0)) && ! (MPFR_IS_POS (z) && MPFR_IS_INF (z))) err ("expected +Inf", i, j, rnd, z, inex); if ((MPFR_IS_NEG (y) ? (cmpabs1 > 0) : (cmpabs1 < 0)) && ! (MPFR_IS_POS (z) && MPFR_IS_ZERO (z))) err ("expected +0", i, j, rnd, z, inex); } if (MPFR_IS_INF (x) && ! MPFR_IS_NAN (y) && MPFR_NOTZERO (y)) { if (MPFR_IS_POS (y) && ! MPFR_IS_INF (z)) err ("expected an infinity", i, j, rnd, z, inex); if (MPFR_IS_NEG (y) && ! MPFR_IS_ZERO (z)) err ("expected a zero", i, j, rnd, z, inex); if ((MPFR_IS_NEG (x) && is_odd (y)) ^ MPFR_IS_NEG (z)) err ("wrong sign", i, j, rnd, z, inex); } test_others (val[i], val[j], (mpfr_rnd_t) rnd, x, y, z, inex, flags, "tst"); } mpfr_clears (x, y, z, tmp, (mpfr_ptr) 0); }
int mpfr_fma (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, mp_rnd_t rnd_mode) { int inexact; mpfr_t u; /* particular cases */ if (MPFR_IS_NAN(x) || MPFR_IS_NAN(y) || MPFR_IS_NAN(z)) { MPFR_SET_NAN(s); MPFR_RET_NAN; } if (MPFR_IS_INF(x) || MPFR_IS_INF(y)) { /* cases Inf*0+z, 0*Inf+z, Inf-Inf */ if ((MPFR_IS_FP(y) && MPFR_IS_ZERO(y)) || (MPFR_IS_FP(x) && MPFR_IS_ZERO(x)) || (MPFR_IS_INF(z) && ((MPFR_SIGN(x) * MPFR_SIGN(y)) != MPFR_SIGN(z)))) { MPFR_SET_NAN(s); MPFR_RET_NAN; } MPFR_CLEAR_NAN(s); if (MPFR_IS_INF(z)) /* case Inf-Inf already checked above */ { MPFR_SET_INF(s); MPFR_SET_SAME_SIGN(s, z); MPFR_RET(0); } else /* z is finite */ { MPFR_SET_INF(s); if (MPFR_SIGN(s) != (MPFR_SIGN(x) * MPFR_SIGN(y))) MPFR_CHANGE_SIGN(s); MPFR_RET(0); } } MPFR_CLEAR_NAN(s); /* now x and y are finite */ if (MPFR_IS_INF(z)) { MPFR_SET_INF(s); MPFR_SET_SAME_SIGN(s, z); MPFR_RET(0); } MPFR_CLEAR_INF(s); if (MPFR_IS_ZERO(x) || MPFR_IS_ZERO(y)) { if (MPFR_IS_ZERO(z)) { int sign_p, sign_z; sign_p = MPFR_SIGN(x) * MPFR_SIGN(y); sign_z = MPFR_SIGN(z); if (MPFR_SIGN(s) != (rnd_mode != GMP_RNDD ? ((sign_p < 0 && sign_z < 0) ? -1 : 1) : ((sign_p > 0 && sign_z > 0) ? 1 : -1))) { MPFR_CHANGE_SIGN(s); } MPFR_SET_ZERO(s); MPFR_RET(0); } else return mpfr_set (s, z, rnd_mode); } if (MPFR_IS_ZERO(z)) return mpfr_mul (s, x, y, rnd_mode); /* if we take prec(u) >= prec(x) + prec(y), the product u <- x*y is always exact */ mpfr_init2 (u, MPFR_PREC(x) + MPFR_PREC(y)); mpfr_mul (u, x, y, GMP_RNDN); /* always exact */ inexact = mpfr_add (s, z, u, rnd_mode); mpfr_clear(u); return inexact; }