/** * Rootfinding by interval bisection. * * Brent's method is faster though. */ int RootFinder::bisection(double t_begin, double t_end, double* root) { double t_mid; double f_t_begin = f(t_begin); double f_t_end = f(t_end); double f_t_mid; uint32_t i = 2; if (SAME_SIGN(f_t_begin, f_t_end)) return false; while (i++ < MAX_ITER) { t_mid = 0.5 * (t_begin + t_end); f_t_mid = f(t_mid); if (fabs(f_t_mid) < tolerance) { *root = t_mid; return i; } if (SAME_SIGN(f_t_begin, f_t_mid)) { t_begin = t_mid; f_t_begin = f_t_mid; } else { t_end = t_mid; f_t_end = f_t_mid; } } return false; }
int RootFinder::regula_falsi(double t_begin, double t_end, double* root) { double t_mid; double f_t_begin = f(t_begin); double f_t_end = f(t_end); double f_t_mid; uint32_t i = 2; if (SAME_SIGN(f_t_begin, f_t_end)) return false; while (i++ < MAX_ITER) { t_mid = ( f_t_end * t_begin - f_t_begin * t_end ) / ( f_t_end - f_t_begin ); f_t_mid = f(t_mid); if (fabs(f_t_mid) < tolerance) { *root = t_mid; return i; } if (SAME_SIGN(f_t_begin, f_t_mid)) { t_begin = t_mid; f_t_begin = f_t_mid; } else { t_end = t_mid; f_t_end = f_t_mid; } } return false; }
static void test_underflow3 (int n) { mpfr_t x, y, z, t1, t2; int sign, k, s, rnd, inex1, inex2; mpfr_exp_t e; mpfr_flags_t flags1, flags2; mpfr_inits2 (4, x, z, t1, t2, (mpfr_ptr) 0); mpfr_init2 (y, 6); e = mpfr_get_emin () - 1; for (sign = 1; sign >= -1; sign -= 2) for (k = 1; k <= 7; k++) for (s = -1; s <= 1; s++) { mpfr_set_si_2exp (x, sign, e, MPFR_RNDN); mpfr_set_si_2exp (y, 8*k+s, -6, MPFR_RNDN); mpfr_neg (z, x, MPFR_RNDN); /* x = sign * 2^(emin-1) y = (8 * k + s) * 2^(-6) = k / 8 + s * 2^(-6) z = -x = -sign * 2^(emin-1) FMA(x,y,z) = sign * ((k-8) * 2^(emin-4) + s * 2^(emin-7)) exactly. Note: The purpose of the s * 2^(emin-7) term is to yield double rounding when scaling for k = 4, s != 0, MPFR_RNDN. */ RND_LOOP (rnd) { mpfr_clear_flags (); inex1 = mpfr_set_si_2exp (t1, sign * (8*k+s-64), e-6, (mpfr_rnd_t) rnd); flags1 = __gmpfr_flags; mpfr_clear_flags (); inex2 = mpfr_fma (t2, x, y, z, (mpfr_rnd_t) rnd); flags2 = __gmpfr_flags; if (! (mpfr_equal_p (t1, t2) && SAME_SIGN (inex1, inex2) && flags1 == flags2)) { printf ("Error in test_underflow3, n = %d, sign = %d," " k = %d, s = %d, %s\n", n, sign, k, s, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); printf ("Expected "); mpfr_dump (t1); printf (" with inex ~ %d, flags =", inex1); flags_out (flags1); printf ("Got "); mpfr_dump (t2); printf (" with inex ~ %d, flags =", inex2); flags_out (flags2); exit (1); } } } mpfr_clears (x, y, z, t1, t2, (mpfr_ptr) 0); }
static void check (long int n, long int d, mpfr_rnd_t rnd, const char *ys) { mpq_t q; mpfr_t x, t; int inexact, compare; unsigned int flags, ex_flags; mpfr_init2 (x, 53); mpfr_init2 (t, mpfr_get_prec (x) + mp_bits_per_limb); mpq_init (q); mpq_set_si (q, n, d); mpfr_clear_flags (); inexact = mpfr_set_q (x, q, rnd); flags = __gmpfr_flags; /* check values */ if (mpfr_cmp_str1 (x, ys)) { printf ("Error for q = %ld/%ld and rnd = %s\n", n, d, mpfr_print_rnd_mode (rnd)); printf ("correct result is %s, mpfr_set_q gives ", ys); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* check inexact flag */ if (mpfr_mul_ui (t, x, (d < 0) ? (-d) : d, rnd)) { printf ("t <- x * d should be exact\n"); exit (1); } compare = mpfr_cmp_si (t, n); if (! SAME_SIGN (inexact, compare)) { printf ("Wrong ternary value for q = %ld/%ld and rnd = %s:\n" "expected %d or equivalent, got %d\n", n, d, mpfr_print_rnd_mode (rnd), compare, inexact); exit (1); } ex_flags = compare == 0 ? 0 : MPFR_FLAGS_INEXACT; if (flags != ex_flags) { printf ("Wrong flags for q = %ld/%ld and rnd = %s:\n", n, d, mpfr_print_rnd_mode (rnd)); printf ("Expected flags:"); flags_out (ex_flags); printf ("Got flags: "); flags_out (flags); exit (1); } mpfr_clear (x); mpfr_clear (t); mpq_clear (q); }
static void check_one (mpz_ptr z) { int inex; int sh, neg; mpfr_t f; mpz_t got; mpfr_init2 (f, MAX( mpz_sizeinbase (z, 2), MPFR_PREC_MIN) ); mpz_init (got); for (sh = -2*GMP_NUMB_BITS ; sh < 2*GMP_NUMB_BITS ; sh++) { for (neg = 0; neg <= 1; neg++) { mpz_neg (z, z); mpfr_set_z (f, z, MPFR_RNDN); if (sh < 0) { mpz_tdiv_q_2exp (z, z, -sh); mpfr_div_2exp (f, f, -sh, MPFR_RNDN); } else { mpz_mul_2exp (z, z, sh); mpfr_mul_2exp (f, f, sh, MPFR_RNDN); } inex = mpfr_get_z (got, f, MPFR_RNDZ); if (mpz_cmp (got, z) != 0) { printf ("Wrong result for shift=%d\n", sh); printf (" f "); mpfr_dump (f); printf (" got "); mpz_dump (got); printf (" want "); mpz_dump (z); exit (1); } if (! SAME_SIGN (inex, - mpfr_cmp_z (f, z))) { printf ("Wrong inexact value for shift=%d\n", sh); printf (" f "); mpfr_dump (f); printf (" got %+d\n", inex); printf (" want %+d\n", -mpfr_cmp_z (f, z)); exit (1); } } } mpfr_clear (f); mpz_clear (got); }
static void check_overflow (void) { mpfr_t sum1, sum2, x, y; mpfr_ptr t[2 * NOVFL]; mpfr_exp_t emin, emax; int i, r; emin = mpfr_get_emin (); emax = mpfr_get_emax (); set_emin (MPFR_EMIN_MIN); set_emax (MPFR_EMAX_MAX); mpfr_inits2 (32, sum1, sum2, x, y, (mpfr_ptr) 0); mpfr_setmax (x, mpfr_get_emax ()); mpfr_neg (y, x, MPFR_RNDN); for (i = 0; i < 2 * NOVFL; i++) t[i] = i < NOVFL ? x : y; /* Two kinds of test: * i = 1: overflow. * i = 2: intermediate overflow (exact sum is 0). */ for (i = 1; i <= 2; i++) RND_LOOP(r) { int inex1, inex2; inex1 = mpfr_add (sum1, x, i == 1 ? x : y, (mpfr_rnd_t) r); inex2 = mpfr_sum (sum2, t, i * NOVFL, (mpfr_rnd_t) r); MPFR_ASSERTN (mpfr_check (sum1)); MPFR_ASSERTN (mpfr_check (sum2)); if (!(mpfr_equal_p (sum1, sum2) && SAME_SIGN (inex1, inex2))) { printf ("Error in check_overflow on %s, i = %d\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), i); printf ("Expected "); mpfr_dump (sum1); printf ("with inex = %d\n", inex1); printf ("Got "); mpfr_dump (sum2); printf ("with inex = %d\n", inex2); exit (1); } } mpfr_clears (sum1, sum2, x, y, (mpfr_ptr) 0); set_emin (emin); set_emax (emax); }
/* 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); }
int SturmSequence::signChanges(double x) const { uint32_t num = f.size() - 1; // Ignore last polynomial that is constant 0. double values[num]; eval(x,values); uint32_t result = 0; for(uint32_t i = 1; i < num; i++) { if (!SAME_SIGN(values[i], values[i-1])) { result++; } } return result; }
/* Occurs in branches/new-sum/src/sum.c@9344 on a 64-bit machine. */ static void bug20150327 (void) { mpfr_t sum1, sum2, t[3]; mpfr_ptr p[3]; char *s[3] = { "0.10000111110101000010101011100001", "1E-100", "0.1E95" }; int i, r; mpfr_inits2 (58, sum1, sum2, (mpfr_ptr) 0); for (i = 0; i < 3; i++) { mpfr_init2 (t[i], 64); mpfr_set_str (t[i], s[i], 2, MPFR_RNDN); p[i] = t[i]; } RND_LOOP(r) { int inex1, inex2; mpfr_set (sum1, t[2], MPFR_RNDN); inex1 = -1; if (MPFR_IS_LIKE_RNDU ((mpfr_rnd_t) r, 1)) { mpfr_nextabove (sum1); inex1 = 1; } inex2 = mpfr_sum (sum2, p, 3, (mpfr_rnd_t) r); if (!(mpfr_equal_p (sum1, sum2) && SAME_SIGN (inex1, inex2))) { printf ("mpfr_sum incorrect in bug20150327 for %s:\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r)); 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 < 3; i++) mpfr_clear (t[i]); mpfr_clears (sum1, sum2, (mpfr_ptr) 0); }
static void bug20081028 (void) { int i; int inexact, res; mpfr_rnd_t rnd; mpfr_t x, y; char *s; mpfr_init2 (x, 32); mpfr_init2 (y, 32); for (i = 0 ; i < numberof (Bug20081028Table) ; i++) { rnd = Bug20081028Table[i].rnd; inexact = Bug20081028Table[i].inexact; mpfr_set_str_binary (x, Bug20081028Table[i].binstr); res = mpfr_strtofr (y, Bug20081028Table[i].str, &s, 10, rnd); if (s == NULL || *s != 0) { printf ("Error in Bug20081028: strtofr didn't parse entire input\n" "for (i=%d) Str=\"%s\"", i, Bug20081028Table[i].str); exit (1); } if (! SAME_SIGN (res, inexact)) { printf ("Error in Bug20081028: expected %s ternary value, " "got %d\nfor (i=%d) Rnd=%s Str=\"%s\"\n Set binary gives: ", inexact > 0 ? "positive" : "negative", res, i, mpfr_print_rnd_mode(rnd), Bug20081028Table[i].str); mpfr_dump (x); printf (" strtofr gives: "); mpfr_dump (y); exit (1); } if (mpfr_cmp (x, y)) { printf ("Error in Bug20081028: Results differ between strtofr and " "set_binary\nfor (i=%d) Rnd=%s Str=\"%s\"\n" " Set binary gives: ", i, mpfr_print_rnd_mode(rnd), Bug20081028Table[i].str); mpfr_dump (x); printf (" strtofr gives: "); mpfr_dump (y); exit (1); } } mpfr_clear (y); mpfr_clear (x); }
static void test_small (void) { mpfr_t x, y, z1, z2; int inex1, inex2; unsigned int flags; /* Test hypot(x,x) with x = 2^(emin-1). Result is x * sqrt(2). */ mpfr_inits2 (8, x, y, z1, z2, (mpfr_ptr) 0); mpfr_set_si_2exp (x, 1, mpfr_get_emin () - 1, MPFR_RNDN); mpfr_set_si_2exp (y, 1, mpfr_get_emin () - 1, MPFR_RNDN); mpfr_set_ui (z1, 2, MPFR_RNDN); inex1 = mpfr_sqrt (z1, z1, MPFR_RNDN); inex2 = mpfr_mul (z1, z1, x, MPFR_RNDN); MPFR_ASSERTN (inex2 == 0); mpfr_clear_flags (); inex2 = mpfr_hypot (z2, x, y, MPFR_RNDN); flags = __gmpfr_flags; if (mpfr_cmp (z1, z2) != 0) { printf ("Error in test_small%s\nExpected ", ext ? ", extended exponent range" : ""); mpfr_out_str (stdout, 2, 0, z1, MPFR_RNDN); printf ("\nGot "); mpfr_out_str (stdout, 2, 0, z2, MPFR_RNDN); printf ("\n"); exit (1); } if (! SAME_SIGN (inex1, inex2)) { printf ("Bad ternary value in test_small%s\nExpected %d, got %d\n", ext ? ", extended exponent range" : "", inex1, inex2); exit (1); } if (flags != MPFR_FLAGS_INEXACT) { printf ("Bad flags in test_small%s\nExpected %u, got %u\n", ext ? ", extended exponent range" : "", (unsigned int) MPFR_FLAGS_INEXACT, flags); exit (1); } mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0); }
/* TODO: A test with more inputs (but can't be compared to mpfr_add). */ static void check_extreme (void) { mpfr_t u, v, w, x, y; mpfr_ptr t[2]; int i, inex1, inex2, r; t[0] = u; t[1] = v; mpfr_inits2 (32, u, v, w, x, y, (mpfr_ptr) 0); mpfr_setmin (u, mpfr_get_emax ()); mpfr_setmax (v, mpfr_get_emin ()); mpfr_setmin (w, mpfr_get_emax () - 40); RND_LOOP (r) for (i = 0; i < 2; i++) { mpfr_set_prec (x, 64); inex1 = mpfr_add (x, u, w, MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); inex1 = mpfr_prec_round (x, 32, (mpfr_rnd_t) r); inex2 = mpfr_sum (y, t, 2, (mpfr_rnd_t) r); if (!(mpfr_equal_p (x, y) && SAME_SIGN (inex1, inex2))) { printf ("Error in check_extreme (%s, i = %d)\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), i); printf ("Expected "); mpfr_dump (x); printf ("with inex = %d\n", inex1); printf ("Got "); mpfr_dump (y); printf ("with inex = %d\n", inex2); exit (1); } mpfr_neg (v, v, MPFR_RNDN); mpfr_neg (w, w, MPFR_RNDN); } mpfr_clears (u, v, w, x, y, (mpfr_ptr) 0); }
static void check_underflow (void) { mpfr_t sum1, sum2, t[NUNFL]; mpfr_ptr p[NUNFL]; mpfr_prec_t precmax = 444; mpfr_exp_t emin, emax; unsigned int ex_flags, flags; int c, i; emin = mpfr_get_emin (); emax = mpfr_get_emax (); set_emin (MPFR_EMIN_MIN); set_emax (MPFR_EMAX_MAX); ex_flags = MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT; mpfr_init2 (sum1, MPFR_PREC_MIN); mpfr_init2 (sum2, precmax); for (i = 0; i < NUNFL; i++) { mpfr_init2 (t[i], precmax); p[i] = t[i]; } for (c = 0; c < 8; c++) { mpfr_prec_t fprec; int n, neg, r; fprec = MPFR_PREC_MIN + (randlimb () % (precmax - MPFR_PREC_MIN + 1)); n = 3 + (randlimb () % (NUNFL - 2)); MPFR_ASSERTN (n <= NUNFL); mpfr_set_prec (sum2, (randlimb () & 1) ? MPFR_PREC_MIN : precmax); mpfr_set_prec (t[0], fprec + 64); mpfr_set_zero (t[0], 1); for (i = 1; i < n; i++) { int inex; mpfr_set_prec (t[i], MPFR_PREC_MIN + (randlimb () % (fprec - MPFR_PREC_MIN + 1))); do mpfr_urandomb (t[i], RANDS); while (MPFR_IS_ZERO (t[i])); mpfr_set_exp (t[i], MPFR_EMIN_MIN); inex = mpfr_sub (t[0], t[0], t[i], MPFR_RNDN); MPFR_ASSERTN (inex == 0); } neg = randlimb () & 1; if (neg) mpfr_nextbelow (t[0]); else mpfr_nextabove (t[0]); RND_LOOP(r) { int inex1, inex2; mpfr_set_zero (sum1, 1); if (neg) mpfr_nextbelow (sum1); else mpfr_nextabove (sum1); inex1 = mpfr_div_2ui (sum1, sum1, 2, (mpfr_rnd_t) r); mpfr_clear_flags (); inex2 = mpfr_sum (sum2, p, n, (mpfr_rnd_t) r); flags = __gmpfr_flags; MPFR_ASSERTN (mpfr_check (sum1)); MPFR_ASSERTN (mpfr_check (sum2)); if (flags != ex_flags) { printf ("Bad flags in check_underflow on %s, c = %d\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), c); printf ("Expected flags:"); flags_out (ex_flags); printf ("Got flags: "); flags_out (flags); printf ("sum = "); mpfr_dump (sum2); exit (1); } if (!(mpfr_equal_p (sum1, sum2) && SAME_SIGN (inex1, inex2))) { printf ("Error in check_underflow on %s, c = %d\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), c); 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 < NUNFL; i++) mpfr_clear (t[i]); mpfr_clears (sum1, sum2, (mpfr_ptr) 0); set_emin (emin); set_emax (emax); }
/* i * 2^(46+h) + j * 2^(45+h) + k * 2^(44+h) + f * 2^(-2), with -1 <= i, j, k <= 1, i != 0, -3 <= f <= 3, and * prec set up so that ulp(exact sum) = 2^0, then * prec set up so that ulp(exact sum) = 2^(44+h) when possible, i.e. when prec >= MPFR_PREC_MIN. ------ Some explanations: ulp(exact sum) = 2^q means EXP(exact sum) - prec = q where prec is the precision of the output. Thus ulp(exact sum) = 2^0 is achieved by setting prec = EXP(s3), where s3 is the exact sum (computed with mpfr_add's and sufficient precision). Then ulp(exact sum) = 2^(44+h) is achieved by subtracting 44+h from prec. The loop on prec does this. Since EXP(s3) <= 47+h, prec <= 3 at the second iteration, thus there will be at most 2 iterations. Whether a second iteration is done or not depends on EXP(s3), i.e. the values of the parameters, and the value of MPFR_PREC_MIN. */ static void check1 (int h) { mpfr_t sum1, sum2, s1, s2, s3, t[4]; mpfr_ptr p[4]; int i, j, k, f, prec, r, inex1, inex2; mpfr_init2 (sum1, 47 + h); mpfr_init2 (sum2, 47 + h); mpfr_init2 (s1, 3); mpfr_init2 (s2, 3); mpfr_init2 (s3, 49 + h); for (i = 0; i < 4; i++) { mpfr_init2 (t[i], 2); p[i] = t[i]; } for (i = -1; i <= 1; i += 2) { mpfr_set_si_2exp (t[0], i, 46 + h, MPFR_RNDN); for (j = -1; j <= 1; j++) { mpfr_set_si_2exp (t[1], j, 45 + h, MPFR_RNDN); inex1 = mpfr_add (s1, t[0], t[1], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (k = -1; k <= 1; k++) { mpfr_set_si_2exp (t[2], k, 44 + h, MPFR_RNDN); inex1 = mpfr_add (s2, s1, t[2], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (f = -3; f <= 3; f++) { mpfr_set_si_2exp (t[3], f, -2, MPFR_RNDN); inex1 = mpfr_add (s3, s2, t[3], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (prec = mpfr_get_exp (s3); prec >= MPFR_PREC_MIN; prec -= 44 + h) { mpfr_set_prec (sum1, prec); mpfr_set_prec (sum2, prec); RND_LOOP (r) { inex1 = mpfr_set (sum1, s3, (mpfr_rnd_t) r); inex2 = mpfr_sum (sum2, p, 4, (mpfr_rnd_t) r); MPFR_ASSERTN (mpfr_check (sum1)); MPFR_ASSERTN (mpfr_check (sum2)); if (!(mpfr_equal_p (sum1, sum2) && SAME_SIGN (inex1, inex2))) { printf ("Error in check1 on %s, prec = %d, " "i = %d, j = %d, k = %d, f = %d, " "h = %d\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), prec, i, j, k, f, h); 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 < 4; i++) mpfr_clear (t[i]); mpfr_clears (sum1, sum2, s1, s2, s3, (mpfr_ptr) 0); }
static int tiny_aux (int stop, mpfr_exp_t e) { mpfr_t x, y, z; int r, s, spm, inex, err = 0; int expected_dir[2][5] = { { 1, -1, 1, -1, 1 }, { 1, 1, 1, -1, -1 } }; mpfr_exp_t saved_emax; saved_emax = mpfr_get_emax (); mpfr_init2 (x, 32); mpfr_inits2 (8, y, z, (mpfr_ptr) 0); mpfr_set_ui_2exp (x, 1, e, MPFR_RNDN); spm = 1; for (s = 0; s < 2; s++) { RND_LOOP(r) { mpfr_rnd_t rr = (mpfr_rnd_t) r; mpfr_exp_t exponent, emax; /* Exponent of the rounded value in unbounded exponent range. */ exponent = expected_dir[s][r] < 0 && s == 0 ? - e : 1 - e; for (emax = exponent - 1; emax <= exponent; emax++) { unsigned int flags, expected_flags = MPFR_FLAGS_INEXACT; int overflow, expected_inex = expected_dir[s][r]; if (emax > MPFR_EMAX_MAX) break; mpfr_set_emax (emax); mpfr_clear_flags (); inex = mpfr_gamma (y, x, rr); flags = __gmpfr_flags; mpfr_clear_flags (); mpfr_set_si_2exp (z, spm, - e, MPFR_RNDU); overflow = mpfr_overflow_p (); /* z is 1/x - euler rounded toward +inf */ if (overflow && rr == MPFR_RNDN && s == 1) expected_inex = -1; if (expected_inex < 0) mpfr_nextbelow (z); /* 1/x - euler rounded toward -inf */ if (exponent > emax) expected_flags |= MPFR_FLAGS_OVERFLOW; if (!(mpfr_equal_p (y, z) && flags == expected_flags && SAME_SIGN (inex, expected_inex))) { printf ("Error in tiny for s = %d, r = %s, emax = %" MPFR_EXP_FSPEC "d%s\n on ", s, mpfr_print_rnd_mode (rr), emax, exponent > emax ? " (overflow)" : ""); mpfr_dump (x); printf (" expected inex = %2d, ", expected_inex); mpfr_dump (z); printf (" got inex = %2d, ", SIGN (inex)); mpfr_dump (y); printf (" expected flags = %u, got %u\n", expected_flags, flags); if (stop) exit (1); err = 1; } } } mpfr_neg (x, x, MPFR_RNDN); spm = - spm; } mpfr_clears (x, y, z, (mpfr_ptr) 0); mpfr_set_emax (saved_emax); return err; }
static void underflow (mpfr_exp_t e) { mpfr_t x, y, z1, z2; mpfr_exp_t emin; int i, k; int prec; int rnd; int div; int inex1, inex2; unsigned int flags1, flags2; /* Test mul_2si(x, e - k), div_2si(x, k - e) and div_2ui(x, k - e) * with emin = e, x = 1 + i/16, i in { -1, 0, 1 }, and k = 1 to 4, * by comparing the result with the one of a simple division. */ emin = mpfr_get_emin (); set_emin (e); mpfr_inits2 (8, x, y, (mpfr_ptr) 0); for (i = 15; i <= 17; i++) { inex1 = mpfr_set_ui_2exp (x, i, -4, MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (prec = 6; prec >= 3; prec -= 3) { mpfr_inits2 (prec, z1, z2, (mpfr_ptr) 0); RND_LOOP (rnd) for (k = 1; k <= 4; k++) { /* The following one is assumed to be correct. */ inex1 = mpfr_mul_2si (y, x, e, MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); inex1 = mpfr_set_ui (z1, 1 << k, MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); mpfr_clear_flags (); /* Do not use mpfr_div_ui to avoid the optimization by mpfr_div_2si. */ inex1 = mpfr_div (z1, y, z1, (mpfr_rnd_t) rnd); flags1 = __gmpfr_flags; for (div = 0; div <= 2; div++) { mpfr_clear_flags (); inex2 = div == 0 ? mpfr_mul_2si (z2, x, e - k, (mpfr_rnd_t) rnd) : div == 1 ? mpfr_div_2si (z2, x, k - e, (mpfr_rnd_t) rnd) : mpfr_div_2ui (z2, x, k - e, (mpfr_rnd_t) rnd); flags2 = __gmpfr_flags; if (flags1 == flags2 && SAME_SIGN (inex1, inex2) && mpfr_equal_p (z1, z2)) continue; printf ("Error in underflow("); if (e == MPFR_EMIN_MIN) printf ("MPFR_EMIN_MIN"); else if (e == emin) printf ("default emin"); else printf ("%ld", e); printf (") with mpfr_%s,\nx = %d/16, prec = %d, k = %d, " "%s\n", div == 0 ? "mul_2si" : div == 1 ? "div_2si" : "div_2ui", i, prec, k, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); printf ("Expected "); 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); exit (1); } /* div */ } /* k */ mpfr_clears (z1, z2, (mpfr_ptr) 0); } /* prec */ } /* i */ mpfr_clears (x, y, (mpfr_ptr) 0); set_emin (emin); }
/* With N = 2 * GMP_NUMB_BITS: i * 2^N + j + k * 2^(-1) + f1 * 2^(-N) + f2 * 2^(-N), with i = -1 or 1, j = 0 or i, -1 <= k <= 1, -1 <= f1 <= 1, -1 <= f2 <= 1 ulp(exact sum) = 2^0. */ static void check2 (void) { mpfr_t sum1, sum2, s1, s2, s3, s4, t[5]; mpfr_ptr p[5]; int i, j, k, f1, f2, prec, r, inex1, inex2; #define N (2 * GMP_NUMB_BITS) mpfr_init2 (sum1, N+1); mpfr_init2 (sum2, N+1); mpfr_init2 (s1, N+1); mpfr_init2 (s2, N+2); mpfr_init2 (s3, 2*N+1); mpfr_init2 (s4, 2*N+1); for (i = 0; i < 5; i++) { mpfr_init2 (t[i], 2); p[i] = t[i]; } for (i = -1; i <= 1; i += 2) { mpfr_set_si_2exp (t[0], i, N, MPFR_RNDN); for (j = 0; j != 2*i; j += i) { mpfr_set_si (t[1], j, MPFR_RNDN); inex1 = mpfr_add (s1, t[0], t[1], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (k = -1; k <= 1; k++) { mpfr_set_si_2exp (t[2], k, -1, MPFR_RNDN); inex1 = mpfr_add (s2, s1, t[2], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (f1 = -1; f1 <= 1; f1++) { mpfr_set_si_2exp (t[3], f1, -N, MPFR_RNDN); inex1 = mpfr_add (s3, s2, t[3], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (f2 = -1; f2 <= 1; f2++) { mpfr_set_si_2exp (t[4], f2, -N, MPFR_RNDN); inex1 = mpfr_add (s4, s3, t[4], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); prec = mpfr_get_exp (s4); mpfr_set_prec (sum1, prec); mpfr_set_prec (sum2, prec); RND_LOOP (r) { inex1 = mpfr_set (sum1, s4, (mpfr_rnd_t) r); inex2 = mpfr_sum (sum2, p, 5, (mpfr_rnd_t) r); MPFR_ASSERTN (mpfr_check (sum1)); MPFR_ASSERTN (mpfr_check (sum2)); if (!(mpfr_equal_p (sum1, sum2) && SAME_SIGN (inex1, inex2))) { printf ("Error in check2 on %s, prec = %d, " "i = %d, j = %d, k = %d, f1 = %d, " "f2 = %d\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), prec, i, j, k, f1, f2); 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 < 5; i++) mpfr_clear (t[i]); mpfr_clears (sum1, sum2, s1, s2, s3, s4, (mpfr_ptr) 0); }
static void test_generic (mpfr_prec_t p0, mpfr_prec_t p1, unsigned int nmax) { mpfr_prec_t prec, xprec, yprec; mpfr_t x, y, z, t, w; #if defined(TWO_ARGS_ALL) mpfr_t u; #endif #if defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) double d; #endif #if defined(ULONG_ARG1) || defined(ULONG_ARG2) unsigned long i; #endif mpfr_rnd_t rnd; int inexact, compare, compare2; unsigned int n; unsigned long ctrt = 0, ctrn = 0; int test_of = 1, test_uf = 1; mpfr_exp_t old_emin, old_emax; old_emin = mpfr_get_emin (); old_emax = mpfr_get_emax (); mpfr_inits2 (MPFR_PREC_MIN, x, y, z, t, w, (mpfr_ptr) 0); #if defined(TWO_ARGS_ALL) mpfr_init2 (u, MPFR_PREC_MIN); #endif /* generic test */ for (prec = p0; prec <= p1; prec++) { mpfr_set_prec (z, prec); mpfr_set_prec (t, prec); yprec = prec + 10; mpfr_set_prec (y, yprec); mpfr_set_prec (w, yprec); /* Note: in precision p1, we test 4 special cases. */ for (n = 0; n < (prec == p1 ? nmax + 4 : nmax); n++) { int infinite_input = 0; unsigned int flags; mpfr_exp_t oemin, oemax; xprec = prec; if (randlimb () & 1) { xprec *= (double) randlimb () / MP_LIMB_T_MAX; if (xprec < MPFR_PREC_MIN) xprec = MPFR_PREC_MIN; } mpfr_set_prec (x, xprec); #if defined(TWO_ARGS) mpfr_set_prec (u, xprec); #elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) mpfr_set_prec (u, IEEE_DBL_MANT_DIG); #elif defined(ULONG_ARG1) || defined(ULONG_ARG2) mpfr_set_prec (u, sizeof (unsigned long) * CHAR_BIT); #endif if (n > 3 || prec < p1) { #if defined(RAND_FUNCTION) RAND_FUNCTION (x); #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) RAND_FUNCTION (u); #endif #else /* ! defined(RAND_FUNCTION) */ tests_default_random (x, TEST_RANDOM_POS, TEST_RANDOM_EMIN, TEST_RANDOM_EMAX, TEST_RANDOM_ALWAYS_SCALE); #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) tests_default_random (u, TEST_RANDOM_POS2, TEST_RANDOM_EMIN, TEST_RANDOM_EMAX, TEST_RANDOM_ALWAYS_SCALE); #endif #endif /* ! defined(RAND_FUNCTION) */ } else { /* Special cases tested in precision p1 if n <= 3. They are useful really in the extended exponent range. */ #if (defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)) && defined(MPFR_ERRDIVZERO) goto next_n; #endif set_emin (MPFR_EMIN_MIN); set_emax (MPFR_EMAX_MAX); if (n <= 1) { mpfr_set_si (x, n == 0 ? 1 : -1, MPFR_RNDN); mpfr_set_exp (x, mpfr_get_emin ()); #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) mpfr_set_si (u, randlimb () % 2 == 0 ? 1 : -1, MPFR_RNDN); mpfr_set_exp (u, mpfr_get_emin ()); #endif } else /* 2 <= n <= 3 */ { if (getenv ("MPFR_CHECK_MAX") == NULL) goto next_n; mpfr_set_si (x, n == 0 ? 1 : -1, MPFR_RNDN); mpfr_setmax (x, REDUCE_EMAX); #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) mpfr_set_si (u, randlimb () % 2 == 0 ? 1 : -1, MPFR_RNDN); mpfr_setmax (u, mpfr_get_emax ()); #endif } } #if defined(ULONG_ARG1) || defined(ULONG_ARG2) i = randlimb (); inexact = mpfr_set_ui (u, i, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); #endif /* Exponent range for the test. */ oemin = mpfr_get_emin (); oemax = mpfr_get_emax (); rnd = RND_RAND (); mpfr_clear_flags (); #ifdef DEBUG_TGENERIC TGENERIC_INFO (TEST_FUNCTION, MPFR_PREC (y)); #endif #if defined(TWO_ARGS) compare = TEST_FUNCTION (y, x, u, rnd); #elif defined(DOUBLE_ARG1) d = mpfr_get_d (u, rnd); compare = TEST_FUNCTION (y, d, x, rnd); /* d can be infinite due to overflow in mpfr_get_d */ infinite_input |= DOUBLE_ISINF (d); #elif defined(DOUBLE_ARG2) d = mpfr_get_d (u, rnd); compare = TEST_FUNCTION (y, x, d, rnd); /* d can be infinite due to overflow in mpfr_get_d */ infinite_input |= DOUBLE_ISINF (d); #elif defined(ULONG_ARG1) compare = TEST_FUNCTION (y, i, x, rnd); #elif defined(ULONG_ARG2) compare = TEST_FUNCTION (y, x, i, rnd); #else compare = TEST_FUNCTION (y, x, rnd); #endif flags = __gmpfr_flags; if (mpfr_get_emin () != oemin || mpfr_get_emax () != oemax) { printf ("tgeneric: the exponent range has been modified" " by the tested function!\n"); exit (1); } TGENERIC_CHECK ("bad inexact flag", (compare != 0) ^ (mpfr_inexflag_p () == 0)); ctrt++; /* Tests in a reduced exponent range. */ { unsigned int oldflags = flags; mpfr_exp_t e, emin, emax; /* Determine the smallest exponent range containing the exponents of the mpfr_t inputs (x, and u if TWO_ARGS) and output (y). */ emin = MPFR_EMAX_MAX; emax = MPFR_EMIN_MIN; if (MPFR_IS_PURE_FP (x)) { e = MPFR_GET_EXP (x); if (e < emin) emin = e; if (e > emax) emax = e; } #if defined(TWO_ARGS) if (MPFR_IS_PURE_FP (u)) { e = MPFR_GET_EXP (u); if (e < emin) emin = e; if (e > emax) emax = e; } #endif if (MPFR_IS_PURE_FP (y)) { e = MPFR_GET_EXP (y); if (test_of && e - 1 >= emax) { unsigned int ex_flags; mpfr_set_emax (e - 1); mpfr_clear_flags (); #if defined(TWO_ARGS) inexact = TEST_FUNCTION (w, x, u, rnd); #elif defined(DOUBLE_ARG1) inexact = TEST_FUNCTION (w, d, x, rnd); #elif defined(DOUBLE_ARG2) inexact = TEST_FUNCTION (w, x, d, rnd); #elif defined(ULONG_ARG1) inexact = TEST_FUNCTION (w, i, x, rnd); #elif defined(ULONG_ARG2) inexact = TEST_FUNCTION (w, x, i, rnd); #else inexact = TEST_FUNCTION (w, x, rnd); #endif flags = __gmpfr_flags; mpfr_set_emax (oemax); ex_flags = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT; if (flags != ex_flags) { printf ("tgeneric: error for " MAKE_STR(TEST_FUNCTION) ", reduced exponent range [%" MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d] (overflow test) on:\n", (mpfr_eexp_t) oemin, (mpfr_eexp_t) e - 1); printf ("x = "); mpfr_dump (x); #if defined(TWO_ARGS_ALL) printf ("u = "); mpfr_dump (u); #endif printf ("yprec = %u, rnd_mode = %s\n", (unsigned int) yprec, mpfr_print_rnd_mode (rnd)); printf ("Expected flags ="); flags_out (ex_flags); printf (" got flags ="); flags_out (flags); printf ("inex = %d, w = ", inexact); mpfr_dump (w); exit (1); } test_of = 0; /* Overflow is tested only once. */ } if (test_uf && e + 1 <= emin) { unsigned int ex_flags; mpfr_set_emin (e + 1); mpfr_clear_flags (); #if defined(TWO_ARGS) inexact = TEST_FUNCTION (w, x, u, rnd); #elif defined(DOUBLE_ARG1) inexact = TEST_FUNCTION (w, d, x, rnd); #elif defined(DOUBLE_ARG2) inexact = TEST_FUNCTION (w, x, d, rnd); #elif defined(ULONG_ARG1) inexact = TEST_FUNCTION (w, i, x, rnd); #elif defined(ULONG_ARG2) inexact = TEST_FUNCTION (w, x, i, rnd); #else inexact = TEST_FUNCTION (w, x, rnd); #endif flags = __gmpfr_flags; mpfr_set_emin (oemin); ex_flags = MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT; if (flags != ex_flags) { printf ("tgeneric: error for " MAKE_STR(TEST_FUNCTION) ", reduced exponent range [%" MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d] (underflow test) on:\n", (mpfr_eexp_t) e + 1, (mpfr_eexp_t) oemax); printf ("x = "); mpfr_dump (x); #if defined(TWO_ARGS_ALL) printf ("u = "); mpfr_dump (u); #endif printf ("yprec = %u, rnd_mode = %s\n", (unsigned int) yprec, mpfr_print_rnd_mode (rnd)); printf ("Expected flags ="); flags_out (ex_flags); printf (" got flags ="); flags_out (flags); printf ("inex = %d, w = ", inexact); mpfr_dump (w); exit (1); } test_uf = 0; /* Underflow is tested only once. */ } if (e < emin) emin = e; if (e > emax) emax = e; } if (emin > emax) emin = emax; /* case where all values are singular */ /* Consistency test in a reduced exponent range. Doing it for the first 10 samples and for prec == p1 (which has some special cases) should be sufficient. */ if (ctrt <= 10 || prec == p1) { mpfr_set_emin (emin); mpfr_set_emax (emax); #ifdef DEBUG_TGENERIC /* Useful information in case of assertion failure. */ printf ("tgeneric: reduced exponent range [%" MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d]\n", (mpfr_eexp_t) emin, (mpfr_eexp_t) emax); #endif mpfr_clear_flags (); #if defined(TWO_ARGS) inexact = TEST_FUNCTION (w, x, u, rnd); #elif defined(DOUBLE_ARG1) inexact = TEST_FUNCTION (w, d, x, rnd); #elif defined(DOUBLE_ARG2) inexact = TEST_FUNCTION (w, x, d, rnd); #elif defined(ULONG_ARG1) inexact = TEST_FUNCTION (w, i, x, rnd); #elif defined(ULONG_ARG2) inexact = TEST_FUNCTION (w, x, i, rnd); #else inexact = TEST_FUNCTION (w, x, rnd); #endif flags = __gmpfr_flags; mpfr_set_emin (oemin); mpfr_set_emax (oemax); if (! (SAME_VAL (w, y) && SAME_SIGN (inexact, compare) && flags == oldflags)) { printf ("tgeneric: error for " MAKE_STR(TEST_FUNCTION) ", reduced exponent range [%" MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d] on:\n", (mpfr_eexp_t) emin, (mpfr_eexp_t) emax); printf ("x = "); mpfr_dump (x); #if defined(TWO_ARGS_ALL) printf ("u = "); mpfr_dump (u); #endif printf ("yprec = %u, rnd_mode = %s\n", (unsigned int) yprec, mpfr_print_rnd_mode (rnd)); printf ("Expected:\n y = "); mpfr_dump (y); printf (" inex = %d, flags =", compare); flags_out (oldflags); printf ("Got:\n w = "); mpfr_dump (w); printf (" inex = %d, flags =", inexact); flags_out (flags); exit (1); } } __gmpfr_flags = oldflags; /* restore the flags */ } if (MPFR_IS_SINGULAR (y)) { if (MPFR_IS_NAN (y) || mpfr_nanflag_p ()) TGENERIC_CHECK ("bad NaN flag", MPFR_IS_NAN (y) && mpfr_nanflag_p ()); else if (MPFR_IS_INF (y)) { TGENERIC_CHECK ("bad overflow flag", (compare != 0) ^ (mpfr_overflow_p () == 0)); TGENERIC_CHECK ("bad divide-by-zero flag", (compare == 0 && !infinite_input) ^ (mpfr_divby0_p () == 0)); } else if (MPFR_IS_ZERO (y)) TGENERIC_CHECK ("bad underflow flag", (compare != 0) ^ (mpfr_underflow_p () == 0)); } else if (mpfr_divby0_p ()) { TGENERIC_CHECK ("both overflow and divide-by-zero", ! mpfr_overflow_p ()); TGENERIC_CHECK ("both underflow and divide-by-zero", ! mpfr_underflow_p ()); TGENERIC_CHECK ("bad compare value (divide-by-zero)", compare == 0); } else if (mpfr_overflow_p ()) { TGENERIC_CHECK ("both underflow and overflow", ! mpfr_underflow_p ()); TGENERIC_CHECK ("bad compare value (overflow)", compare != 0); mpfr_nexttoinf (y); TGENERIC_CHECK ("should have been max MPFR number (overflow)", MPFR_IS_INF (y)); } else if (mpfr_underflow_p ()) { TGENERIC_CHECK ("bad compare value (underflow)", compare != 0); mpfr_nexttozero (y); TGENERIC_CHECK ("should have been min MPFR number (underflow)", MPFR_IS_ZERO (y)); } else if (mpfr_can_round (y, yprec, rnd, rnd, prec)) { ctrn++; mpfr_set (t, y, rnd); /* Risk of failures are known when some flags are already set before the function call. Do not set the erange flag, as it will remain set after the function call and no checks are performed in such a case (see the mpfr_erangeflag_p test below). */ if (randlimb () & 1) __gmpfr_flags = MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE; #ifdef DEBUG_TGENERIC TGENERIC_INFO (TEST_FUNCTION, MPFR_PREC (z)); #endif /* Let's increase the precision of the inputs in a random way. In most cases, this doesn't make any difference, but for the mpfr_fmod bug fixed in r6230, this triggers the bug. */ mpfr_prec_round (x, mpfr_get_prec (x) + (randlimb () & 15), MPFR_RNDN); #if defined(TWO_ARGS) mpfr_prec_round (u, mpfr_get_prec (u) + (randlimb () & 15), MPFR_RNDN); inexact = TEST_FUNCTION (z, x, u, rnd); #elif defined(DOUBLE_ARG1) inexact = TEST_FUNCTION (z, d, x, rnd); #elif defined(DOUBLE_ARG2) inexact = TEST_FUNCTION (z, x, d, rnd); #elif defined(ULONG_ARG1) inexact = TEST_FUNCTION (z, i, x, rnd); #elif defined(ULONG_ARG2) inexact = TEST_FUNCTION (z, x, i, rnd); #else inexact = TEST_FUNCTION (z, x, rnd); #endif if (mpfr_erangeflag_p ()) goto next_n; if (! mpfr_equal_p (t, z)) { printf ("tgeneric: results differ for " MAKE_STR(TEST_FUNCTION) " on\n x = "); mpfr_dump (x); #if defined(TWO_ARGS_ALL) printf (" u = "); mpfr_dump (u); #endif printf (" prec = %u, rnd_mode = %s\n", (unsigned int) prec, mpfr_print_rnd_mode (rnd)); printf ("Got "); mpfr_dump (z); printf ("Expected "); mpfr_dump (t); printf ("Approx "); mpfr_dump (y); exit (1); } compare2 = mpfr_cmp (t, y); /* if rounding to nearest, cannot know the sign of t - f(x) because of composed rounding: y = o(f(x)) and t = o(y) */ if (compare * compare2 >= 0) compare = compare + compare2; else compare = inexact; /* cannot determine sign(t-f(x)) */ if (! SAME_SIGN (inexact, compare)) { printf ("Wrong inexact flag for rnd=%s: expected %d, got %d" "\n", mpfr_print_rnd_mode (rnd), compare, inexact); printf ("x = "); mpfr_dump (x); #if defined(TWO_ARGS_ALL) printf ("u = "); mpfr_dump (u); #endif printf ("y = "); mpfr_dump (y); printf ("t = "); mpfr_dump (t); exit (1); } } else if (getenv ("MPFR_SUSPICIOUS_OVERFLOW") != NULL) { /* For developers only! */ MPFR_ASSERTN (MPFR_IS_PURE_FP (y)); mpfr_nexttoinf (y); if (MPFR_IS_INF (y) && MPFR_IS_LIKE_RNDZ (rnd, MPFR_IS_NEG (y)) && !mpfr_overflow_p () && TGENERIC_SO_TEST) { printf ("Possible bug! |y| is the maximum finite number " "and has been obtained when\nrounding toward zero" " (%s). Thus there is a very probable overflow,\n" "but the overflow flag is not set!\n", mpfr_print_rnd_mode (rnd)); printf ("x = "); mpfr_dump (x); #if defined(TWO_ARGS_ALL) printf ("u = "); mpfr_dump (u); #endif exit (1); } } next_n: /* In case the exponent range has been changed by tests_default_random() or for special values... */ mpfr_set_emin (old_emin); mpfr_set_emax (old_emax); } } #ifndef TGENERIC_NOWARNING if (3 * ctrn < 2 * ctrt) printf ("Warning! Too few normal cases in generic tests (%lu / %lu)\n", ctrn, ctrt); #endif mpfr_clears (x, y, z, t, w, (mpfr_ptr) 0); #if defined(TWO_ARGS_ALL) mpfr_clear (u); #endif }
static int mpfr_all_div (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t r) { mpfr_t a2; unsigned int oldflags, newflags; int inex, inex2; oldflags = __gmpfr_flags; inex = mpfr_div (a, b, c, r); if (a == b || a == c) return inex; newflags = __gmpfr_flags; mpfr_init2 (a2, MPFR_PREC (a)); if (mpfr_integer_p (b) && ! (MPFR_IS_ZERO (b) && MPFR_IS_NEG (b))) { /* b is an integer, but not -0 (-0 is rejected as it becomes +0 when converted to an integer). */ if (mpfr_fits_ulong_p (b, MPFR_RNDA)) { __gmpfr_flags = oldflags; inex2 = mpfr_ui_div (a2, mpfr_get_ui (b, MPFR_RNDN), c, r); MPFR_ASSERTN (SAME_SIGN (inex2, inex)); MPFR_ASSERTN (__gmpfr_flags == newflags); check_equal (a, a2, "mpfr_ui_div", b, c, r); } if (mpfr_fits_slong_p (b, MPFR_RNDA)) { __gmpfr_flags = oldflags; inex2 = mpfr_si_div (a2, mpfr_get_si (b, MPFR_RNDN), c, r); MPFR_ASSERTN (SAME_SIGN (inex2, inex)); MPFR_ASSERTN (__gmpfr_flags == newflags); check_equal (a, a2, "mpfr_si_div", b, c, r); } } if (mpfr_integer_p (c) && ! (MPFR_IS_ZERO (c) && MPFR_IS_NEG (c))) { /* c is an integer, but not -0 (-0 is rejected as it becomes +0 when converted to an integer). */ if (mpfr_fits_ulong_p (c, MPFR_RNDA)) { __gmpfr_flags = oldflags; inex2 = mpfr_div_ui (a2, b, mpfr_get_ui (c, MPFR_RNDN), r); MPFR_ASSERTN (SAME_SIGN (inex2, inex)); MPFR_ASSERTN (__gmpfr_flags == newflags); check_equal (a, a2, "mpfr_div_ui", b, c, r); } if (mpfr_fits_slong_p (c, MPFR_RNDA)) { __gmpfr_flags = oldflags; inex2 = mpfr_div_si (a2, b, mpfr_get_si (c, MPFR_RNDN), r); MPFR_ASSERTN (SAME_SIGN (inex2, inex)); MPFR_ASSERTN (__gmpfr_flags == newflags); check_equal (a, a2, "mpfr_div_si", b, c, r); } } mpfr_clear (a2); return inex; }
/** * Brent's method is a root-finding algorithm which combines root * bracketing, interval bisection, and inverse quadratic interpolation. * It is sometimes known as the van Wijngaarden-Deker-Brent method. * * Using the algorithm from Numerical Recipes in FORTRAN. * * @see http://www.library.cornell.edu/nr/cbookfpdf.html */ int RootFinder::brents_method(double x1, double x2, double* root) { double a,b,c; double r,s; double p,q; double fa,fb,fc; double tol,m; bool ac_equal; double e,d; d = x2 - x1; e = d; a = x1; b = x2; c = b; fa = f(a); fb = f(b); fc = f(c); if (SAME_SIGN(fa, fb)) return false; uint32_t i = 3; while(i++ < MAX_ITER) { ac_equal = false; if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) { ac_equal = true; c = a; fc = fa; d = b - a; e = b - a; } if (fabs(fc) < fabs(fb)) { ac_equal = true; a = b; b = c; c = a; fa = fb; fb = fc; fc = fa; } //tol = 0.5 * DBL_EPSILON * fabs (b) + 0.5 * tolerance; tol = 0.5 * DBL_EPSILON * fabs (b); m = 0.5 * (c - b); if (fabs(fb) < tolerance) { *root = b; return i; } /* if (fabs(m) < tol) { *root = b; return i; } */ if (fabs(e) < tol || fabs(fa) <= fabs(fb)) { // Using bisection d = m; e = m; } else { // Use inverse cubic interpolation s = fb / fa; if (ac_equal) { p = 2 * m * s; q = 1 - s; } else { q = fa / fb; r = fb / fc; p = s * (2 * m * q * (q - r) - (b - a) * (r - 1)); q = (q - 1) * (r - 1) * (s - 1); } if (p > 0) { q = -q; } else { p = -p; } if (2 * p < MIN(3 * m * q - fabs(tol * q), fabs (e * q))) { e = d; d = p / q; } else { // interpolation failed, fall back to bisection d = m; e = m; } } a = b; fa = fb; if (fabs (d) > tol) { b += d; } else { //b += (m > 0 ? +tol : -tol); b += copysign(tol,m); } fb = f(b); } return false; }
/* t[i] = (2^17 - 1) * 2^(17*(i-8)) for 0 <= i <= 16. * t[17] = 2^(17*9+1) * j for -4 <= j <= 4. * t[18] = 2^(-1) * k for -1 <= k <= 1. * t[19] = 2^(-17*8) * m for -3 <= m <= 3. * prec = MPFR_PREC_MIN and 17*9+4 */ static void check3 (void) { mpfr_t sum1, sum2, s1, s2, s3, s4, t[20]; mpfr_ptr p[20]; mpfr_flags_t flags1, flags2; int i, s, j, k, m, q, r, inex1, inex2; int prec[2] = { MPFR_PREC_MIN, 17*9+4 }; mpfr_init2 (s1, 17*17); mpfr_init2 (s2, 17*17+4); mpfr_init2 (s3, 17*17+4); mpfr_init2 (s4, 17*17+5); mpfr_set_ui (s1, 0, MPFR_RNDN); for (i = 0; i < 20; i++) { mpfr_init2 (t[i], 20); p[i] = t[i]; if (i < 17) { mpfr_set_ui_2exp (t[i], 0x1ffff, 17*(i-8), MPFR_RNDN); inex1 = mpfr_add (s1, s1, t[i], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); } } for (s = 1; s >= -1; s -= 2) { for (j = -4; j <= 4; j++) { mpfr_set_si_2exp (t[17], j, 17*9+1, MPFR_RNDN); inex1 = mpfr_add (s2, s1, t[17], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (k = -1; k <= 1; k++) { mpfr_set_si_2exp (t[18], k, -1, MPFR_RNDN); inex1 = mpfr_add (s3, s2, t[18], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (m = -3; m <= 3; m++) { mpfr_set_si_2exp (t[19], m, -17*8, MPFR_RNDN); inex1 = mpfr_add (s4, s3, t[19], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (q = 0; q < 2; q++) { mpfr_inits2 (prec[q], sum1, sum2, (mpfr_ptr) 0); RND_LOOP (r) { mpfr_clear_flags (); inex1 = mpfr_set (sum1, s4, (mpfr_rnd_t) r); flags1 = __gmpfr_flags; mpfr_clear_flags (); inex2 = mpfr_sum (sum2, p, 20, (mpfr_rnd_t) r); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_check (sum1)); MPFR_ASSERTN (mpfr_check (sum2)); if (!(mpfr_equal_p (sum1, sum2) && SAME_SIGN (inex1, inex2) && flags1 == flags2)) { printf ("Error in check3 on %s, " "s = %d, j = %d, k = %d, m = %d\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), s, j, k, m); printf ("Expected "); mpfr_dump (sum1); printf ("with inex = %d and flags =", inex1); flags_out (flags1); printf ("Got "); mpfr_dump (sum2); printf ("with inex = %d and flags =", inex2); flags_out (flags2); exit (1); } } mpfr_clears (sum1, sum2, (mpfr_ptr) 0); } /* q */ } /* m */ } /* k */ } /* j */ for (i = 0; i < 17; i++) mpfr_neg (t[i], t[i], MPFR_RNDN); mpfr_neg (s1, s1, MPFR_RNDN); } /* s */ for (i = 0; i < 20; i++) mpfr_clear (t[i]); mpfr_clears (s1, s2, s3, s4, (mpfr_ptr) 0); }
/* Test of s * (q * 2^(n-1) - 2^k) + h + i * 2^(-2) + j * 2^(-2) * with h = -1 or 1, -1 <= i odd <= j <= 3, 2 <= q <= 3, s = -1 or 1, * prec n-k. * On a 64-bit machine: * MPFR_RNDN, tmd=2, rbit=0, sst=0, negative is checked with the inputs * -3*2^58, 2^5, -1, 2^(-2), 3*2^(-2) * MPFR_RNDN, tmd=2, rbit=0, sst=1, negative is checked with the inputs * -3*2^58, 2^5, -1, 3*2^(-2), 3*2^(-2) * * Note: This test detects an error in a result when "sq + 3" is replaced * by "sq + 2" (11th argument of the first sum_raw invocation) and the * corresponding assertion d >= 3 is removed, confirming that one cannot * decrease this proved error bound. */ static void check4 (void) { mpfr_t sum1, sum2, s1, s2, s3, s4, t[5]; mpfr_ptr p[5]; int h, i, j, k, n, q, r, s, prec, inex1, inex2; mpfr_inits2 (257, sum1, sum2, s1, s2, s3, s4, (mpfr_ptr) 0); for (i = 0; i < 5; i++) { mpfr_init2 (t[i], 2); p[i] = t[i]; } /* No GNU style for the many nested loops... */ for (k = 1; k <= 64; k++) { mpfr_set_si_2exp (t[0], -1, k, MPFR_RNDN); for (n = k + MPFR_PREC_MIN; n <= k + 65; n++) { prec = n - k; mpfr_set_prec (sum1, prec); mpfr_set_prec (sum2, prec); for (q = 2; q <= 3; q++) { mpfr_set_si_2exp (t[1], q, n - 1, MPFR_RNDN); inex1 = mpfr_add (s1, t[0], t[1], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (s = -1; s <= 1; s += 2) { mpfr_neg (t[0], t[0], MPFR_RNDN); mpfr_neg (t[1], t[1], MPFR_RNDN); mpfr_neg (s1, s1, MPFR_RNDN); for (h = -1; h <= 1; h += 2) { mpfr_set_si (t[2], h, MPFR_RNDN); inex1 = mpfr_add (s2, s1, t[2], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (i = -1; i <= 3; i += 2) { mpfr_set_si_2exp (t[3], i, -2, MPFR_RNDN); inex1 = mpfr_add (s3, s2, t[3], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); for (j = i; j <= 3; j++) { mpfr_set_si_2exp (t[4], j, -2, MPFR_RNDN); inex1 = mpfr_add (s4, s3, t[4], MPFR_RNDN); MPFR_ASSERTN (inex1 == 0); RND_LOOP (r) { inex1 = mpfr_set (sum1, s4, (mpfr_rnd_t) r); inex2 = mpfr_sum (sum2, p, 5, (mpfr_rnd_t) r); MPFR_ASSERTN (mpfr_check (sum1)); MPFR_ASSERTN (mpfr_check (sum2)); if (!(mpfr_equal_p (sum1, sum2) && SAME_SIGN (inex1, inex2))) { printf ("Error in check4 on %s, " "k = %d, n = %d (prec %d), " "q = %d, s = %d, h = %d, i = %d, j = %d\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), k, n, prec, q, s, h, i, j); 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 < 5; i++) mpfr_clear (t[i]); mpfr_clears (sum1, sum2, s1, s2, s3, s4, (mpfr_ptr) 0); }
int mpfr_erf (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode) { mpfr_t xf; mp_limb_t xf_limb[(53 - 1) / GMP_NUMB_BITS + 1]; int inex, large; MPFR_SAVE_EXPO_DECL (expo); MPFR_LOG_FUNC (("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode), ("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; } else if (MPFR_IS_INF (x)) /* erf(+inf) = +1, erf(-inf) = -1 */ return mpfr_set_si (y, MPFR_INT_SIGN (x), MPFR_RNDN); else /* erf(+0) = +0, erf(-0) = -0 */ { MPFR_ASSERTD (MPFR_IS_ZERO (x)); return mpfr_set (y, x, MPFR_RNDN); /* should keep the sign of x */ } } /* now x is neither NaN, Inf nor 0 */ /* first try expansion at x=0 when x is small, or asymptotic expansion where x is large */ MPFR_SAVE_EXPO_MARK (expo); /* around x=0, we have erf(x) = 2x/sqrt(Pi) (1 - x^2/3 + ...), with 1 - x^2/3 <= sqrt(Pi)*erf(x)/2/x <= 1 for x >= 0. This means that if x^2/3 < 2^(-PREC(y)-1) we can decide of the correct rounding, unless we have a worst-case for 2x/sqrt(Pi). */ if (MPFR_EXP(x) < - (mpfr_exp_t) (MPFR_PREC(y) / 2)) { /* we use 2x/sqrt(Pi) (1 - x^2/3) <= erf(x) <= 2x/sqrt(Pi) for x > 0 and 2x/sqrt(Pi) <= erf(x) <= 2x/sqrt(Pi) (1 - x^2/3) for x < 0. In both cases |2x/sqrt(Pi) (1 - x^2/3)| <= |erf(x)| <= |2x/sqrt(Pi)|. We will compute l and h such that l <= |2x/sqrt(Pi) (1 - x^2/3)| and |2x/sqrt(Pi)| <= h. If l and h round to the same value to precision PREC(y) and rounding rnd_mode, then we are done. */ mpfr_t l, h; /* lower and upper bounds for erf(x) */ int ok, inex2; mpfr_init2 (l, MPFR_PREC(y) + 17); mpfr_init2 (h, MPFR_PREC(y) + 17); /* first compute l */ mpfr_mul (l, x, x, MPFR_RNDU); mpfr_div_ui (l, l, 3, MPFR_RNDU); /* upper bound on x^2/3 */ mpfr_ui_sub (l, 1, l, MPFR_RNDZ); /* lower bound on 1 - x^2/3 */ mpfr_const_pi (h, MPFR_RNDU); /* upper bound of Pi */ mpfr_sqrt (h, h, MPFR_RNDU); /* upper bound on sqrt(Pi) */ mpfr_div (l, l, h, MPFR_RNDZ); /* lower bound on 1/sqrt(Pi) (1 - x^2/3) */ mpfr_mul_2ui (l, l, 1, MPFR_RNDZ); /* 2/sqrt(Pi) (1 - x^2/3) */ mpfr_mul (l, l, x, MPFR_RNDZ); /* |l| is a lower bound on |2x/sqrt(Pi) (1 - x^2/3)| */ /* now compute h */ mpfr_const_pi (h, MPFR_RNDD); /* lower bound on Pi */ mpfr_sqrt (h, h, MPFR_RNDD); /* lower bound on sqrt(Pi) */ mpfr_div_2ui (h, h, 1, MPFR_RNDD); /* lower bound on sqrt(Pi)/2 */ /* since sqrt(Pi)/2 < 1, the following should not underflow */ mpfr_div (h, x, h, MPFR_IS_POS(x) ? MPFR_RNDU : MPFR_RNDD); /* round l and h to precision PREC(y) */ inex = mpfr_prec_round (l, MPFR_PREC(y), rnd_mode); inex2 = mpfr_prec_round (h, MPFR_PREC(y), rnd_mode); /* Caution: we also need inex=inex2 (inex might be 0). */ ok = SAME_SIGN (inex, inex2) && mpfr_cmp (l, h) == 0; if (ok) mpfr_set (y, h, rnd_mode); mpfr_clear (l); mpfr_clear (h); if (ok) goto end; /* this test can still fail for small precision, for example for x=-0.100E-2 with a target precision of 3 bits, since the error term x^2/3 is not that small. */ } MPFR_TMP_INIT1(xf_limb, xf, 53); mpfr_div (xf, x, __gmpfr_const_log2_RNDU, MPFR_RNDZ); /* round to zero ensures we get a lower bound of |x/log(2)| */ mpfr_mul (xf, xf, x, MPFR_RNDZ); large = mpfr_cmp_ui (xf, MPFR_PREC (y) + 1) > 0; /* when x goes to infinity, we have erf(x) = 1 - 1/sqrt(Pi)/exp(x^2)/x + ... and |erf(x) - 1| <= exp(-x^2) is true for any x >= 0, thus if exp(-x^2) < 2^(-PREC(y)-1) the result is 1 or 1-epsilon. This rewrites as x^2/log(2) > p+1. */ if (MPFR_UNLIKELY (large)) /* |erf x| = 1 or 1- */ { mpfr_rnd_t rnd2 = MPFR_IS_POS (x) ? rnd_mode : MPFR_INVERT_RND(rnd_mode); if (rnd2 == MPFR_RNDN || rnd2 == MPFR_RNDU || rnd2 == MPFR_RNDA) { inex = MPFR_INT_SIGN (x); mpfr_set_si (y, inex, rnd2); } else /* round to zero */ { inex = -MPFR_INT_SIGN (x); mpfr_setmax (y, 0); /* warning: setmax keeps the old sign of y */ MPFR_SET_SAME_SIGN (y, x); } } else /* use Taylor */ { double xf2; /* FIXME: get rid of doubles/mpfr_get_d here */ xf2 = mpfr_get_d (x, MPFR_RNDN); xf2 = xf2 * xf2; /* xf2 ~ x^2 */ inex = mpfr_erf_0 (y, x, xf2, rnd_mode); } end: MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (y, inex, rnd_mode); }
static void check1 (void) { mpfr_t x; int i, j, k, s, old_inex, tiny, expj; mpfr_exp_t emin, emax; unsigned int expflags, flags; emin = mpfr_get_emin (); emax = mpfr_get_emax (); mpfr_set_default_prec (9); mpfr_set_emin (-10); mpfr_set_emax (10); mpfr_init (x); for (i = 0; i < numberof (tab); i++) for (s = 0; s <= (tab[i].rnd == MPFR_RNDN); s++) for (k = 0; k <= 1; k++) { mpfr_set_str (x, tab[i].in, 2, MPFR_RNDN); old_inex = tab[i].i; expj = tab[i].j; if (s) { mpfr_neg (x, x, MPFR_RNDN); old_inex = - old_inex; expj = - expj; } if (k && old_inex) old_inex = old_inex < 0 ? INT_MIN : INT_MAX; tiny = MPFR_GET_EXP (x) <= -3; mpfr_clear_flags (); j = mpfr_subnormalize (x, old_inex, tab[i].rnd); expflags = (tiny ? MPFR_FLAGS_UNDERFLOW : 0) | (expj ? MPFR_FLAGS_INEXACT : 0); flags = __gmpfr_flags; if (s) mpfr_neg (x, x, MPFR_RNDN); if (mpfr_cmp_str (x, tab[i].out, 2, MPFR_RNDN) != 0 || flags != expflags || ! SAME_SIGN (j, expj)) { const char *sgn = s ? "-" : ""; printf ("Error for i = %d (old_inex = %d), k = %d, x = %s%s\n" "Expected: %s%s\nGot: ", i, old_inex, k, sgn, tab[i].in, sgn, tab[i].out); if (s) mpfr_neg (x, x, MPFR_RNDN); mpfr_dump (x); printf ("Expected flags = %u, got %u\n", expflags, flags); printf ("Expected ternary value = %d, got %d\n", expj, j); exit (1); } } mpfr_clear (x); MPFR_ASSERTN (mpfr_get_emin () == -10); MPFR_ASSERTN (mpfr_get_emax () == 10); set_emin (emin); set_emax (emax); }
int main (int argc, char *argv[]) { mpfr_t x, y, z, s; mpfr_exp_t emin, emax; tests_start_mpfr (); emin = mpfr_get_emin (); emax = mpfr_get_emax (); bug20101018 (); mpfr_init (x); mpfr_init (s); mpfr_init (y); mpfr_init (z); /* check special cases */ mpfr_set_prec (x, 2); mpfr_set_prec (y, 2); mpfr_set_prec (z, 2); mpfr_set_prec (s, 2); mpfr_set_str (x, "-0.75", 10, MPFR_RNDN); mpfr_set_str (y, "0.5", 10, MPFR_RNDN); mpfr_set_str (z, "0.375", 10, MPFR_RNDN); mpfr_fma (s, x, y, z, MPFR_RNDU); /* result is 0 */ if (mpfr_cmp_ui (s, 0)) { printf ("Error: -0.75 * 0.5 + 0.375 should be equal to 0 for prec=2\n"); printf ("got instead "); mpfr_dump (s); exit (1); } mpfr_set_prec (x, 27); mpfr_set_prec (y, 27); mpfr_set_prec (z, 27); mpfr_set_prec (s, 27); mpfr_set_str_binary (x, "1.11111111111111111111111111e-1"); mpfr_set (y, x, MPFR_RNDN); mpfr_set_str_binary (z, "-1.00011110100011001011001001e-1"); if (mpfr_fma (s, x, y, z, MPFR_RNDN) >= 0) { printf ("Wrong inexact flag for x=y=1-2^(-27)\n"); exit (1); } mpfr_set_nan (x); mpfr_urandomb (y, RANDS); mpfr_urandomb (z, RANDS); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_nan_p (s)) { printf ("evaluation of function in x=NAN does not return NAN\n"); exit (1); } mpfr_set_nan (y); mpfr_urandomb (x, RANDS); mpfr_urandomb (z, RANDS); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_nan_p(s)) { printf ("evaluation of function in y=NAN does not return NAN\n"); exit (1); } mpfr_set_nan (z); mpfr_urandomb (y, RANDS); mpfr_urandomb (x, RANDS); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_nan_p (s)) { printf ("evaluation of function in z=NAN does not return NAN\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_set_inf (y, 1); mpfr_set_inf (z, 1); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0) { printf ("Error for (+inf) * (+inf) + (+inf)\n"); exit (1); } mpfr_set_inf (x, -1); mpfr_set_inf (y, -1); mpfr_set_inf (z, 1); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0) { printf ("Error for (-inf) * (-inf) + (+inf)\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_set_inf (y, -1); mpfr_set_inf (z, -1); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_inf_p (s) || mpfr_sgn (s) > 0) { printf ("Error for (+inf) * (-inf) + (-inf)\n"); exit (1); } mpfr_set_inf (x, -1); mpfr_set_inf (y, 1); mpfr_set_inf (z, -1); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_inf_p (s) || mpfr_sgn (s) > 0) { printf ("Error for (-inf) * (+inf) + (-inf)\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_set_ui (y, 0, MPFR_RNDN); mpfr_urandomb (z, RANDS); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_nan_p (s)) { printf ("evaluation of function in x=INF y=0 does not return NAN\n"); exit (1); } mpfr_set_inf (y, 1); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_urandomb (z, RANDS); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_nan_p (s)) { printf ("evaluation of function in x=0 y=INF does not return NAN\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_urandomb (y, RANDS); /* always positive */ mpfr_set_inf (z, -1); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_nan_p (s)) { printf ("evaluation of function in x=INF y>0 z=-INF does not return NAN\n"); exit (1); } mpfr_set_inf (y, 1); mpfr_urandomb (x, RANDS); mpfr_set_inf (z, -1); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_nan_p (s)) { printf ("evaluation of function in x>0 y=INF z=-INF does not return NAN\n"); exit (1); } mpfr_set_inf (x, 1); do mpfr_urandomb (y, RANDS); while (MPFR_IS_ZERO(y)); mpfr_urandomb (z, RANDS); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0) { printf ("evaluation of function in x=INF does not return INF\n"); exit (1); } mpfr_set_inf (y, 1); do mpfr_urandomb (x, RANDS); while (MPFR_IS_ZERO(x)); mpfr_urandomb (z, RANDS); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0) { printf ("evaluation of function at y=INF does not return INF\n"); exit (1); } mpfr_set_inf (z, 1); mpfr_urandomb (x, RANDS); mpfr_urandomb (y, RANDS); mpfr_fma (s, x, y, z, MPFR_RNDN); if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0) { printf ("evaluation of function in z=INF does not return INF\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_urandomb (y, RANDS); mpfr_urandomb (z, RANDS); mpfr_fma (s, x, y, z, MPFR_RNDN); if (! mpfr_equal_p (s, z)) { printf ("evaluation of function in x=0 does not return z\n"); exit (1); } mpfr_set_ui (y, 0, MPFR_RNDN); mpfr_urandomb (x, RANDS); mpfr_urandomb (z, RANDS); mpfr_fma (s, x, y, z, MPFR_RNDN); if (! mpfr_equal_p (s, z)) { printf ("evaluation of function in y=0 does not return z\n"); exit (1); } { mpfr_prec_t prec; mpfr_t t, slong; mpfr_rnd_t rnd; int inexact, compare; unsigned int n; mpfr_prec_t p0 = 2, p1 = 200; unsigned int N = 200; mpfr_init (t); mpfr_init (slong); /* generic test */ for (prec = p0; prec <= p1; prec++) { mpfr_set_prec (x, prec); mpfr_set_prec (y, prec); mpfr_set_prec (z, prec); mpfr_set_prec (s, prec); mpfr_set_prec (t, prec); for (n = 0; n < N; n++) { mpfr_urandomb (x, RANDS); mpfr_urandomb (y, RANDS); mpfr_urandomb (z, RANDS); if (randlimb () % 2) mpfr_neg (x, x, MPFR_RNDN); if (randlimb () % 2) mpfr_neg (y, y, MPFR_RNDN); if (randlimb () % 2) mpfr_neg (z, z, MPFR_RNDN); rnd = RND_RAND (); mpfr_set_prec (slong, 2 * prec); if (mpfr_mul (slong, x, y, rnd)) { printf ("x*y should be exact\n"); exit (1); } compare = mpfr_add (t, slong, z, rnd); inexact = mpfr_fma (s, x, y, z, rnd); if (! mpfr_equal_p (s, t)) { printf ("results differ for x="); mpfr_out_str (stdout, 2, prec, x, MPFR_RNDN); printf (" y="); mpfr_out_str (stdout, 2, prec, y, MPFR_RNDN); printf (" z="); mpfr_out_str (stdout, 2, prec, z, MPFR_RNDN); printf (" prec=%u rnd_mode=%s\n", (unsigned int) prec, mpfr_print_rnd_mode (rnd)); printf ("got "); mpfr_out_str (stdout, 2, prec, s, MPFR_RNDN); puts (""); printf ("expected "); mpfr_out_str (stdout, 2, prec, t, MPFR_RNDN); puts (""); printf ("approx "); mpfr_print_binary (slong); puts (""); exit (1); } if (! SAME_SIGN (inexact, compare)) { printf ("Wrong inexact flag for rnd=%s: expected %d, got %d\n", mpfr_print_rnd_mode (rnd), compare, inexact); printf (" x="); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); printf (" y="); mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); printf (" z="); mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN); printf (" s="); mpfr_out_str (stdout, 2, 0, s, MPFR_RNDN); printf ("\n"); exit (1); } } } mpfr_clear (t); mpfr_clear (slong); } mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); mpfr_clear (s); test_exact (); test_overflow1 (); test_overflow2 (); test_underflow1 (); test_underflow2 (); test_underflow3 (1); set_emin (MPFR_EMIN_MIN); set_emax (MPFR_EMAX_MAX); test_overflow1 (); test_overflow2 (); test_underflow1 (); test_underflow2 (); test_underflow3 (2); set_emin (emin); set_emax (emax); tests_end_mpfr (); return 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)); }
static void test_large_small (void) { mpfr_t x, y, z; int inexact, inex2, r; mpfr_init2 (x, 3); mpfr_init2 (y, 2); mpfr_init2 (z, 2); mpfr_set_ui_2exp (x, 1, mpfr_get_emax () / 2, MPFR_RNDN); mpfr_set_ui_2exp (y, 1, -1, MPFR_RNDN); inexact = mpfr_hypot (z, x, y, MPFR_RNDN); if (inexact >= 0 || mpfr_cmp (x, z)) { printf ("Error 1 in test_large_small%s\n", ext ? ", extended exponent range" : ""); exit (1); } mpfr_mul_ui (x, x, 5, MPFR_RNDN); inexact = mpfr_hypot (z, x, y, MPFR_RNDN); if (mpfr_cmp (x, z) >= 0) { printf ("Error 2 in test_large_small%s\n", ext ? ", extended exponent range" : ""); printf ("x = "); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); printf ("\n"); printf ("y = "); mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); printf ("\n"); printf ("z = "); mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN); printf (" (in precision 2) instead of\n "); mpfr_out_str (stdout, 2, 2, x, MPFR_RNDU); printf ("\n"); exit (1); } RND_LOOP(r) { mpfr_set_ui_2exp (x, 1, mpfr_get_emax () - 1, MPFR_RNDN); mpfr_set_ui_2exp (y, 1, mpfr_get_emin (), MPFR_RNDN); inexact = mpfr_hypot (z, x, y, (mpfr_rnd_t) r); inex2 = mpfr_add_ui (y, x, 1, (mpfr_rnd_t) r); if (! mpfr_equal_p (y, z) || ! SAME_SIGN (inexact, inex2)) { printf ("Error 3 in test_large_small, %s%s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), ext ? ", extended exponent range" : ""); printf ("Expected "); mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); printf (", inex = %d\n", inex2); printf ("Got "); mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); printf (", inex = %d\n", inexact); exit (1); } } mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); }
static void ternary_test (void) { int prec; int rnd; int inex, expected_inex; mpf_t x; mpfr_t y; mpf_init2 (x, 256); mpfr_init2 (y, 256); for (prec = 2; prec <= 256; prec++) { mpf_set_prec (x, prec); mpfr_set_prec (y, PREC (x) * GMP_NUMB_BITS + 1); /* y == 1 */ mpfr_set_ui_2exp (y, 1, prec, MPFR_RNDN); RND_LOOP (rnd) { inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd); if (inex != 0 || mpfr_cmp_f (y, x) !=0) { printf ("Error in mpfr_get_f (x, y, %s)\nx = ", mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); mpf_out_str (stdout, 2, 0, x); printf ("\ny = "); mpfr_dump (y); if (inex != 0) printf ("got ternary value = %+d, expected: 0\n", inex); exit (1); } } /* y == 1 + epsilon */ mpfr_nextbelow (y); RND_LOOP (rnd) { switch (rnd) { case MPFR_RNDU: case MPFR_RNDA: case MPFR_RNDN: expected_inex = +1; break; default : expected_inex = -1; } inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd); if (! SAME_SIGN (expected_inex, inex) || SAME_SIGN (expected_inex, mpfr_cmp_f (y, x))) { printf ("Error in mpfr_get_f (x, y, %s)\nx = ", mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); mpf_out_str (stdout, 2, 0, x); printf ("\ny = "); mpfr_dump (y); if (! SAME_SIGN (expected_inex, inex)) printf ("got ternary value = %+d, expected: %+d\n", inex, expected_inex); exit (1); } } /* y == positive random float */ mpfr_random2 (y, MPFR_LIMB_SIZE (y), 1024, RANDS); RND_LOOP (rnd) { inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd); if (! SAME_SIGN (inex, -mpfr_cmp_f (y, x))) { printf ("Error in mpfr_get_f (x, y, %s)\nx = ", mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); mpf_out_str (stdout, 2, 0, x); printf ("\ny = "); mpfr_dump (y); printf ("got ternary value = %+d, expected: %+d\n", inex, -mpfr_cmp_f (y, x)); exit (1); } } } mpf_clear (x); mpfr_clear (y); }
static void check_one (mpz_ptr z) { int inex, ex_inex, same; int sh, neg; mpfr_t f; mpz_t got, ex; mpfr_init2 (f, MAX (mpz_sizeinbase (z, 2), MPFR_PREC_MIN)); mpz_init (got); mpz_init (ex); for (sh = -2*GMP_NUMB_BITS ; sh < 2*GMP_NUMB_BITS ; sh++) { inex = mpfr_set_z (f, z, MPFR_RNDN); /* exact */ MPFR_ASSERTN (inex == 0); if (sh < 0) { mpz_tdiv_q_2exp (ex, z, -sh); inex = mpfr_div_2exp (f, f, -sh, MPFR_RNDN); } else { mpz_mul_2exp (ex, z, sh); inex = mpfr_mul_2exp (f, f, sh, MPFR_RNDN); } MPFR_ASSERTN (inex == 0); for (neg = 0; neg <= 1; neg++) { /* Test (-1)^neg * z * 2^sh */ int fi; mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE, MPFR_FLAGS_ALL }, ex_flags, gt_flags; for (fi = 0; fi < numberof (flags); fi++) { ex_inex = - mpfr_cmp_z (f, ex); ex_flags = __gmpfr_flags = flags[fi]; if (ex_inex != 0) ex_flags |= MPFR_FLAGS_INEXACT; inex = mpfr_get_z (got, f, MPFR_RNDZ); gt_flags = __gmpfr_flags; same = SAME_SIGN (inex, ex_inex); if (mpz_cmp (got, ex) != 0 || !same || gt_flags != ex_flags) { printf ("Error in check_one for sh=%d, fi=%d\n", sh, fi); printf (" f = "); mpfr_dump (f); printf ("expected "); mpz_dump (ex); printf (" got "); mpz_dump (got); printf ("Expected inex ~ %d, got %d (%s)\n", inex, ex_inex, same ? "OK" : "wrong"); printf ("Flags:\n"); printf (" in"); flags_out (gt_flags); printf ("expected"); flags_out (ex_flags); printf (" got"); flags_out (gt_flags); exit (1); } } mpz_neg (ex, ex); mpfr_neg (f, f, MPFR_RNDN); } } mpfr_clear (f); mpz_clear (got); mpz_clear (ex); }
int main (void) { mpf_t x; mpfr_t y, z; unsigned long i; mpfr_exp_t e; int inex; tests_start_mpfr (); mpfr_init (y); mpfr_init (z); mpf_init (x); i = 1; while (i) { mpfr_set_ui (y, i, MPFR_RNDN); if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, i)) { printf ("Error: mpfr_get_f(%lu) fails\n", i); exit (1); } if (i <= - (unsigned long) LONG_MIN) { long j = i < - (unsigned long) LONG_MIN ? - (long) i : LONG_MIN; mpfr_set_si (y, j, MPFR_RNDN); if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_si (x, j)) { printf ("Error: mpfr_get_f(-%lu) fails\n", i); exit (1); } } i *= 2; } /* same tests, but with a larger precision for y, which requires to round it */ mpfr_set_prec (y, 100); i = 1; while (i) { mpfr_set_ui (y, i, MPFR_RNDN); inex = mpfr_get_f (x, y, MPFR_RNDN); if (! SAME_SIGN (inex, - mpfr_cmp_f (y, x)) || mpf_cmp_ui (x, i)) { printf ("Error: mpfr_get_f(%lu) fails\n", i); exit (1); } mpfr_set_si (y, (signed long) -i, MPFR_RNDN); inex = mpfr_get_f (x, y, MPFR_RNDN); if (! SAME_SIGN (inex, - mpfr_cmp_f (y, x)) || mpf_cmp_si (x, (signed long) -i)) { printf ("Error: mpfr_get_f(-%lu) fails\n", i); exit (1); } i *= 2; } /* bug reported by Jim White */ for (e = 0; e <= 2 * GMP_NUMB_BITS; e++) { /* test with 2^(-e) */ mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_div_2exp (y, y, e, MPFR_RNDN); inex = mpfr_get_f (x, y, MPFR_RNDN); mpf_mul_2exp (x, x, e); if (inex != 0 || mpf_cmp_ui (x, 1) != 0) { printf ("Error: mpfr_get_f(x,y,MPFR_RNDN) fails\n"); printf ("y="); mpfr_dump (y); printf ("x="); mpf_div_2exp (x, x, e); mpf_out_str (stdout, 2, 0, x); exit (1); } /* test with 2^(e) */ mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_mul_2exp (y, y, e, MPFR_RNDN); inex = mpfr_get_f (x, y, MPFR_RNDN); mpf_div_2exp (x, x, e); if (inex != 0 || mpf_cmp_ui (x, 1) != 0) { printf ("Error: mpfr_get_f(x,y,MPFR_RNDN) fails\n"); printf ("y="); mpfr_dump (y); printf ("x="); mpf_mul_2exp (x, x, e); mpf_out_str (stdout, 2, 0, x); exit (1); } } /* Bug reported by Yury Lukach on 2006-04-05 */ mpfr_set_prec (y, 32); mpfr_set_prec (z, 32); mpf_set_prec (x, 32); mpfr_set_ui_2exp (y, 0xc1234567, -30, MPFR_RNDN); mpfr_get_f (x, y, MPFR_RNDN); inex = mpfr_set_f (z, x, MPFR_RNDN); if (inex != 0 || ! mpfr_equal_p (y, z)) { printf ("Error in mpfr_get_f:\n inex = %d, y = ", inex); mpfr_dump (z); printf ("Expected:\n inex = 0, y = "); mpfr_dump (y); exit (1); } mpfr_clear (y); mpfr_clear (z); mpf_clear (x); special_test (); prec_test (); ternary_test (); tests_end_mpfr (); return 0; }