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; }
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; }
/* bug reported by Joseph S. Myers on 2013-10-27 https://sympa.inria.fr/sympa/arc/mpfr/2013-10/msg00015.html */ static void bug20131027 (void) { mpfr_t sum, t[4]; mpfr_ptr p[4]; char *s[4] = { "0x1p1000", "-0x0.fffffffffffff80000000000000001p1000", "-0x1p947", "0x1p880" }; int i, r; mpfr_init2 (sum, 53); for (i = 0; i < 4; i++) { mpfr_init2 (t[i], i == 0 ? 53 : 1000); mpfr_set_str (t[i], s[i], 0, MPFR_RNDN); p[i] = t[i]; } RND_LOOP(r) { int expected_sign = (mpfr_rnd_t) r == MPFR_RNDD ? -1 : 1; int inex; inex = mpfr_sum (sum, p, 4, (mpfr_rnd_t) r); if (MPFR_NOTZERO (sum) || MPFR_SIGN (sum) != expected_sign || inex != 0) { printf ("mpfr_sum incorrect in bug20131027 for %s:\n" "expected %c0 with inex = 0, got ", mpfr_print_rnd_mode ((mpfr_rnd_t) r), expected_sign > 0 ? '+' : '-'); mpfr_dump (sum); printf ("with inex = %d\n", inex); exit (1); } } for (i = 0; i < 4; i++) mpfr_clear (t[i]); mpfr_clear (sum); }
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; }
/* Assumes that the exponent range has already been extended and if y is an integer, then the result is not exact in unbounded exponent range. */ int mpfr_pow_general (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode, int y_is_integer, mpfr_save_expo_t *expo) { mpfr_t t, u, k, absx; int neg_result = 0; int k_non_zero = 0; int check_exact_case = 0; int inexact; /* Declaration of the size variable */ mpfr_prec_t Nz = MPFR_PREC(z); /* target precision */ mpfr_prec_t Nt; /* working precision */ mpfr_exp_t err; /* error */ MPFR_ZIV_DECL (ziv_loop); MPFR_LOG_FUNC (("x[%Pu]=%.*Rg y[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, mpfr_get_prec (y), mpfr_log_prec, y, rnd_mode), ("z[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (z), mpfr_log_prec, z, inexact)); /* We put the absolute value of x in absx, pointing to the significand of x to avoid allocating memory for the significand of absx. */ MPFR_ALIAS(absx, x, /*sign=*/ 1, /*EXP=*/ MPFR_EXP(x)); /* We will compute the absolute value of the result. So, let's invert the rounding mode if the result is negative. */ if (MPFR_IS_NEG (x) && is_odd (y)) { neg_result = 1; rnd_mode = MPFR_INVERT_RND (rnd_mode); } /* compute the precision of intermediary variable */ /* the optimal number of bits : see algorithms.tex */ Nt = Nz + 5 + MPFR_INT_CEIL_LOG2 (Nz); /* initialise of intermediary variable */ mpfr_init2 (t, Nt); MPFR_ZIV_INIT (ziv_loop, Nt); for (;;) { MPFR_BLOCK_DECL (flags1); /* compute exp(y*ln|x|), using MPFR_RNDU to get an upper bound, so that we can detect underflows. */ mpfr_log (t, absx, MPFR_IS_NEG (y) ? MPFR_RNDD : MPFR_RNDU); /* ln|x| */ mpfr_mul (t, y, t, MPFR_RNDU); /* y*ln|x| */ if (k_non_zero) { MPFR_LOG_MSG (("subtract k * ln(2)\n", 0)); mpfr_const_log2 (u, MPFR_RNDD); mpfr_mul (u, u, k, MPFR_RNDD); /* Error on u = k * log(2): < k * 2^(-Nt) < 1. */ mpfr_sub (t, t, u, MPFR_RNDU); MPFR_LOG_MSG (("t = y * ln|x| - k * ln(2)\n", 0)); MPFR_LOG_VAR (t); } /* estimate of the error -- see pow function in algorithms.tex. The error on t is at most 1/2 + 3*2^(EXP(t)+1) ulps, which is <= 2^(EXP(t)+3) for EXP(t) >= -1, and <= 2 ulps for EXP(t) <= -2. Additional error if k_no_zero: treal = t * errk, with 1 - |k| * 2^(-Nt) <= exp(-|k| * 2^(-Nt)) <= errk <= 1, i.e., additional absolute error <= 2^(EXP(k)+EXP(t)-Nt). Total error <= 2^err1 + 2^err2 <= 2^(max(err1,err2)+1). */ err = MPFR_NOTZERO (t) && MPFR_GET_EXP (t) >= -1 ? MPFR_GET_EXP (t) + 3 : 1; if (k_non_zero) { if (MPFR_GET_EXP (k) > err) err = MPFR_GET_EXP (k); err++; } MPFR_BLOCK (flags1, mpfr_exp (t, t, MPFR_RNDN)); /* exp(y*ln|x|)*/ /* We need to test */ if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (t) || MPFR_UNDERFLOW (flags1))) { mpfr_prec_t Ntmin; MPFR_BLOCK_DECL (flags2); MPFR_ASSERTN (!k_non_zero); MPFR_ASSERTN (!MPFR_IS_NAN (t)); /* Real underflow? */ if (MPFR_IS_ZERO (t)) { /* Underflow. We computed rndn(exp(t)), where t >= y*ln|x|. Therefore rndn(|x|^y) = 0, and we have a real underflow on |x|^y. */ inexact = mpfr_underflow (z, rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode, MPFR_SIGN_POS); if (expo != NULL) MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW); break; } /* Real overflow? */ if (MPFR_IS_INF (t)) { /* Note: we can probably use a low precision for this test. */ mpfr_log (t, absx, MPFR_IS_NEG (y) ? MPFR_RNDU : MPFR_RNDD); mpfr_mul (t, y, t, MPFR_RNDD); /* y * ln|x| */ MPFR_BLOCK (flags2, mpfr_exp (t, t, MPFR_RNDD)); /* t = lower bound on exp(y * ln|x|) */ if (MPFR_OVERFLOW (flags2)) { /* We have computed a lower bound on |x|^y, and it overflowed. Therefore we have a real overflow on |x|^y. */ inexact = mpfr_overflow (z, rnd_mode, MPFR_SIGN_POS); if (expo != NULL) MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW); break; } } k_non_zero = 1; Ntmin = sizeof(mpfr_exp_t) * CHAR_BIT; if (Ntmin > Nt) { Nt = Ntmin; mpfr_set_prec (t, Nt); } mpfr_init2 (u, Nt); mpfr_init2 (k, Ntmin); mpfr_log2 (k, absx, MPFR_RNDN); mpfr_mul (k, y, k, MPFR_RNDN); mpfr_round (k, k); MPFR_LOG_VAR (k); /* |y| < 2^Ntmin, therefore |k| < 2^Nt. */ continue; } if (MPFR_LIKELY (MPFR_CAN_ROUND (t, Nt - err, Nz, rnd_mode))) { inexact = mpfr_set (z, t, rnd_mode); break; } /* check exact power, except when y is an integer (since the exact cases for y integer have already been filtered out) */ if (check_exact_case == 0 && ! y_is_integer) { if (mpfr_pow_is_exact (z, absx, y, rnd_mode, &inexact)) break; check_exact_case = 1; } /* reactualisation of the precision */ MPFR_ZIV_NEXT (ziv_loop, Nt); mpfr_set_prec (t, Nt); if (k_non_zero) mpfr_set_prec (u, Nt); } MPFR_ZIV_FREE (ziv_loop); if (k_non_zero) { int inex2; long lk; /* The rounded result in an unbounded exponent range is z * 2^k. As * MPFR chooses underflow after rounding, the mpfr_mul_2si below will * correctly detect underflows and overflows. However, in rounding to * nearest, if z * 2^k = 2^(emin - 2), then the double rounding may * affect the result. We need to cope with that before overwriting z. * This can occur only if k < 0 (this test is necessary to avoid a * potential integer overflow). * If inexact >= 0, then the real result is <= 2^(emin - 2), so that * o(2^(emin - 2)) = +0 is correct. If inexact < 0, then the real * result is > 2^(emin - 2) and we need to round to 2^(emin - 1). */ MPFR_ASSERTN (MPFR_EXP_MAX <= LONG_MAX); lk = mpfr_get_si (k, MPFR_RNDN); /* Due to early overflow detection, |k| should not be much larger than * MPFR_EMAX_MAX, and as MPFR_EMAX_MAX <= MPFR_EXP_MAX/2 <= LONG_MAX/2, * an overflow should not be possible in mpfr_get_si (and lk is exact). * And one even has the following assertion. TODO: complete proof. */ MPFR_ASSERTD (lk > LONG_MIN && lk < LONG_MAX); /* Note: even in case of overflow (lk inexact), the code is correct. * Indeed, for the 3 occurrences of lk: * - The test lk < 0 is correct as sign(lk) = sign(k). * - In the test MPFR_GET_EXP (z) == __gmpfr_emin - 1 - lk, * if lk is inexact, then lk = LONG_MIN <= MPFR_EXP_MIN * (the minimum value of the mpfr_exp_t type), and * __gmpfr_emin - 1 - lk >= MPFR_EMIN_MIN - 1 - 2 * MPFR_EMIN_MIN * >= - MPFR_EMIN_MIN - 1 = MPFR_EMAX_MAX - 1. However, from the * choice of k, z has been chosen to be around 1, so that the * result of the test is false, as if lk were exact. * - In the mpfr_mul_2si (z, z, lk, rnd_mode), if lk is inexact, * then |lk| >= LONG_MAX >= MPFR_EXP_MAX, and as z is around 1, * mpfr_mul_2si underflows or overflows in the same way as if * lk were exact. * TODO: give a bound on |t|, then on |EXP(z)|. */ if (rnd_mode == MPFR_RNDN && inexact < 0 && lk < 0 && MPFR_GET_EXP (z) == __gmpfr_emin - 1 - lk && mpfr_powerof2_raw (z)) { /* Rounding to nearest, real result > z * 2^k = 2^(emin - 2), * underflow case: as the minimum precision is > 1, we will * obtain the correct result and exceptions by replacing z by * nextabove(z). */ MPFR_ASSERTN (MPFR_PREC_MIN > 1); mpfr_nextabove (z); } MPFR_CLEAR_FLAGS (); inex2 = mpfr_mul_2si (z, z, lk, rnd_mode); if (inex2) /* underflow or overflow */ { inexact = inex2; if (expo != NULL) MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, __gmpfr_flags); } mpfr_clears (u, k, (mpfr_ptr) 0); } mpfr_clear (t); /* update the sign of the result if x was negative */ if (neg_result) { MPFR_SET_NEG(z); inexact = -inexact; } return inexact; }
/* Exact product. The number a is assumed to have enough allocated memory, where the trailing bits are regarded as being part of the input numbers (no reallocation is attempted and no check is performed as MPFR_TMP_INIT could have been used). The arguments b and c may actually be UBF numbers (mpfr_srcptr can be seen a bit like void *, but is stronger). This function does not change the flags, except in case of NaN. */ void mpfr_ubf_mul_exact (mpfr_ubf_ptr a, mpfr_srcptr b, mpfr_srcptr c) { MPFR_LOG_FUNC (("b[%Pu]=%.*Rg c[%Pu]=%.*Rg", mpfr_get_prec (b), mpfr_log_prec, b, mpfr_get_prec (c), mpfr_log_prec, c), ("a[%Pu]=%.*Rg", mpfr_get_prec (a), mpfr_log_prec, a)); MPFR_ASSERTD ((mpfr_ptr) a != b); MPFR_ASSERTD ((mpfr_ptr) a != c); MPFR_SIGN (a) = MPFR_MULT_SIGN (MPFR_SIGN (b), MPFR_SIGN (c)); if (MPFR_ARE_SINGULAR (b, c)) { if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c)) MPFR_SET_NAN (a); else if (MPFR_IS_INF (b)) { if (MPFR_NOTZERO (c)) MPFR_SET_INF (a); else MPFR_SET_NAN (a); } else if (MPFR_IS_INF (c)) { if (!MPFR_IS_ZERO (b)) MPFR_SET_INF (a); else MPFR_SET_NAN (a); } else { MPFR_ASSERTD (MPFR_IS_ZERO(b) || MPFR_IS_ZERO(c)); MPFR_SET_ZERO (a); } } else { mpfr_exp_t e; mp_size_t bn, cn; mpfr_limb_ptr ap; mp_limb_t u, v; int m; /* Note about the code below: For the choice of the precision of * the result a, one could choose PREC(b) + PREC(c), instead of * taking whole limbs into account, but in most cases where one * would gain one limb, one would need to copy the significand * instead of a no-op (see the mul.c code). * But in the case MPFR_LIMB_MSB (u) == 0, if the result fits in * an-1 limbs, one could actually do * mpn_rshift (ap, ap, k, GMP_NUMB_BITS - 1) * instead of * mpn_lshift (ap, ap, k, 1) * to gain one limb (and reduce the precision), replacing a shift * by another one. Would this be interesting? */ bn = MPFR_LIMB_SIZE (b); cn = MPFR_LIMB_SIZE (c); ap = MPFR_MANT (a); u = (bn >= cn) ? mpn_mul (ap, MPFR_MANT (b), bn, MPFR_MANT (c), cn) : mpn_mul (ap, MPFR_MANT (c), cn, MPFR_MANT (b), bn); if (MPFR_UNLIKELY (MPFR_LIMB_MSB (u) == 0)) { m = 1; MPFR_DBGRES (v = mpn_lshift (ap, ap, bn + cn, 1)); MPFR_ASSERTD (v == 0); } else m = 0; if (! MPFR_IS_UBF (b) && ! MPFR_IS_UBF (c) && (e = MPFR_GET_EXP (b) + MPFR_GET_EXP (c) - m, MPFR_EXP_IN_RANGE (e))) { MPFR_SET_EXP (a, e); } else { mpz_t be, ce; mpz_init (MPFR_ZEXP (a)); /* This may involve copies of mpz_t, but exponents should not be very large integers anyway. */ mpfr_get_zexp (be, b); mpfr_get_zexp (ce, c); mpz_add (MPFR_ZEXP (a), be, ce); mpz_clear (be); mpz_clear (ce); mpz_sub_ui (MPFR_ZEXP (a), MPFR_ZEXP (a), m); MPFR_SET_UBF (a); } } }
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 int mpfr_mul3 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) { /* Old implementation */ int sign_product, cc, inexact; mpfr_exp_t ax; mp_limb_t *tmp; mp_limb_t b1; mpfr_prec_t bq, cq; mp_size_t bn, cn, tn, k; MPFR_TMP_DECL(marker); /* deal with special cases */ if (MPFR_ARE_SINGULAR(b,c)) { if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c)) { MPFR_SET_NAN(a); MPFR_RET_NAN; } sign_product = MPFR_MULT_SIGN( MPFR_SIGN(b) , MPFR_SIGN(c) ); if (MPFR_IS_INF(b)) { if (MPFR_IS_INF(c) || MPFR_NOTZERO(c)) { MPFR_SET_SIGN(a,sign_product); MPFR_SET_INF(a); MPFR_RET(0); /* exact */ } else { MPFR_SET_NAN(a); MPFR_RET_NAN; } } else if (MPFR_IS_INF(c)) { if (MPFR_NOTZERO(b)) { MPFR_SET_SIGN(a, sign_product); MPFR_SET_INF(a); MPFR_RET(0); /* exact */ } else { MPFR_SET_NAN(a); MPFR_RET_NAN; } } else { MPFR_ASSERTD(MPFR_IS_ZERO(b) || MPFR_IS_ZERO(c)); MPFR_SET_SIGN(a, sign_product); MPFR_SET_ZERO(a); MPFR_RET(0); /* 0 * 0 is exact */ } } sign_product = MPFR_MULT_SIGN( MPFR_SIGN(b) , MPFR_SIGN(c) ); ax = MPFR_GET_EXP (b) + MPFR_GET_EXP (c); bq = MPFR_PREC(b); cq = MPFR_PREC(c); MPFR_ASSERTD(bq+cq > bq); /* PREC_MAX is /2 so no integer overflow */ bn = (bq+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; /* number of limbs of b */ cn = (cq+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; /* number of limbs of c */ k = bn + cn; /* effective nb of limbs used by b*c (= tn or tn+1) below */ tn = (bq + cq + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS; /* <= k, thus no int overflow */ MPFR_ASSERTD(tn <= k); /* Check for no size_t overflow*/ MPFR_ASSERTD((size_t) k <= ((size_t) -1) / BYTES_PER_MP_LIMB); MPFR_TMP_MARK(marker); tmp = (mp_limb_t *) MPFR_TMP_ALLOC((size_t) k * BYTES_PER_MP_LIMB); /* multiplies two mantissa in temporary allocated space */ b1 = (MPFR_LIKELY(bn >= cn)) ? mpn_mul (tmp, MPFR_MANT(b), bn, MPFR_MANT(c), cn) : mpn_mul (tmp, MPFR_MANT(c), cn, MPFR_MANT(b), bn); /* now tmp[0]..tmp[k-1] contains the product of both mantissa, with tmp[k-1]>=2^(GMP_NUMB_BITS-2) */ b1 >>= GMP_NUMB_BITS - 1; /* msb from the product */ /* if the mantissas of b and c are uniformly distributed in ]1/2, 1], then their product is in ]1/4, 1/2] with probability 2*ln(2)-1 ~ 0.386 and in [1/2, 1] with probability 2-2*ln(2) ~ 0.614 */ tmp += k - tn; if (MPFR_UNLIKELY(b1 == 0)) mpn_lshift (tmp, tmp, tn, 1); /* tn <= k, so no stack corruption */ cc = mpfr_round_raw (MPFR_MANT (a), tmp, bq + cq, MPFR_IS_NEG_SIGN(sign_product), MPFR_PREC (a), rnd_mode, &inexact); /* cc = 1 ==> result is a power of two */ if (MPFR_UNLIKELY(cc)) MPFR_MANT(a)[MPFR_LIMB_SIZE(a)-1] = MPFR_LIMB_HIGHBIT; MPFR_TMP_FREE(marker); { mpfr_exp_t ax2 = ax + (mpfr_exp_t) (b1 - 1 + cc); if (MPFR_UNLIKELY( ax2 > __gmpfr_emax)) return mpfr_overflow (a, rnd_mode, sign_product); if (MPFR_UNLIKELY( ax2 < __gmpfr_emin)) { /* In the rounding to the nearest mode, if the exponent of the exact result (i.e. before rounding, i.e. without taking cc into account) is < __gmpfr_emin - 1 or the exact result is a power of 2 (i.e. if both arguments are powers of 2), then round to zero. */ if (rnd_mode == MPFR_RNDN && (ax + (mpfr_exp_t) b1 < __gmpfr_emin || (mpfr_powerof2_raw (b) && mpfr_powerof2_raw (c)))) rnd_mode = MPFR_RNDZ; return mpfr_underflow (a, rnd_mode, sign_product); } MPFR_SET_EXP (a, ax2); MPFR_SET_SIGN(a, sign_product); } MPFR_RET (inexact); }
int main (void) { mpfr_t x, y; int i, r; tests_start_mpfr (); mpfr_init2 (x, 256); mpfr_init2 (y, 8); RND_LOOP (r) { /* Check NAN */ mpfr_set_nan (x); if (mpfr_fits_ulong_p (x, (mpfr_rnd_t) r)) ERROR1 (1); if (mpfr_fits_slong_p (x, (mpfr_rnd_t) r)) ERROR1 (2); if (mpfr_fits_uint_p (x, (mpfr_rnd_t) r)) ERROR1 (3); if (mpfr_fits_sint_p (x, (mpfr_rnd_t) r)) ERROR1 (4); if (mpfr_fits_ushort_p (x, (mpfr_rnd_t) r)) ERROR1 (5); if (mpfr_fits_sshort_p (x, (mpfr_rnd_t) r)) ERROR1 (6); /* Check INF */ mpfr_set_inf (x, 1); if (mpfr_fits_ulong_p (x, (mpfr_rnd_t) r)) ERROR1 (7); if (mpfr_fits_slong_p (x, (mpfr_rnd_t) r)) ERROR1 (8); if (mpfr_fits_uint_p (x, (mpfr_rnd_t) r)) ERROR1 (9); if (mpfr_fits_sint_p (x, (mpfr_rnd_t) r)) ERROR1 (10); if (mpfr_fits_ushort_p (x, (mpfr_rnd_t) r)) ERROR1 (11); if (mpfr_fits_sshort_p (x, (mpfr_rnd_t) r)) ERROR1 (12); /* Check Zero */ MPFR_SET_ZERO (x); if (!mpfr_fits_ulong_p (x, (mpfr_rnd_t) r)) ERROR1 (13); if (!mpfr_fits_slong_p (x, (mpfr_rnd_t) r)) ERROR1 (14); if (!mpfr_fits_uint_p (x, (mpfr_rnd_t) r)) ERROR1 (15); if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r)) ERROR1 (16); if (!mpfr_fits_ushort_p (x, (mpfr_rnd_t) r)) ERROR1 (17); if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r)) ERROR1 (18); /* Check small positive op */ mpfr_set_str1 (x, "1@-1"); if (!mpfr_fits_ulong_p (x, (mpfr_rnd_t) r)) ERROR1 (19); if (!mpfr_fits_slong_p (x, (mpfr_rnd_t) r)) ERROR1 (20); if (!mpfr_fits_uint_p (x, (mpfr_rnd_t) r)) ERROR1 (21); if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r)) ERROR1 (22); if (!mpfr_fits_ushort_p (x, (mpfr_rnd_t) r)) ERROR1 (23); if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r)) ERROR1 (24); /* Check 17 */ mpfr_set_ui (x, 17, MPFR_RNDN); if (!mpfr_fits_ulong_p (x, (mpfr_rnd_t) r)) ERROR1 (25); if (!mpfr_fits_slong_p (x, (mpfr_rnd_t) r)) ERROR1 (26); if (!mpfr_fits_uint_p (x, (mpfr_rnd_t) r)) ERROR1 (27); if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r)) ERROR1 (28); if (!mpfr_fits_ushort_p (x, (mpfr_rnd_t) r)) ERROR1 (29); if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r)) ERROR1 (30); /* Check all other values */ mpfr_set_ui (x, ULONG_MAX, MPFR_RNDN); mpfr_mul_2exp (x, x, 1, MPFR_RNDN); if (mpfr_fits_ulong_p (x, (mpfr_rnd_t) r)) ERROR1 (31); if (mpfr_fits_slong_p (x, (mpfr_rnd_t) r)) ERROR1 (32); mpfr_mul_2exp (x, x, 40, MPFR_RNDN); if (mpfr_fits_ulong_p (x, (mpfr_rnd_t) r)) ERROR1 (33); if (mpfr_fits_uint_p (x, (mpfr_rnd_t) r)) ERROR1 (34); if (mpfr_fits_sint_p (x, (mpfr_rnd_t) r)) ERROR1 (35); if (mpfr_fits_ushort_p (x, (mpfr_rnd_t) r)) ERROR1 (36); if (mpfr_fits_sshort_p (x, (mpfr_rnd_t) r)) ERROR1 (37); mpfr_set_ui (x, ULONG_MAX, MPFR_RNDN); if (!mpfr_fits_ulong_p (x, (mpfr_rnd_t) r)) ERROR1 (38); mpfr_set_ui (x, LONG_MAX, MPFR_RNDN); if (!mpfr_fits_slong_p (x, (mpfr_rnd_t) r)) ERROR1 (39); mpfr_set_ui (x, UINT_MAX, MPFR_RNDN); if (!mpfr_fits_uint_p (x, (mpfr_rnd_t) r)) ERROR1 (40); mpfr_set_ui (x, INT_MAX, MPFR_RNDN); if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r)) ERROR1 (41); mpfr_set_ui (x, USHRT_MAX, MPFR_RNDN); if (!mpfr_fits_ushort_p (x, (mpfr_rnd_t) r)) ERROR1 (42); mpfr_set_ui (x, SHRT_MAX, MPFR_RNDN); if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r)) ERROR1 (43); mpfr_set_si (x, 1, MPFR_RNDN); if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r)) ERROR1 (44); if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r)) ERROR1 (45); /* 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_ulong_p (x, (mpfr_rnd_t) r) ^ inv) ERROR1 (46); if (!mpfr_fits_slong_p (x, (mpfr_rnd_t) r)) ERROR1 (47); if (!mpfr_fits_uint_p (x, (mpfr_rnd_t) r) ^ inv) ERROR1 (48); if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r)) ERROR1 (49); if (!mpfr_fits_ushort_p (x, (mpfr_rnd_t) r) ^ inv) ERROR1 (50); if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r)) ERROR1 (51); } } mpfr_clear (x); mpfr_clear (y); check_intmax (); tests_end_mpfr (); return 0; }
static void underflow_up (int extended_emin) { mpfr_t minpos, x, y, t, t2; int precx, precy; int inex; int rnd; int e3; int i, j; mpfr_init2 (minpos, 2); mpfr_set_ui (minpos, 0, MPFR_RNDN); mpfr_nextabove (minpos); /* Let's test values near the underflow boundary. * * Minimum representable positive number: minpos = 2^(emin - 1). * Let's choose an MPFR number x = log(minpos) + eps, with |eps| small * (note: eps cannot be 0, and cannot be a rational number either). * Then exp(x) = minpos * exp(eps) ~= minpos * (1 + eps + eps^2). * We will compute y = rnd(exp(x)) in some rounding mode, precision p. * 1. If eps > 0, then in any rounding mode: * rnd(exp(x)) >= minpos and no underflow. * So, let's take x1 = rndu(log(minpos)) in some precision. * 2. If eps < 0, then exp(x) < minpos and the result will be either 0 * or minpos. An underflow always occurs in MPFR_RNDZ and MPFR_RNDD, * but not necessarily in MPFR_RNDN and MPFR_RNDU (this is underflow * after rounding in an unbounded exponent range). If -a < eps < -b, * minpos * (1 - a) < exp(x) < minpos * (1 - b + b^2). * - If eps > -2^(-p), no underflow in MPFR_RNDU. * - If eps > -2^(-p-1), no underflow in MPFR_RNDN. * - If eps < - (2^(-p-1) + 2^(-2p-1)), underflow in MPFR_RNDN. * - If eps < - (2^(-p) + 2^(-2p+1)), underflow in MPFR_RNDU. * - In MPFR_RNDN, result is minpos iff exp(eps) > 1/2, i.e. * - log(2) < eps < ... * * Moreover, since precy < MPFR_EXP_THRESHOLD (to avoid tests that take * too much time), mpfr_exp() always selects mpfr_exp_2(); so, we need * to test mpfr_exp_3() too. This will be done via the e3 variable: * e3 = 0: mpfr_exp(), thus mpfr_exp_2(). * e3 = 1: mpfr_exp_3(), via the exp_3() wrapper. * i.e.: inex = e3 ? exp_3 (y, x, rnd) : mpfr_exp (y, x, rnd); */ /* Case eps > 0. In revision 5461 (trunk) on a 64-bit Linux machine: * Incorrect flags in underflow_up, eps > 0, MPFR_RNDN and extended emin * for precx = 96, precy = 16, mpfr_exp_3 * Got 9 instead of 8. * Note: testing this case in several precisions for x and y introduces * some useful random. Indeed, the bug is not always triggered. * Fixed in r5469. */ for (precx = 16; precx <= 128; precx += 16) { mpfr_init2 (x, precx); mpfr_log (x, minpos, MPFR_RNDU); for (precy = 16; precy <= 128; precy += 16) { mpfr_init2 (y, precy); for (e3 = 0; e3 <= 1; e3++) { RND_LOOP (rnd) { int err = 0; mpfr_clear_flags (); inex = e3 ? exp_3 (y, x, (mpfr_rnd_t) rnd) : mpfr_exp (y, x, (mpfr_rnd_t) rnd); if (__gmpfr_flags != MPFR_FLAGS_INEXACT) { printf ("Incorrect flags in underflow_up, eps > 0, %s", mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); if (extended_emin) printf (" and extended emin"); printf ("\nfor precx = %d, precy = %d, %s\n", precx, precy, e3 ? "mpfr_exp_3" : "mpfr_exp"); printf ("Got %u instead of %u.\n", __gmpfr_flags, (unsigned int) MPFR_FLAGS_INEXACT); err = 1; } if (mpfr_cmp0 (y, minpos) < 0) { printf ("Incorrect result in underflow_up, eps > 0, %s", mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); if (extended_emin) printf (" and extended emin"); printf ("\nfor precx = %d, precy = %d, %s\n", precx, precy, e3 ? "mpfr_exp_3" : "mpfr_exp"); mpfr_dump (y); err = 1; } MPFR_ASSERTN (inex != 0); if (rnd == MPFR_RNDD || rnd == MPFR_RNDZ) MPFR_ASSERTN (inex < 0); if (rnd == MPFR_RNDU) MPFR_ASSERTN (inex > 0); if (err) exit (1); } } mpfr_clear (y); } mpfr_clear (x); } /* Case - log(2) < eps < 0 in MPFR_RNDN, starting with small-precision x; * only check the result and the ternary value. * Previous to r5453 (trunk), on 32-bit and 64-bit machines, this fails * for precx = 65 and precy = 16, e.g.: * exp_2.c:264: assertion failed: ... * because mpfr_sub (r, x, r, MPFR_RNDU); yields a null value. This is * fixed in r5453 by going to next Ziv's iteration. */ for (precx = sizeof(mpfr_exp_t) * CHAR_BIT + 1; precx <= 81; precx += 8) { mpfr_init2 (x, precx); mpfr_log (x, minpos, MPFR_RNDD); /* |ulp| <= 1/2 */ for (precy = 16; precy <= 128; precy += 16) { mpfr_init2 (y, precy); inex = mpfr_exp (y, x, MPFR_RNDN); if (inex <= 0 || mpfr_cmp0 (y, minpos) != 0) { printf ("Error in underflow_up, - log(2) < eps < 0"); if (extended_emin) printf (" and extended emin"); printf (" for prec = %d\nExpected ", precy); mpfr_out_str (stdout, 16, 0, minpos, MPFR_RNDN); printf (" (minimum positive MPFR number) and inex > 0\nGot "); mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN); printf ("\nwith inex = %d\n", inex); exit (1); } mpfr_clear (y); } mpfr_clear (x); } /* Cases eps ~ -2^(-p) and eps ~ -2^(-p-1). More precisely, * _ for j = 0, eps > -2^(-(p+i)), * _ for j = 1, eps < - (2^(-(p+i)) + 2^(1-2(p+i))), * where i = 0 or 1. */ mpfr_inits2 (2, t, t2, (mpfr_ptr) 0); for (precy = 16; precy <= 128; precy += 16) { mpfr_set_ui_2exp (t, 1, - precy, MPFR_RNDN); /* 2^(-p) */ mpfr_set_ui_2exp (t2, 1, 1 - 2 * precy, MPFR_RNDN); /* 2^(-2p+1) */ precx = sizeof(mpfr_exp_t) * CHAR_BIT + 2 * precy + 8; mpfr_init2 (x, precx); mpfr_init2 (y, precy); for (i = 0; i <= 1; i++) { for (j = 0; j <= 1; j++) { if (j == 0) { /* Case eps > -2^(-(p+i)). */ mpfr_log (x, minpos, MPFR_RNDU); } else /* j == 1 */ { /* Case eps < - (2^(-(p+i)) + 2^(1-2(p+i))). */ mpfr_log (x, minpos, MPFR_RNDD); inex = mpfr_sub (x, x, t2, MPFR_RNDN); MPFR_ASSERTN (inex == 0); } inex = mpfr_sub (x, x, t, MPFR_RNDN); MPFR_ASSERTN (inex == 0); RND_LOOP (rnd) for (e3 = 0; e3 <= 1; e3++) { int err = 0; unsigned int flags; flags = MPFR_FLAGS_INEXACT | (((rnd == MPFR_RNDU || rnd == MPFR_RNDA) && (i == 1 || j == 0)) || (rnd == MPFR_RNDN && (i == 1 && j == 0)) ? 0 : MPFR_FLAGS_UNDERFLOW); mpfr_clear_flags (); inex = e3 ? exp_3 (y, x, (mpfr_rnd_t) rnd) : mpfr_exp (y, x, (mpfr_rnd_t) rnd); if (__gmpfr_flags != flags) { printf ("Incorrect flags in underflow_up, %s", mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); if (extended_emin) printf (" and extended emin"); printf ("\nfor precx = %d, precy = %d, ", precx, precy); if (j == 0) printf ("eps >~ -2^(-%d)", precy + i); else printf ("eps <~ - (2^(-%d) + 2^(%d))", precy + i, 1 - 2 * (precy + i)); printf (", %s\n", e3 ? "mpfr_exp_3" : "mpfr_exp"); printf ("Got %u instead of %u.\n", __gmpfr_flags, flags); err = 1; } if (rnd == MPFR_RNDU || rnd == MPFR_RNDA || rnd == MPFR_RNDN ? mpfr_cmp0 (y, minpos) != 0 : MPFR_NOTZERO (y)) { printf ("Incorrect result in underflow_up, %s", mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); if (extended_emin) printf (" and extended emin"); printf ("\nfor precx = %d, precy = %d, ", precx, precy); if (j == 0) printf ("eps >~ -2^(-%d)", precy + i); else printf ("eps <~ - (2^(-%d) + 2^(%d))", precy + i, 1 - 2 * (precy + i)); printf (", %s\n", e3 ? "mpfr_exp_3" : "mpfr_exp"); mpfr_dump (y); err = 1; } if (err) exit (1); } /* for (e3 ...) */ } /* for (j ...) */ mpfr_div_2si (t, t, 1, MPFR_RNDN); mpfr_div_2si (t2, t2, 2, MPFR_RNDN); } /* for (i ...) */ mpfr_clears (x, y, (mpfr_ptr) 0); } /* for (precy ...) */ mpfr_clears (t, t2, (mpfr_ptr) 0); /* Case exp(eps) ~= 1/2, i.e. eps ~= - log(2). * We choose x0 and x1 with high enough precision such that: * x0 = rndd(rndd(log(minpos)) - rndu(log(2))) * x1 = rndu(rndu(log(minpos)) - rndd(log(2))) * In revision 5507 (trunk) on a 64-bit Linux machine, this fails: * Error in underflow_up, eps >~ - log(2) and extended emin * for precy = 16, mpfr_exp * Expected 1.0@-1152921504606846976 (minimum positive MPFR number), * inex > 0 and flags = 9 * Got 0 * with inex = -1 and flags = 9 * due to a double-rounding problem in mpfr_mul_2si when rescaling * the result. */ mpfr_inits2 (sizeof(mpfr_exp_t) * CHAR_BIT + 64, x, t, (mpfr_ptr) 0); for (i = 0; i <= 1; i++) { mpfr_log (x, minpos, i ? MPFR_RNDU : MPFR_RNDD); mpfr_const_log2 (t, i ? MPFR_RNDD : MPFR_RNDU); mpfr_sub (x, x, t, i ? MPFR_RNDU : MPFR_RNDD); for (precy = 16; precy <= 128; precy += 16) { mpfr_init2 (y, precy); for (e3 = 0; e3 <= 1; e3++) { unsigned int flags, uflags = MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW; mpfr_clear_flags (); inex = e3 ? exp_3 (y, x, MPFR_RNDN) : mpfr_exp (y, x, MPFR_RNDN); flags = __gmpfr_flags; if (flags != uflags || (i ? (inex <= 0 || mpfr_cmp0 (y, minpos) != 0) : (inex >= 0 || MPFR_NOTZERO (y)))) { printf ("Error in underflow_up, eps %c~ - log(2)", i ? '>' : '<'); if (extended_emin) printf (" and extended emin"); printf ("\nfor precy = %d, %s\nExpected ", precy, e3 ? "mpfr_exp_3" : "mpfr_exp"); if (i) { mpfr_out_str (stdout, 16, 0, minpos, MPFR_RNDN); printf (" (minimum positive MPFR number),\ninex >"); } else { printf ("+0, inex <"); } printf (" 0 and flags = %u\nGot ", uflags); mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN); printf ("\nwith inex = %d and flags = %u\n", inex, flags); exit (1); } } mpfr_clear (y); } } mpfr_clears (x, t, (mpfr_ptr) 0); mpfr_clear (minpos); }
int mpfr_eq (mpfr_srcptr u, mpfr_srcptr v, unsigned long int n_bits) { mp_srcptr up, vp; mp_size_t usize, vsize, size, i; mp_exp_t uexp, vexp; int usign, k; uexp = MPFR_EXP(u); vexp = MPFR_EXP(v); usize = (MPFR_PREC(u)-1)/BITS_PER_MP_LIMB + 1; vsize = (MPFR_PREC(v)-1)/BITS_PER_MP_LIMB + 1; usign = MPFR_SIGN(u); /* 1. Are the signs different? */ if (usign == MPFR_SIGN(v)) { /* U and V are both non-negative or both negative. */ if (!MPFR_NOTZERO(u)) return !MPFR_NOTZERO(v); if (!MPFR_NOTZERO(v)) return !MPFR_NOTZERO(u); /* Fall out. */ } else { /* Either U or V is negative, but not both. */ if (MPFR_NOTZERO(u) || MPFR_NOTZERO(v)) return 0; else return 1; /* particular case -0 = +0 */ } /* U and V have the same sign and are both non-zero. */ if (MPFR_IS_INF(u)) return (MPFR_IS_INF(v) && (usign == MPFR_SIGN(v))); else if (MPFR_IS_INF(v)) return 0; if (MPFR_IS_NAN(u) || MPFR_IS_NAN(v)) return 0; /* 2. Are the exponents different? */ if (uexp > vexp) return 0; /* ??? handle (uexp = vexp + 1) */ if (vexp > uexp) return 0; /* ??? handle (vexp = uexp + 1) */ usize = ABS (usize); vsize = ABS (vsize); up = MPFR_MANT(u); vp = MPFR_MANT(v); if (usize > vsize) { if (vsize * BITS_PER_MP_LIMB < n_bits) { k = usize - vsize - 1; while (k >= 0 && !up[k]) --k; if (k >= 0) return 0; /* surely too different */ } size = vsize; } else if (vsize > usize) { if (usize * BITS_PER_MP_LIMB < n_bits) { k = vsize - usize - 1; while (k >= 0 && !vp[k]) --k; if (k >= 0) return 0; /* surely too different */ } size = usize; } else { size = usize; } if (size > (n_bits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) size = (n_bits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB; up += usize - size; vp += vsize - size; for (i = size - 1; i > 0; i--) { if (up[i] != vp[i]) return 0; } if (n_bits & (BITS_PER_MP_LIMB - 1)) return (up[i] >> (BITS_PER_MP_LIMB - (n_bits & (BITS_PER_MP_LIMB - 1))) == vp[i] >> (BITS_PER_MP_LIMB - (n_bits & (BITS_PER_MP_LIMB - 1)))); else return (up[i] == vp[i]);
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 }
static void check_special_exprange (void) { int inexact, ov; unsigned int eflags, gflags; mpfr_t xi, xf, x; mpfr_exp_t emax; emax = mpfr_get_emax (); mpfr_init2 (xi, 7); mpfr_init2 (xf, 7); mpfr_init2 (x, 8); mpfr_set_str (x, "0.11111111", 2, MPFR_RNDN); for (ov = 0; ov <= 1; ov++) { const char *s = ov ? "@Inf@" : "1"; if (ov) set_emax (0); mpfr_clear_flags (); inexact = mpfr_modf (xi, xf, x, MPFR_RNDN); gflags = __gmpfr_flags; set_emax (emax); if (MPFR_NOTZERO (xi) || MPFR_IS_NEG (xi) || mpfr_cmp_str1 (xf, s) != 0) { printf ("Error in check_special_exprange (ov = %d):" " expected 0 and %s, got\n", ov, s); mpfr_out_str (stdout, 2, 0, xi, MPFR_RNDN); printf (" and "); mpfr_out_str (stdout, 2, 0, xf, MPFR_RNDN); printf ("\n"); exit (1); } if (inexact != 4) { printf ("Bad inexact value in check_special_exprange (ov = %d):" " expected 4, got %d\n", ov, inexact); exit (1); } eflags = MPFR_FLAGS_INEXACT | (ov ? MPFR_FLAGS_OVERFLOW : 0); if (gflags != eflags) { printf ("Bad flags in check_special_exprange (ov = %d):" " expected %u, got %u\n", ov, eflags, gflags); exit (1); } } /* Test if an overflow occurs in mpfr_set for ope >= opq. */ mpfr_set_emax (MPFR_EMAX_MAX); mpfr_set_inf (x, 1); mpfr_nextbelow (x); mpfr_clear_flags (); inexact = mpfr_modf (xi, xf, x, MPFR_RNDN); gflags = __gmpfr_flags; if (mpfr_cmp_str1 (xi, "@Inf@") != 0 || MPFR_NOTZERO (xf) || MPFR_IS_NEG (xf)) { printf ("Error in check_special_exprange:" " expected 0 and @Inf@, got\n"); mpfr_out_str (stdout, 2, 0, xi, MPFR_RNDN); printf (" and "); mpfr_out_str (stdout, 2, 0, xf, MPFR_RNDN); printf ("\n"); exit (1); } if (inexact != 1) { printf ("Bad inexact value in check_special_exprange:" " expected 1, got %d\n", inexact); exit (1); } eflags = MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW; if (gflags != eflags) { printf ("Bad flags in check_special_exprange:" " expected %u, got %u\n", eflags, gflags); exit (1); } set_emax (emax); /* Test if an underflow occurs in the general case. TODO */ mpfr_clears (xi, xf, x, (mpfr_ptr) 0); }
int mpfr_atan2 (mpfr_ptr dest, mpfr_srcptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode) { mpfr_t tmp, pi; int inexact; mpfr_prec_t prec; mpfr_exp_t e; MPFR_SAVE_EXPO_DECL (expo); MPFR_ZIV_DECL (loop); MPFR_LOG_FUNC (("y[%Pu]=%.*Rg x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (y), mpfr_log_prec, y, mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode), ("atan[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (dest), mpfr_log_prec, dest, inexact)); /* Special cases */ if (MPFR_ARE_SINGULAR (x, y)) { /* atan2(0, 0) does not raise the "invalid" floating-point exception, nor does atan2(y, 0) raise the "divide-by-zero" floating-point exception. -- atan2(±0, -0) returns ±pi.313) -- atan2(±0, +0) returns ±0. -- atan2(±0, x) returns ±pi, for x < 0. -- atan2(±0, x) returns ±0, for x > 0. -- atan2(y, ±0) returns -pi/2 for y < 0. -- atan2(y, ±0) returns pi/2 for y > 0. -- atan2(±oo, -oo) returns ±3pi/4. -- atan2(±oo, +oo) returns ±pi/4. -- atan2(±oo, x) returns ±pi/2, for finite x. -- atan2(±y, -oo) returns ±pi, for finite y > 0. -- atan2(±y, +oo) returns ±0, for finite y > 0. */ if (MPFR_IS_NAN (x) || MPFR_IS_NAN (y)) { MPFR_SET_NAN (dest); MPFR_RET_NAN; } if (MPFR_IS_ZERO (y)) { if (MPFR_IS_NEG (x)) /* +/- PI */ { set_pi: if (MPFR_IS_NEG (y)) { inexact = mpfr_const_pi (dest, MPFR_INVERT_RND (rnd_mode)); MPFR_CHANGE_SIGN (dest); return -inexact; } else return mpfr_const_pi (dest, rnd_mode); } else /* +/- 0 */ { set_zero: MPFR_SET_ZERO (dest); MPFR_SET_SAME_SIGN (dest, y); return 0; } } if (MPFR_IS_ZERO (x)) { return pi_div_2ui (dest, 1, MPFR_IS_NEG (y), rnd_mode); } if (MPFR_IS_INF (y)) { if (!MPFR_IS_INF (x)) /* +/- PI/2 */ return pi_div_2ui (dest, 1, MPFR_IS_NEG (y), rnd_mode); else if (MPFR_IS_POS (x)) /* +/- PI/4 */ return pi_div_2ui (dest, 2, MPFR_IS_NEG (y), rnd_mode); else /* +/- 3*PI/4: Ugly since we have to round properly */ { mpfr_t tmp2; MPFR_ZIV_DECL (loop2); mpfr_prec_t prec2 = MPFR_PREC (dest) + 10; MPFR_SAVE_EXPO_MARK (expo); mpfr_init2 (tmp2, prec2); MPFR_ZIV_INIT (loop2, prec2); for (;;) { mpfr_const_pi (tmp2, MPFR_RNDN); mpfr_mul_ui (tmp2, tmp2, 3, MPFR_RNDN); /* Error <= 2 */ mpfr_div_2ui (tmp2, tmp2, 2, MPFR_RNDN); if (mpfr_round_p (MPFR_MANT (tmp2), MPFR_LIMB_SIZE (tmp2), MPFR_PREC (tmp2) - 2, MPFR_PREC (dest) + (rnd_mode == MPFR_RNDN))) break; MPFR_ZIV_NEXT (loop2, prec2); mpfr_set_prec (tmp2, prec2); } MPFR_ZIV_FREE (loop2); if (MPFR_IS_NEG (y)) MPFR_CHANGE_SIGN (tmp2); inexact = mpfr_set (dest, tmp2, rnd_mode); mpfr_clear (tmp2); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (dest, inexact, rnd_mode); } } MPFR_ASSERTD (MPFR_IS_INF (x)); if (MPFR_IS_NEG (x)) goto set_pi; else goto set_zero; } /* When x is a power of two, we call directly atan(y/x) since y/x is exact. */ if (MPFR_UNLIKELY (MPFR_IS_POWER_OF_2 (x))) { int r; mpfr_t yoverx; unsigned int saved_flags = __gmpfr_flags; mpfr_init2 (yoverx, MPFR_PREC (y)); if (MPFR_LIKELY (mpfr_div_2si (yoverx, y, MPFR_GET_EXP (x) - 1, MPFR_RNDN) == 0)) { /* Here the flags have not changed due to mpfr_div_2si. */ r = mpfr_atan (dest, yoverx, rnd_mode); mpfr_clear (yoverx); return r; } else { /* Division is inexact because of a small exponent range */ mpfr_clear (yoverx); __gmpfr_flags = saved_flags; } } MPFR_SAVE_EXPO_MARK (expo); /* Set up initial prec */ prec = MPFR_PREC (dest) + 3 + MPFR_INT_CEIL_LOG2 (MPFR_PREC (dest)); mpfr_init2 (tmp, prec); MPFR_ZIV_INIT (loop, prec); if (MPFR_IS_POS (x)) /* use atan2(y,x) = atan(y/x) */ for (;;) { int div_inex; MPFR_BLOCK_DECL (flags); MPFR_BLOCK (flags, div_inex = mpfr_div (tmp, y, x, MPFR_RNDN)); if (div_inex == 0) { /* Result is exact. */ inexact = mpfr_atan (dest, tmp, rnd_mode); goto end; } /* Error <= ulp (tmp) except in case of underflow or overflow. */ /* If the division underflowed, since |atan(z)/z| < 1, we have an underflow. */ if (MPFR_UNDERFLOW (flags)) { int sign; /* In the case MPFR_RNDN with 2^(emin-2) < |y/x| < 2^(emin-1): The smallest significand value S > 1 of |y/x| is: * 1 / (1 - 2^(-px)) if py <= px, * (1 - 2^(-px) + 2^(-py)) / (1 - 2^(-px)) if py >= px. Therefore S - 1 > 2^(-pz), where pz = max(px,py). We have: atan(|y/x|) > atan(z), where z = 2^(emin-2) * (1 + 2^(-pz)). > z - z^3 / 3. > 2^(emin-2) * (1 + 2^(-pz) - 2^(2 emin - 5)) Assuming pz <= -2 emin + 5, we can round away from zero (this is what mpfr_underflow always does on MPFR_RNDN). In the case MPFR_RNDN with |y/x| <= 2^(emin-2), we round toward zero, as |atan(z)/z| < 1. */ MPFR_ASSERTN (MPFR_PREC_MAX <= 2 * (mpfr_uexp_t) - MPFR_EMIN_MIN + 5); if (rnd_mode == MPFR_RNDN && MPFR_IS_ZERO (tmp)) rnd_mode = MPFR_RNDZ; sign = MPFR_SIGN (tmp); mpfr_clear (tmp); MPFR_SAVE_EXPO_FREE (expo); return mpfr_underflow (dest, rnd_mode, sign); } mpfr_atan (tmp, tmp, MPFR_RNDN); /* Error <= 2*ulp (tmp) since abs(D(arctan)) <= 1 */ /* TODO: check that the error bound is correct in case of overflow. */ /* FIXME: Error <= ulp(tmp) ? */ if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp, prec - 2, MPFR_PREC (dest), rnd_mode))) break; MPFR_ZIV_NEXT (loop, prec); mpfr_set_prec (tmp, prec); } else /* x < 0 */ /* Use sign(y)*(PI - atan (|y/x|)) */ { mpfr_init2 (pi, prec); for (;;) { mpfr_div (tmp, y, x, MPFR_RNDN); /* Error <= ulp (tmp) */ /* If tmp is 0, we have |y/x| <= 2^(-emin-2), thus atan|y/x| < 2^(-emin-2). */ MPFR_SET_POS (tmp); /* no error */ mpfr_atan (tmp, tmp, MPFR_RNDN); /* Error <= 2*ulp (tmp) since abs(D(arctan)) <= 1 */ mpfr_const_pi (pi, MPFR_RNDN); /* Error <= ulp(pi) /2 */ e = MPFR_NOTZERO(tmp) ? MPFR_GET_EXP (tmp) : __gmpfr_emin - 1; mpfr_sub (tmp, pi, tmp, MPFR_RNDN); /* see above */ if (MPFR_IS_NEG (y)) MPFR_CHANGE_SIGN (tmp); /* Error(tmp) <= (1/2+2^(EXP(pi)-EXP(tmp)-1)+2^(e-EXP(tmp)+1))*ulp <= 2^(MAX (MAX (EXP(PI)-EXP(tmp)-1, e-EXP(tmp)+1), -1)+2)*ulp(tmp) */ e = MAX (MAX (MPFR_GET_EXP (pi)-MPFR_GET_EXP (tmp) - 1, e - MPFR_GET_EXP (tmp) + 1), -1) + 2; if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp, prec - e, MPFR_PREC (dest), rnd_mode))) break; MPFR_ZIV_NEXT (loop, prec); mpfr_set_prec (tmp, prec); mpfr_set_prec (pi, prec); } mpfr_clear (pi); } inexact = mpfr_set (dest, tmp, rnd_mode); end: MPFR_ZIV_FREE (loop); mpfr_clear (tmp); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (dest, inexact, rnd_mode); }
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); }
static void generic_tests (void) { mpfr_t exact_sum, sum1, sum2; mpfr_t *t; mpfr_ptr *p; mpfr_prec_t precmax = 444; int i, m, nmax = 500; int rnd_mode; t = (mpfr_t *) tests_allocate (nmax * sizeof(mpfr_t)); p = (mpfr_ptr *) tests_allocate (nmax * sizeof(mpfr_ptr)); for (i = 0; i < nmax; i++) { mpfr_init2 (t[i], precmax); p[i] = t[i]; } mpfr_inits2 (precmax, exact_sum, sum1, sum2, (mpfr_ptr) 0); for (m = 0; m < 4000; m++) { int non_uniform, n; mpfr_prec_t prec; non_uniform = randlimb () % 10; n = (randlimb () % nmax) + 1; prec = MPFR_PREC_MIN + (randlimb () % (precmax - MPFR_PREC_MIN + 1)); mpfr_set_prec (sum1, prec); mpfr_set_prec (sum2, prec); for (i = 0; i < n; i++) { mpfr_set_prec (t[i], MPFR_PREC_MIN + (randlimb () % (precmax - MPFR_PREC_MIN + 1))); mpfr_urandomb (t[i], RANDS); if (m % 8 != 0 && (m % 8 == 1 || (randlimb () & 1))) mpfr_neg (t[i], t[i], MPFR_RNDN); if (non_uniform && MPFR_NOTZERO (t[i])) mpfr_set_exp (t[i], randlimb () % 1000); /* putchar ("-0+"[SIGN (mpfr_sgn (t[i])) + 1]); */ } /* putchar ('\n'); */ get_exact_sum (exact_sum, t, n); RND_LOOP (rnd_mode) { int inex1, inex2; inex1 = mpfr_set (sum1, exact_sum, (mpfr_rnd_t) rnd_mode); inex2 = mpfr_sum (sum2, p, n, (mpfr_rnd_t) rnd_mode); if (!(mpfr_equal_p (sum1, sum2) && SAME_SIGN (inex1, inex2))) { printf ("generic_tests failed on m = %d, %s\n", m, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd_mode)); printf ("Expected "); mpfr_dump (sum1); printf ("with inex = %d\n", inex1); printf ("Got "); mpfr_dump (sum2); printf ("with inex = %d\n", inex2); exit (1); } } } for (i = 0; i < nmax; i++) mpfr_clear (t[i]); mpfr_clears (exact_sum, sum1, sum2, (mpfr_ptr) 0); tests_free (t, nmax * sizeof(mpfr_t)); tests_free (p, nmax * sizeof(mpfr_ptr)); }
/* generic code */ __float128 mpfr_get_float128 (mpfr_srcptr x, mpfr_rnd_t rnd_mode) { if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) return (__float128) mpfr_get_d (x, rnd_mode); else /* now x is a normal non-zero number */ { __float128 r; /* result */ __float128 m; double s; /* part of result */ mpfr_exp_t sh; /* exponent shift, so that x/2^sh is in the double range */ mpfr_t y, z; int sign; /* first round x to the target __float128 precision, so that all subsequent operations are exact (this avoids double rounding problems) */ mpfr_init2 (y, IEEE_FLOAT128_MANT_DIG); mpfr_init2 (z, IEEE_FLOAT128_MANT_DIG); mpfr_set (y, x, rnd_mode); sh = MPFR_GET_EXP (y); sign = MPFR_SIGN (y); MPFR_SET_EXP (y, 0); MPFR_SET_POS (y); r = 0.0; do { s = mpfr_get_d (y, MPFR_RNDN); /* high part of y */ r += (__float128) s; mpfr_set_d (z, s, MPFR_RNDN); /* exact */ mpfr_sub (y, y, z, MPFR_RNDN); /* exact */ } while (MPFR_NOTZERO (y)); mpfr_clear (z); mpfr_clear (y); /* we now have to multiply r by 2^sh */ MPFR_ASSERTD (r > 0); if (sh != 0) { /* An overflow may occur (example: 0.5*2^1024) */ while (r < 1.0) { r += r; sh--; } if (sh > 0) m = 2.0; else { m = 0.5; sh = -sh; } for (;;) { if (sh % 2) r = r * m; sh >>= 1; if (sh == 0) break; m = m * m; } } if (sign < 0) r = -r; return r; } }
static void check_parse (void) { mpfr_t x; char *s; int res; mpfr_init (x); /* Invalid data */ mpfr_set_si (x, -1, MPFR_RNDN); res = mpfr_strtofr (x, " invalid", NULL, 10, MPFR_RNDN); if (MPFR_NOTZERO (x) || MPFR_IS_NEG (x)) { printf ("Failed parsing ' invalid' (1)\n X="); mpfr_dump (x); exit (1); } MPFR_ASSERTN (res == 0); mpfr_set_si (x, -1, MPFR_RNDN); res = mpfr_strtofr (x, " invalid", &s, 0, MPFR_RNDN); if (MPFR_NOTZERO (x) || MPFR_IS_NEG (x) || strcmp (s, " invalid")) { printf ("Failed parsing ' invalid' (2)\n S=%s\n X=", s); mpfr_dump (x); exit (1); } MPFR_ASSERTN (res == 0); /* Check if it stops correctly */ mpfr_strtofr (x, "15*x", &s, 10, MPFR_RNDN); if (mpfr_cmp_ui (x, 15) || strcmp (s, "*x")) { printf ("Failed parsing '15*x'\n S=%s\n X=", s); mpfr_dump (x); exit (1); } /* Check for leading spaces */ mpfr_strtofr (x, " 1.5E-10 *x^2", &s, 10, MPFR_RNDN); if (mpfr_cmp_str1 (x, "1.5E-10") || strcmp (s, " *x^2")) { printf ("Failed parsing '1.5E-10*x^2'\n S=%s\n X=", s); mpfr_dump (x); exit (1); } /* Check for leading sign */ mpfr_strtofr (x, " +17.5E-42E ", &s, 10, MPFR_RNDN); if (mpfr_cmp_str1 (x, "17.5E-42") || strcmp (s, "E ")) { printf ("Failed parsing '+17.5E-42E '\n S=%s\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "-17.5E+42E\n", &s, 10, MPFR_RNDN); if (mpfr_cmp_str1 (x, "-17.5E42") || strcmp (s, "E\n")) { printf ("Failed parsing '-17.5E+42\\n'\n S=%s\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* P form */ mpfr_strtofr (x, "0x42P17", &s, 16, MPFR_RNDN); if (mpfr_cmp_str (x, "8650752", 10, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '0x42P17' (base = 16)\n S='%s'\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "-0X42p17", &s, 16, MPFR_RNDN); if (mpfr_cmp_str (x, "-8650752", 10, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '-0x42p17' (base = 16)\n S='%s'\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "42p17", &s, 16, MPFR_RNDN); if (mpfr_cmp_str (x, "8650752", 10, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '42p17' (base = 16)\n S='%s'\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "-42P17", &s, 16, MPFR_RNDN); if (mpfr_cmp_str (x, "-8650752", 10, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '-42P17' (base = 16)\n S='%s'\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "0b1001P17", &s, 2, MPFR_RNDN); if (mpfr_cmp_str (x, "1179648", 10, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '0b1001P17' (base = 2)\n S='%s'\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "-0B1001p17", &s, 2, MPFR_RNDN); if (mpfr_cmp_str (x, "-1179648", 10, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '-0B1001p17' (base = 2)\n S='%s'\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "1001p17", &s, 2, MPFR_RNDN); if (mpfr_cmp_str (x, "1179648", 10, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '1001p17' (base = 2)\n S='%s'\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "-1001P17", &s, 2, MPFR_RNDN); if (mpfr_cmp_str (x, "-1179648", 10, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '-1001P17' (base = 2)\n S='%s'\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* Check for auto-detection of the base */ mpfr_strtofr (x, "+0x42P17", &s, 0, MPFR_RNDN); if (mpfr_cmp_str (x, "42P17", 16, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '+0x42P17'\n S=%s\n X=", s); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "-42E17", &s, 0, MPFR_RNDN); if (mpfr_cmp_str (x, "-42E17", 10, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '-42E17'\n S=%s\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "-42P17", &s, 0, MPFR_RNDN); if (mpfr_cmp_str (x, "-42", 10, MPFR_RNDN) || strcmp (s, "P17")) { printf ("Failed parsing '-42P17' (base = 0)\n S='%s'\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, " 0b0101.011@42", &s, 0, MPFR_RNDN); if (mpfr_cmp_str (x, "0101.011@42", 2, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '0101.011@42'\n S=%s\n X=", s); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, " 0b0101.011P42", &s, 0, MPFR_RNDN); if (mpfr_cmp_str (x, "0101.011@42", 2, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '0101.011@42'\n S=%s\n X=", s); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "+0x42@17", &s, 0, MPFR_RNDN); if (mpfr_cmp_str (x, "4.2@18", 16, MPFR_RNDN) || *s != 0) { printf ("Failed parsing '+0x42P17'\n S=%s\n X=", s); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* Check for space inside the mantissa */ mpfr_strtofr (x, "+0x4 2@17", &s, 0, MPFR_RNDN); if (mpfr_cmp_ui (x, 4) || strcmp(s," 2@17")) { printf ("Failed parsing '+0x4 2@17'\n S=%s\n X=", s); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "+0x42 P17", &s, 0, MPFR_RNDN); if (mpfr_cmp_ui (x, 0x42) || strcmp(s," P17")) { printf ("Failed parsing '+0x42 P17'\n S=%s\n X=", s); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* Space between mantissa and exponent */ mpfr_strtofr (x, " -0b0101P 17", &s, 0, MPFR_RNDN); if (mpfr_cmp_si (x, -5) || strcmp(s,"P 17")) { printf ("Failed parsing '-0b0101P 17'\n S=%s\n X=", s); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* Check for Invalid exponent. */ mpfr_strtofr (x, " -0b0101PF17", &s, 0, MPFR_RNDN); if (mpfr_cmp_si (x, -5) || strcmp(s,"PF17")) { printf ("Failed parsing '-0b0101PF17'\n S=%s\n X=", s); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* At least one digit in the mantissa. */ mpfr_strtofr (x, " .E10", &s, 0, MPFR_RNDN); if (strcmp(s," .E10")) { printf ("Failed parsing ' .E10'\n S=%s\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* Check 2 '.': 2.3.4 */ mpfr_strtofr (x, "-1.2.3E4", &s, 0, MPFR_RNDN); if (mpfr_cmp_str1 (x, "-1.2") || strcmp(s,".3E4")) { printf ("Failed parsing '-1.2.3E4'\n S=%s\n X=", s); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* Check for 0x and 0b */ mpfr_strtofr (x, " 0xG", &s, 0, MPFR_RNDN); if (mpfr_cmp_ui (x, 0) || strcmp(s,"xG")) { printf ("Failed parsing ' 0xG'\n S=%s\n X=", s); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, " 0b2", &s, 0, MPFR_RNDN); if (mpfr_cmp_ui (x, 0) || strcmp(s,"b2")) { printf ("Failed parsing ' 0b2'\n S=%s\n X=", s); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, "-0x.23@2Z33", &s, 0, MPFR_RNDN); if (mpfr_cmp_si (x, -0x23) || strcmp(s,"Z33")) { printf ("Failed parsing '-0x.23@2Z33'\n S=%s\n X=", s); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_strtofr (x, " 0x", &s, 0, MPFR_RNDN); if (mpfr_cmp_ui (x, 0) || strcmp(s,"x")) { printf ("Failed parsing ' 0x'\n S=%s\n X=", s); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_clear (x); }
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; }