/* expx is the value of exp(X) rounded toward -infinity */ static void check_worst_case (const char *Xs, const char *expxs) { mpfr_t x, y; mpfr_inits2 (53, x, y, (mpfr_ptr) 0); mpfr_set_str1(x, Xs); test_exp(y, x, MPFR_RNDD); if (mpfr_cmp_str1 (y, expxs)) { printf ("exp(x) rounded toward -infinity is wrong\n"); exit(1); } mpfr_set_str1(x, Xs); test_exp(x, x, MPFR_RNDU); mpfr_nexttoinf (y); if (mpfr_cmp(x,y)) { printf ("exp(x) rounded toward +infinity is wrong\n"); exit(1); } mpfr_clears (x, y, (mpfr_ptr) 0); }
static void check_overflow (void) { mpfr_t x, y; int inex, r; mpfr_inits2 (8, x, y, (mpfr_ptr) 0); mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_setmax (x, mpfr_get_emax ()); RND_LOOP(r) { mpfr_clear_overflow (); inex = mpfr_hypot (y, x, x, (mpfr_rnd_t) r); if (!mpfr_overflow_p ()) { printf ("No overflow in check_overflow for %s%s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), ext ? ", extended exponent range" : ""); exit (1); } MPFR_ASSERTN (MPFR_IS_POS (y)); if (r == MPFR_RNDZ || r == MPFR_RNDD) { MPFR_ASSERTN (inex < 0); MPFR_ASSERTN (!mpfr_inf_p (y)); mpfr_nexttoinf (y); } else { MPFR_ASSERTN (inex > 0); } MPFR_ASSERTN (mpfr_inf_p (y)); } mpfr_clears (x, y, (mpfr_ptr) 0); }
static void check_lowr (void) { mpfr_t x, y, z, z2, z3, tmp; int k, c, c2; mpfr_init2 (x, 1000); mpfr_init2 (y, 100); mpfr_init2 (tmp, 850); mpfr_init2 (z, 10); mpfr_init2 (z2, 10); mpfr_init2 (z3, 50); for (k = 1; k < KMAX; k++) { do { mpfr_urandomb (z, RANDS); } while (mpfr_cmp_ui (z, 0) == 0); do { mpfr_urandomb (tmp, RANDS); } while (mpfr_cmp_ui (tmp, 0) == 0); mpfr_mul (x, z, tmp, MPFR_RNDN); /* exact */ c = test_div (z2, x, tmp, MPFR_RNDN); if (c || mpfr_cmp (z2, z)) { printf ("Error in mpfr_div rnd=MPFR_RNDN\n"); printf ("got "); mpfr_print_binary(z2); puts (""); printf ("instead of "); mpfr_print_binary(z); puts (""); printf ("inex flag = %d, expected 0\n", c); exit (1); } } /* x has still precision 1000, z precision 10, and tmp prec 850 */ mpfr_set_prec (z2, 9); for (k = 1; k < KMAX; k++) { mpfr_urandomb (z, RANDS); do { mpfr_urandomb (tmp, RANDS); } while (mpfr_cmp_ui (tmp, 0) == 0); mpfr_mul (x, z, tmp, MPFR_RNDN); /* exact */ c = test_div (z2, x, tmp, MPFR_RNDN); /* since z2 has one less bit that z, either the division is exact if z is representable on 9 bits, or we have an even round case */ c2 = get_inexact (z2, x, tmp); if ((mpfr_cmp (z2, z) == 0 && c) || inex_cmp (c, c2)) { printf ("Error in mpfr_div rnd=MPFR_RNDN\n"); printf ("got "); mpfr_print_binary(z2); puts (""); printf ("instead of "); mpfr_print_binary(z); puts (""); printf ("inex flag = %d, expected %d\n", c, c2); exit (1); } else if (c == 2) { mpfr_nexttoinf (z); if (mpfr_cmp(z2, z)) { printf ("Error in mpfr_div [even rnd?] rnd=MPFR_RNDN\n"); printf ("Dividing "); printf ("got "); mpfr_print_binary(z2); puts (""); printf ("instead of "); mpfr_print_binary(z); puts (""); printf ("inex flag = %d\n", 1); exit (1); } } else if (c == -2) { mpfr_nexttozero (z); if (mpfr_cmp(z2, z)) { printf ("Error in mpfr_div [even rnd?] rnd=MPFR_RNDN\n"); printf ("Dividing "); printf ("got "); mpfr_print_binary(z2); puts (""); printf ("instead of "); mpfr_print_binary(z); puts (""); printf ("inex flag = %d\n", 1); exit (1); } } } mpfr_set_prec(x, 1000); mpfr_set_prec(y, 100); mpfr_set_prec(tmp, 850); mpfr_set_prec(z, 10); mpfr_set_prec(z2, 10); /* almost exact divisions */ for (k = 1; k < KMAX; k++) { do { mpfr_urandomb (z, RANDS); } while (mpfr_cmp_ui (z, 0) == 0); do { mpfr_urandomb (tmp, RANDS); } while (mpfr_cmp_ui (tmp, 0) == 0); mpfr_mul(x, z, tmp, MPFR_RNDN); mpfr_set(y, tmp, MPFR_RNDD); mpfr_nexttoinf (x); c = test_div(z2, x, y, MPFR_RNDD); test_div(z3, x, y, MPFR_RNDD); mpfr_set(z, z3, MPFR_RNDD); if (c != -1 || mpfr_cmp(z2, z)) { printf ("Error in mpfr_div rnd=MPFR_RNDD\n"); printf ("got "); mpfr_print_binary(z2); puts (""); printf ("instead of "); mpfr_print_binary(z); puts (""); printf ("inex flag = %d\n", c); exit (1); } mpfr_set (y, tmp, MPFR_RNDU); test_div (z3, x, y, MPFR_RNDU); mpfr_set (z, z3, MPFR_RNDU); c = test_div (z2, x, y, MPFR_RNDU); if (c != 1 || mpfr_cmp (z2, z)) { printf ("Error in mpfr_div rnd=MPFR_RNDU\n"); printf ("u="); mpfr_dump (x); printf ("v="); mpfr_dump (y); printf ("got "); mpfr_print_binary (z2); puts (""); printf ("instead of "); mpfr_print_binary (z); puts (""); printf ("inex flag = %d\n", c); exit (1); } } mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); mpfr_clear (z2); mpfr_clear (z3); mpfr_clear (tmp); }
/* The test_one argument is seen a boolean. If it is true and rnd is a rounding mode toward infinity, then the function is tested in only one rounding mode (the one provided in rnd) and the variable rndnext is not used (due to the break). If it is true and rnd is a rounding mode toward or away from zero, then the function is tested twice, first with the provided rounding mode and second with the rounding mode toward the corresponding infinity (determined by the sign of the result). If it is false, then the function is tested in the 5 rounding modes, and rnd must initially be MPFR_RNDZ; thus rndnext will be initialized in the first iteration. If the test_one argument is 2, then this means that y is exact, and the ternary value is checked. As examples of use, see the calls to test5rm from the data_check and bad_cases functions. */ static void test5rm (int (*fct) (FLIST), mpfr_srcptr x, mpfr_ptr y, mpfr_ptr z, mpfr_rnd_t rnd, int test_one, const char *name) { mpfr_prec_t yprec = MPFR_PREC (y); mpfr_rnd_t rndnext = MPFR_RND_MAX; /* means uninitialized */ MPFR_ASSERTN (test_one || rnd == MPFR_RNDZ); mpfr_set_prec (z, yprec); while (1) { int inex; MPFR_ASSERTN (rnd != MPFR_RND_MAX); inex = fct (z, x, rnd); if (! (mpfr_equal_p (y, z) || (mpfr_nan_p (y) && mpfr_nan_p (z)))) { printf ("Error for %s with xprec=%lu, yprec=%lu, rnd=%s\nx = ", name, (unsigned long) MPFR_PREC (x), (unsigned long) yprec, mpfr_print_rnd_mode (rnd)); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); printf ("\nexpected "); mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN); printf ("\ngot "); mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN); printf ("\n"); exit (1); } if (test_one == 2 && inex != 0) { printf ("Error for %s with xprec=%lu, yprec=%lu, rnd=%s\nx = ", name, (unsigned long) MPFR_PREC (x), (unsigned long) yprec, mpfr_print_rnd_mode (rnd)); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); printf ("\nexact case, but non-zero ternary value (%d)\n", inex); exit (1); } if (rnd == MPFR_RNDN) break; if (test_one) { if (rnd == MPFR_RNDU || rnd == MPFR_RNDD) break; if (MPFR_IS_NEG (y)) rnd = (rnd == MPFR_RNDA) ? MPFR_RNDD : MPFR_RNDU; else rnd = (rnd == MPFR_RNDA) ? MPFR_RNDU : MPFR_RNDD; } else if (rnd == MPFR_RNDZ) { rnd = MPFR_IS_NEG (y) ? MPFR_RNDU : MPFR_RNDD; rndnext = MPFR_RNDA; } else { rnd = rndnext; if (rnd == MPFR_RNDA) { mpfr_nexttoinf (y); rndnext = (MPFR_IS_NEG (y)) ? MPFR_RNDD : MPFR_RNDU; } else if (rndnext != MPFR_RNDN) rndnext = MPFR_RNDN; else { if (yprec == MPFR_PREC_MIN) break; mpfr_prec_round (y, --yprec, MPFR_RNDZ); mpfr_set_prec (z, yprec); } } } }
static void special (void) { mpfr_t x, y, z; int inexact; mpfr_prec_t p; mpfr_init (x); mpfr_init (y); mpfr_init (z); mpfr_set_prec (x, 64); mpfr_set_str_binary (x, "1010000010100011011001010101010010001100001101011101110001011001E-1"); mpfr_set_prec (y, 32); test_sqrt (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 2405743844UL)) { printf ("Error for n^2+n+1/2 with n=2405743843\n"); exit (1); } mpfr_set_prec (x, 65); mpfr_set_str_binary (x, "10100000101000110110010101010100100011000011010111011100010110001E-2"); mpfr_set_prec (y, 32); test_sqrt (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 2405743844UL)) { printf ("Error for n^2+n+1/4 with n=2405743843\n"); mpfr_dump (y); exit (1); } mpfr_set_prec (x, 66); mpfr_set_str_binary (x, "101000001010001101100101010101001000110000110101110111000101100011E-3"); mpfr_set_prec (y, 32); test_sqrt (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 2405743844UL)) { printf ("Error for n^2+n+1/4+1/8 with n=2405743843\n"); mpfr_dump (y); exit (1); } mpfr_set_prec (x, 66); mpfr_set_str_binary (x, "101000001010001101100101010101001000110000110101110111000101100001E-3"); mpfr_set_prec (y, 32); test_sqrt (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 2405743843UL)) { printf ("Error for n^2+n+1/8 with n=2405743843\n"); mpfr_dump (y); exit (1); } mpfr_set_prec (x, 27); mpfr_set_str_binary (x, "0.110100111010101000010001011"); if ((inexact = test_sqrt (x, x, MPFR_RNDZ)) >= 0) { printf ("Wrong inexact flag: expected -1, got %d\n", inexact); exit (1); } mpfr_set_prec (x, 2); for (p=2; p<1000; p++) { mpfr_set_prec (z, p); mpfr_set_ui (z, 1, MPFR_RNDN); mpfr_nexttoinf (z); test_sqrt (x, z, MPFR_RNDU); if (mpfr_cmp_ui_2exp(x, 3, -1)) { printf ("Error: sqrt(1+ulp(1), up) should give 1.5 (prec=%u)\n", (unsigned int) p); printf ("got "); mpfr_print_binary (x); puts (""); exit (1); } } /* check inexact flag */ mpfr_set_prec (x, 5); mpfr_set_str_binary (x, "1.1001E-2"); if ((inexact = test_sqrt (x, x, MPFR_RNDN))) { printf ("Wrong inexact flag: expected 0, got %d\n", inexact); exit (1); } mpfr_set_prec (x, 2); mpfr_set_prec (z, 2); /* checks the sign is correctly set */ mpfr_set_si (x, 1, MPFR_RNDN); mpfr_set_si (z, -1, MPFR_RNDN); test_sqrt (z, x, MPFR_RNDN); if (mpfr_cmp_ui (z, 0) < 0) { printf ("Error: square root of 1 gives "); mpfr_print_binary(z); putchar('\n'); exit (1); } mpfr_set_prec (x, 192); mpfr_set_prec (z, 160); mpfr_set_str_binary (z, "0.1011010100000100100100100110011001011100100100000011000111011001011101101101110000110100001000100001100001011000E1"); mpfr_set_prec (x, 160); test_sqrt(x, z, MPFR_RNDN); test_sqrt(z, x, MPFR_RNDN); mpfr_set_prec (x, 53); mpfr_set_str (x, "8093416094703476.0", 10, MPFR_RNDN); mpfr_div_2exp (x, x, 1075, MPFR_RNDN); test_sqrt (x, x, MPFR_RNDN); mpfr_set_str (z, "1e55596835b5ef@-141", 16, MPFR_RNDN); if (mpfr_cmp (x, z)) { printf ("Error: square root of 8093416094703476*2^(-1075)\n"); printf ("expected "); mpfr_dump (z); printf ("got "); mpfr_dump (x); exit (1); } mpfr_set_prec (x, 33); mpfr_set_str_binary (x, "0.111011011011110001100111111001000e-10"); mpfr_set_prec (z, 157); inexact = test_sqrt (z, x, MPFR_RNDN); mpfr_set_prec (x, 157); mpfr_set_str_binary (x, "0.11110110101100101111001011100011100011100001101010111011010000100111011000111110100001001011110011111100101110010110010110011001011011010110010000011001101E-5"); if (mpfr_cmp (x, z)) { printf ("Error: square root (1)\n"); exit (1); } if (inexact <= 0) { printf ("Error: wrong inexact flag (1)\n"); exit (1); } /* case prec(result) << prec(input) */ mpfr_set_prec (z, 2); for (p = 2; p < 1000; p++) { mpfr_set_prec (x, p); mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_nextabove (x); /* 1.0 < x <= 1.5 thus 1 < sqrt(x) <= 1.23 */ inexact = test_sqrt (z, x, MPFR_RNDN); MPFR_ASSERTN(inexact < 0 && mpfr_cmp_ui (z, 1) == 0); inexact = test_sqrt (z, x, MPFR_RNDZ); MPFR_ASSERTN(inexact < 0 && mpfr_cmp_ui (z, 1) == 0); inexact = test_sqrt (z, x, MPFR_RNDU); MPFR_ASSERTN(inexact > 0 && mpfr_cmp_ui_2exp (z, 3, -1) == 0); inexact = test_sqrt (z, x, MPFR_RNDD); MPFR_ASSERTN(inexact < 0 && mpfr_cmp_ui (z, 1) == 0); inexact = test_sqrt (z, x, MPFR_RNDA); MPFR_ASSERTN(inexact > 0 && mpfr_cmp_ui_2exp (z, 3, -1) == 0); } /* corner case rw = 0 in rounding to nearest */ mpfr_set_prec (z, GMP_NUMB_BITS - 1); mpfr_set_prec (y, GMP_NUMB_BITS - 1); mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_mul_2exp (y, y, GMP_NUMB_BITS - 1, MPFR_RNDN); mpfr_nextabove (y); for (p = 2 * GMP_NUMB_BITS - 1; p <= 1000; p++) { mpfr_set_prec (x, p); mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_set_exp (x, GMP_NUMB_BITS); mpfr_add_ui (x, x, 1, MPFR_RNDN); /* now x = 2^(GMP_NUMB_BITS - 1) + 1 (GMP_NUMB_BITS bits) */ MPFR_ASSERTN (mpfr_mul (x, x, x, MPFR_RNDN) == 0); /* exact */ inexact = test_sqrt (z, x, MPFR_RNDN); /* even rule: z should be 2^(GMP_NUMB_BITS - 1) */ MPFR_ASSERTN (inexact < 0); MPFR_ASSERTN (mpfr_cmp_ui_2exp (z, 1, GMP_NUMB_BITS - 1) == 0); mpfr_nextbelow (x); /* now x is just below [2^(GMP_NUMB_BITS - 1) + 1]^2 */ inexact = test_sqrt (z, x, MPFR_RNDN); MPFR_ASSERTN(inexact < 0 && mpfr_cmp_ui_2exp (z, 1, GMP_NUMB_BITS - 1) == 0); mpfr_nextabove (x); mpfr_nextabove (x); /* now x is just above [2^(GMP_NUMB_BITS - 1) + 1]^2 */ inexact = test_sqrt (z, x, MPFR_RNDN); if (mpfr_cmp (z, y)) { printf ("Error for sqrt(x) in rounding to nearest\n"); printf ("x="); mpfr_dump (x); printf ("Expected "); mpfr_dump (y); printf ("Got "); mpfr_dump (z); exit (1); } if (inexact <= 0) { printf ("Wrong inexact flag in corner case for p = %lu\n", (unsigned long) p); exit (1); } } mpfr_set_prec (x, 1000); mpfr_set_ui (x, 9, MPFR_RNDN); mpfr_set_prec (y, 10); inexact = test_sqrt (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 3) || inexact != 0) { printf ("Error in sqrt(9:1000) for prec=10\n"); exit (1); } mpfr_set_prec (y, GMP_NUMB_BITS); mpfr_nextabove (x); inexact = test_sqrt (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 3) || inexact >= 0) { printf ("Error in sqrt(9:1000) for prec=%d\n", (int) GMP_NUMB_BITS); exit (1); } mpfr_set_prec (x, 2 * GMP_NUMB_BITS); mpfr_set_prec (y, GMP_NUMB_BITS); mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_nextabove (y); mpfr_set (x, y, MPFR_RNDN); inexact = test_sqrt (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 1) || inexact >= 0) { printf ("Error in sqrt(1) for prec=%d\n", (int) GMP_NUMB_BITS); mpfr_dump (y); exit (1); } mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); }
/* Usage: tzeta - generic tests tzeta s prec rnd_mode - compute zeta(s) with precision 'prec' and rounding mode 'mode' */ int main (int argc, char *argv[]) { mpfr_t s, y, z; mpfr_prec_t prec; mpfr_rnd_t rnd_mode; int inex; tests_start_mpfr (); if (argc != 1 && argc != 4) { printf ("Usage: tzeta\n" " or tzeta s prec rnd_mode\n"); exit (1); } if (argc == 4) { prec = atoi(argv[2]); mpfr_init2 (s, prec); mpfr_init2 (z, prec); mpfr_set_str (s, argv[1], 10, MPFR_RNDN); rnd_mode = (mpfr_rnd_t) atoi(argv[3]); mpfr_zeta (z, s, rnd_mode); mpfr_out_str (stdout, 10, 0, z, MPFR_RNDN); printf ("\n"); mpfr_clear (s); mpfr_clear (z); return 0; } test1(); mpfr_init2 (s, MPFR_PREC_MIN); mpfr_init2 (y, MPFR_PREC_MIN); mpfr_init2 (z, MPFR_PREC_MIN); /* the following seems to loop */ mpfr_set_prec (s, 6); mpfr_set_prec (z, 6); mpfr_set_str_binary (s, "1.10010e4"); mpfr_zeta (z, s, MPFR_RNDZ); mpfr_set_prec (s, 53); mpfr_set_prec (y, 53); mpfr_set_prec (z, 53); mpfr_set_ui (s, 1, MPFR_RNDN); mpfr_clear_divby0(); mpfr_zeta (z, s, MPFR_RNDN); if (!mpfr_inf_p (z) || MPFR_SIGN (z) < 0 || !mpfr_divby0_p()) { printf ("Error in mpfr_zeta for s = 1 (should be +inf) with divby0 flag\n"); exit (1); } mpfr_set_str_binary (s, "0.1100011101110111111111111010000110010111001011001011"); mpfr_set_str_binary (y, "-0.11111101111011001001001111111000101010000100000100100E2"); mpfr_zeta (z, s, MPFR_RNDN); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (1,RNDN)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDZ); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (1,RNDZ)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDU); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (1,RNDU)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDD); mpfr_nexttoinf (y); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (1,RNDD)\n"); exit (1); } mpfr_set_str_binary (s, "0.10001011010011100110010001100100001011000010011001011"); mpfr_set_str_binary (y, "-0.11010011010010101101110111011010011101111101111010110E1"); mpfr_zeta (z, s, MPFR_RNDN); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (2,RNDN)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDZ); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (2,RNDZ)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDU); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (2,RNDU)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDD); mpfr_nexttoinf (y); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (2,RNDD)\n"); exit (1); } mpfr_set_str_binary (s, "0.1100111110100001111110111000110101111001011101000101"); mpfr_set_str_binary (y, "-0.10010111010110000111011111001101100001111011000001010E3"); mpfr_zeta (z, s, MPFR_RNDN); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (3,RNDN)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDD); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (3,RNDD)\n"); exit (1); } mpfr_nexttozero (y); mpfr_zeta (z, s, MPFR_RNDZ); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (3,RNDZ)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDU); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (3,RNDU)\n"); exit (1); } mpfr_set_str (s, "-400000001", 10, MPFR_RNDZ); mpfr_zeta (z, s, MPFR_RNDN); if (!(mpfr_inf_p (z) && MPFR_SIGN(z) < 0)) { printf ("Error in mpfr_zeta (-400000001)\n"); exit (1); } mpfr_set_str (s, "-400000003", 10, MPFR_RNDZ); mpfr_zeta (z, s, MPFR_RNDN); if (!(mpfr_inf_p (z) && MPFR_SIGN(z) > 0)) { printf ("Error in mpfr_zeta (-400000003)\n"); exit (1); } mpfr_set_prec (s, 34); mpfr_set_prec (z, 34); mpfr_set_str_binary (s, "-1.111111100001011110000010001010000e-35"); mpfr_zeta (z, s, MPFR_RNDD); mpfr_set_str_binary (s, "-1.111111111111111111111111111111111e-2"); if (mpfr_cmp (s, z)) { printf ("Error in mpfr_zeta, prec=34, MPFR_RNDD\n"); mpfr_dump (z); exit (1); } /* bug found by nightly tests on June 7, 2007 */ mpfr_set_prec (s, 23); mpfr_set_prec (z, 25); mpfr_set_str_binary (s, "-1.0110110110001000000000e-27"); mpfr_zeta (z, s, MPFR_RNDN); mpfr_set_prec (s, 25); mpfr_set_str_binary (s, "-1.111111111111111111111111e-2"); if (mpfr_cmp (s, z)) { printf ("Error in mpfr_zeta, prec=25, MPFR_RNDN\n"); printf ("expected "); mpfr_dump (s); printf ("got "); mpfr_dump (z); exit (1); } /* bug reported by Kevin Rauch on 26 Oct 2007 */ mpfr_set_prec (s, 128); mpfr_set_prec (z, 128); mpfr_set_str_binary (s, "-0.1000000000000000000000000000000000000000000000000000000000000001E64"); inex = mpfr_zeta (z, s, MPFR_RNDN); MPFR_ASSERTN (mpfr_inf_p (z) && MPFR_SIGN (z) < 0 && inex < 0); inex = mpfr_zeta (z, s, MPFR_RNDU); mpfr_set_inf (s, -1); mpfr_nextabove (s); MPFR_ASSERTN (mpfr_equal_p (z, s) && inex > 0); mpfr_clear (s); mpfr_clear (y); mpfr_clear (z); test_generic (2, 70, 5); test2 (); tests_end_mpfr (); return 0; }
int mpfr_sin (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode) { mpfr_t c, xr; mpfr_srcptr xx; mpfr_exp_t expx, err; mpfr_prec_t precy, m; int inexact, sign, reduce; MPFR_ZIV_DECL (loop); MPFR_SAVE_EXPO_DECL (expo); MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode), ("y[%#R]=%R inexact=%d", y, y, inexact)); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) { if (MPFR_IS_NAN (x) || MPFR_IS_INF (x)) { MPFR_SET_NAN (y); MPFR_RET_NAN; } else /* x is zero */ { MPFR_ASSERTD (MPFR_IS_ZERO (x)); MPFR_SET_ZERO (y); MPFR_SET_SAME_SIGN (y, x); MPFR_RET (0); } } /* sin(x) = x - x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */ MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -2 * MPFR_GET_EXP (x), 2, 0, rnd_mode, {}); MPFR_SAVE_EXPO_MARK (expo); /* Compute initial precision */ precy = MPFR_PREC (y); if (precy >= MPFR_SINCOS_THRESHOLD) return mpfr_sin_fast (y, x, rnd_mode); m = precy + MPFR_INT_CEIL_LOG2 (precy) + 13; expx = MPFR_GET_EXP (x); mpfr_init (c); mpfr_init (xr); MPFR_ZIV_INIT (loop, m); for (;;) { /* first perform argument reduction modulo 2*Pi (if needed), also helps to determine the sign of sin(x) */ if (expx >= 2) /* If Pi < x < 4, we need to reduce too, to determine the sign of sin(x). For 2 <= |x| < Pi, we could avoid the reduction. */ { reduce = 1; /* As expx + m - 1 will silently be converted into mpfr_prec_t in the mpfr_set_prec call, the assert below may be useful to avoid undefined behavior. */ MPFR_ASSERTN (expx + m - 1 <= MPFR_PREC_MAX); mpfr_set_prec (c, expx + m - 1); mpfr_set_prec (xr, m); mpfr_const_pi (c, MPFR_RNDN); mpfr_mul_2ui (c, c, 1, MPFR_RNDN); mpfr_remainder (xr, x, c, MPFR_RNDN); /* The analysis is similar to that of cos.c: |xr - x - 2kPi| <= 2^(2-m). Thus we can decide the sign of sin(x) if xr is at distance at least 2^(2-m) of both 0 and +/-Pi. */ mpfr_div_2ui (c, c, 1, MPFR_RNDN); /* Since c approximates Pi with an error <= 2^(2-expx-m) <= 2^(-m), it suffices to check that c - |xr| >= 2^(2-m). */ if (MPFR_SIGN (xr) > 0) mpfr_sub (c, c, xr, MPFR_RNDZ); else mpfr_add (c, c, xr, MPFR_RNDZ); if (MPFR_IS_ZERO(xr) || MPFR_EXP(xr) < (mpfr_exp_t) 3 - (mpfr_exp_t) m || MPFR_EXP(c) < (mpfr_exp_t) 3 - (mpfr_exp_t) m) goto ziv_next; /* |xr - x - 2kPi| <= 2^(2-m), thus |sin(xr) - sin(x)| <= 2^(2-m) */ xx = xr; } else /* the input argument is already reduced */ { reduce = 0; xx = x; } sign = MPFR_SIGN(xx); /* now that the argument is reduced, precision m is enough */ mpfr_set_prec (c, m); mpfr_cos (c, xx, MPFR_RNDZ); /* can't be exact */ mpfr_nexttoinf (c); /* now c = cos(x) rounded away */ mpfr_mul (c, c, c, MPFR_RNDU); /* away */ mpfr_ui_sub (c, 1, c, MPFR_RNDZ); mpfr_sqrt (c, c, MPFR_RNDZ); if (MPFR_IS_NEG_SIGN(sign)) MPFR_CHANGE_SIGN(c); /* Warning: c may be 0! */ if (MPFR_UNLIKELY (MPFR_IS_ZERO (c))) { /* Huge cancellation: increase prec a lot! */ m = MAX (m, MPFR_PREC (x)); m = 2 * m; } else { /* the absolute error on c is at most 2^(3-m-EXP(c)), plus 2^(2-m) if there was an argument reduction. Since EXP(c) <= 1, 3-m-EXP(c) >= 2-m, thus the error is at most 2^(3-m-EXP(c)) in case of argument reduction. */ err = 2 * MPFR_GET_EXP (c) + (mpfr_exp_t) m - 3 - (reduce != 0); if (MPFR_CAN_ROUND (c, err, precy, rnd_mode)) break; /* check for huge cancellation (Near 0) */ if (err < (mpfr_exp_t) MPFR_PREC (y)) m += MPFR_PREC (y) - err; /* Check if near 1 */ if (MPFR_GET_EXP (c) == 1) m += m; } ziv_next: /* Else generic increase */ MPFR_ZIV_NEXT (loop, m); } MPFR_ZIV_FREE (loop); inexact = mpfr_set (y, c, rnd_mode); /* inexact cannot be 0, since this would mean that c was representable within the target precision, but in that case mpfr_can_round will fail */ mpfr_clear (c); mpfr_clear (xr); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (y, inexact, rnd_mode); }
static void check_small (void) { mpfr_t x; char *s; mpfr_exp_t e; mpfr_prec_t p; mpfr_init (x); mpfr_set_prec (x, 20); mpfr_set_ui (x, 2, MPFR_RNDN); mpfr_nexttozero (x); s = mpfr_get_str (NULL, &e, 4, 2, x, MPFR_RNDU); if (strcmp (s, "20") || (e != 1)) { printf ("Error in mpfr_get_str: 2- rounded up with 2 digits" " in base 4\n"); exit (1); } mpfr_free_str (s); /* check n_digits=0 */ mpfr_set_prec (x, 5); mpfr_set_ui (x, 17, MPFR_RNDN); s = mpfr_get_str (NULL, &e, 3, 0, x, MPFR_RNDN); mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 36, 0, x, MPFR_RNDN); mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 62, 0, x, MPFR_RNDN); mpfr_free_str (s); mpfr_set_prec (x, 64); mpfr_set_si (x, -1, MPFR_RNDN); mpfr_div_2exp (x, x, 63, MPFR_RNDN); /* x = -2^(-63) */ mpfr_add_ui (x, x, 1, MPFR_RNDN); /* x = 1 - 2^(-63) */ mpfr_mul_2exp (x, x, 32, MPFR_RNDN); /* x = 2^32 - 2^(-31) */ s = mpfr_get_str (NULL, &e, 3, 21, x, MPFR_RNDU); if (strcmp (s, "102002022201221111211") || (e != 21)) { printf ("Error in mpfr_get_str: 2^32-2^(-31) rounded up with" " 21 digits in base 3\n"); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 3, 20, x, MPFR_RNDU); if (strcmp (s, "10200202220122111122") || (e != 21)) { printf ("Error in mpfr_get_str: 2^32-2^(-31) rounded up with" " 20 digits in base 3\n"); exit (1); } mpfr_free_str (s); /* check corner case ret!=0, j0!=0 in mpfr_get_str_aux */ mpfr_set_prec (x, 100); mpfr_set_str_binary (x, "0.1001011111010001101110010101010101111001010111111101101101100110100011110110000101110110001011110000E-9"); s = mpfr_get_str (NULL, &e, 3, 2, x, MPFR_RNDU); if (strcmp (s, "22") || (e != -6)) { printf ("Error in mpfr_get_str: 100-bit number rounded up with" " 2 digits in base 3\n"); exit (1); } mpfr_free_str (s); /* check corner case exact=0 in mpfr_get_str_aux */ mpfr_set_prec (x, 100); mpfr_set_str_binary (x, "0.1001001111101101111000101000110111111010101100000110010001111111011001101011101100001100110000000000E8"); s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDZ); if (strcmp (s, "14") || (e != 3)) { printf ("Error in mpfr_get_str: 100-bit number rounded to zero with" " 2 digits in base 10\n"); exit (1); } mpfr_free_str (s); for (p=4; p<=200; p++) { mpfr_set_prec (x, p); mpfr_set_str (x, "6.5", 10, MPFR_RNDN); s = mpfr_get_str (NULL, &e, 6, 2, x, MPFR_RNDN); if (strcmp (s, "10") || (e != 2)) { printf ("Error in mpfr_get_str: 6.5 rounded to nearest with" " 2 digits in base 6\n"); exit (1); } mpfr_free_str (s); mpfr_nexttoinf (x); s = mpfr_get_str (NULL, &e, 6, 2, x, MPFR_RNDN); if (strcmp (s, "11") || (e != 2)) { printf ("Error in mpfr_get_str: 6.5+ rounded to nearest with" " 2 digits in base 6\ngot %se%d instead of 11e2\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str (x, "6.5", 10, MPFR_RNDN); mpfr_nexttozero (x); s = mpfr_get_str (NULL, &e, 6, 2, x, MPFR_RNDN); if (strcmp (s, "10") || (e != 2)) { printf ("Error in mpfr_get_str: 6.5- rounded to nearest with" " 2 digits in base 6\n"); exit (1); } mpfr_free_str (s); } mpfr_set_prec (x, 3); mpfr_set_ui (x, 7, MPFR_RNDN); s = mpfr_get_str (NULL, &e, 2, 2, x, MPFR_RNDU); if (strcmp (s, "10") || (e != 4)) { printf ("Error in mpfr_get_str: 7 rounded up with 2 bits should" " give 0.10e3 instead of 0.%s*2^%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* problem found by Fabrice Rouillier */ mpfr_set_prec (x, 63); mpfr_set_str (x, "5e14", 10, MPFR_RNDN); s = mpfr_get_str (NULL, &e, 10, 18, x, MPFR_RNDU); mpfr_free_str (s); /* bug found by Johan Vervloet */ mpfr_set_prec (x, 6); mpfr_set_str (x, "688.0", 10, MPFR_RNDN); s = mpfr_get_str (NULL, &e, 2, 4, x, MPFR_RNDU); if (strcmp (s, "1011") || (e != 10)) { printf ("Error in mpfr_get_str: 688 printed up to 4 bits should" " give 1.011e9\ninstead of "); mpfr_out_str (stdout, 2, 4, x, MPFR_RNDU); puts (""); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 38); mpfr_set_str_binary (x, "1.0001110111110100011010100010010100110e-6"); s = mpfr_get_str (NULL, &e, 8, 10, x, MPFR_RNDU); if (strcmp (s, "1073721522") || (e != -1)) { printf ("Error in mpfr_get_str (3): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 53); mpfr_set_str_binary (x, "0.11010111011101100010000100010101110001000000010111001E454"); s = mpfr_get_str (NULL, &e, 19, 12, x, MPFR_RNDU); if (strcmp (s, "b1cgfa4gha0h") || (e != 107)) { printf ("Error in mpfr_get_str (4): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 145); mpfr_set_str_binary (x, "-0.1000110011000001011000010101101010110110101100101110100011111100011110011001001001010000100001000011000011000000010111011001000111101001110100110e6"); s = mpfr_get_str (NULL, &e, 4, 53, x, MPFR_RNDU); if (strcmp (s, "-20303001120111222312230232203330132121021100201003003") || (e != 3)) { printf ("Error in mpfr_get_str (5): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 45); mpfr_set_str_binary (x, "-0.00100111010110010001011001110111010001010010010"); s = mpfr_get_str (NULL, &e, 32, 9, x, MPFR_RNDN); if (strcmp (s, "-4tchctq54") || (e != 0)) { printf ("Error in mpfr_get_str (6): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* worst case found by Vincent Lefe`vre */ mpfr_set_prec (x, 53); mpfr_set_str_binary (x, "10011110111100000000001011011110101100010000011011111E164"); s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDN); if (strcmp (s, "13076622631878654") || (e != 66)) { printf ("Error in mpfr_get_str (7): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10000001001001001100011101010011011011111000011000100E93"); s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDU); if (strcmp (s, "46") || e != 44) { printf ("Error in mpfr_get_str (8): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10010001111100000111001111010101001010000010111010101E55"); s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDN); if (strcmp (s, "19") || e != 33) { printf ("Error in mpfr_get_str (9): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11011001010010111110010101101100111110111000010110110E44"); s = mpfr_get_str (NULL, &e, 10, 3, x, MPFR_RNDN); if (strcmp (s, "135") || e != 30) { printf ("Error in mpfr_get_str (10): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11101111101000001011100001111000011111101111011001100E72"); s = mpfr_get_str (NULL, &e, 10, 4, x, MPFR_RNDN); if (strcmp (s, "3981") || e != 38) { printf ("Error in mpfr_get_str (11): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10011001001100100010111100001101110101001001111110000E46"); s = mpfr_get_str (NULL, &e, 10, 5, x, MPFR_RNDN); if (strcmp (s, "37930") || e != 30) { printf ("Error in mpfr_get_str (12): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10001100110111001011011110011011011101100011010001011E-72"); s = mpfr_get_str (NULL, &e, 10, 6, x, MPFR_RNDN); if (strcmp (s, "104950") || e != -5) { printf ("Error in mpfr_get_str (13): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10100100001011001000011001101101000110100110000010111E89"); s = mpfr_get_str (NULL, &e, 10, 7, x, MPFR_RNDN); if (strcmp (s, "3575392") || e != 43) { printf ("Error in mpfr_get_str (14): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11000011011110110010100110001010000001010011001011001E-73"); s = mpfr_get_str (NULL, &e, 10, 8, x, MPFR_RNDN); if (strcmp (s, "72822386") || e != -6) { printf ("Error in mpfr_get_str (15): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10101010001101000111001100001000100011100010010001010E78"); s = mpfr_get_str (NULL, &e, 10, 9, x, MPFR_RNDN); if (strcmp (s, "180992873") || e != 40) { printf ("Error in mpfr_get_str (16): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10110111001000100000001101111001100101101110011011101E91"); s = mpfr_get_str (NULL, &e, 10, 10, x, MPFR_RNDN); if (strcmp (s, "1595312255") || e != 44) { printf ("Error in mpfr_get_str (17): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10011101010111101111000100111011101011110100110110101E93"); s = mpfr_get_str (NULL, &e, 10, 11, x, MPFR_RNDN); if (strcmp (s, "54835744350") || e != 44) { printf ("Error in mpfr_get_str (18): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10011101010111101111000100111011101011110100110110101E92"); s = mpfr_get_str (NULL, &e, 10, 12, x, MPFR_RNDN); if (strcmp (s, "274178721752") || e != 44) { printf ("Error in mpfr_get_str (19): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10011101010111101111000100111011101011110100110110101E91"); s = mpfr_get_str (NULL, &e, 10, 13, x, MPFR_RNDN); if (strcmp (s, "1370893608762") || e != 44) { printf ("Error in mpfr_get_str (20): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10010011010110011100010010100101100011101000011111111E92"); s = mpfr_get_str (NULL, &e, 10, 14, x, MPFR_RNDN); if (strcmp (s, "25672105101864") || e != 44) { printf ("Error in mpfr_get_str (21): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "100110111110110001000101110100100101101000011111001E87"); s = mpfr_get_str (NULL, &e, 10, 15, x, MPFR_RNDN); if (strcmp (s, "212231308858721") || e != 42) { printf ("Error in mpfr_get_str (22): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10111010110000111000101100101111001011011100101001111E-128"); s = mpfr_get_str (NULL, &e, 10, 15, x, MPFR_RNDN); if (strcmp (s, "193109287087290") || e != -22) { printf ("Error in mpfr_get_str (22b): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10001101101011010001111110000111010111010000110101010E80"); s = mpfr_get_str (NULL, &e, 10, 16, x, MPFR_RNDN); if (strcmp (s, "6026241735727920") || e != 40) { printf ("Error in mpfr_get_str (23): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "100010001011101001110101000110011001001000110001001E-81"); s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDN); if (strcmp (s, "49741483709103481") || e != -9) { printf ("Error in mpfr_get_str (24): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11000100001001001110111010011001111001001010110101111E-101"); s = mpfr_get_str (NULL, &e, 10, 7, x, MPFR_RNDN); if (strcmp (s, "2722049") || e != -14) { printf ("Error in mpfr_get_str (25): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11111001010011100101000001111111110001001001110110001E-135"); s = mpfr_get_str (NULL, &e, 10, 8, x, MPFR_RNDN); if (strcmp (s, "20138772") || e != -24) { printf ("Error in mpfr_get_str (26): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11111001010011100101000001111111110001001001110110001E-136"); s = mpfr_get_str (NULL, &e, 10, 9, x, MPFR_RNDN); if (strcmp (s, "100693858") || e != -24) { printf ("Error in mpfr_get_str (27): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10001000001110010110001011111011111011011010000110001E-110"); s = mpfr_get_str (NULL, &e, 10, 14, x, MPFR_RNDN); if (strcmp (s, "36923634350619") || e != -17) { printf ("Error in mpfr_get_str (28): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11001100010111000111100010000110011101110001000101111E-87"); s = mpfr_get_str (NULL, &e, 10, 16, x, MPFR_RNDN); if (strcmp (s, "4646636036100804") || e != -10) { printf ("Error in mpfr_get_str (29): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10011111001111110100001001010111111011010101111111000E-99"); s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDN); if (strcmp (s, "88399901882446712") || e != -14) { printf ("Error in mpfr_get_str (30): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 8116315218207718*2^(-293) ~ 0.5100000000000000000015*10^(-72) */ mpfr_set_str_binary (x, "11100110101011011111011100101011101110110001111100110E-293"); s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDU); if (strcmp (s, "52") || e != -72) { printf ("Error in mpfr_get_str (31u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDD); if (strcmp (s, "51") || e != -72) { printf ("Error in mpfr_get_str (31d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 6712731423444934*2^536 ~ .151000000000000000000067*10^178 */ mpfr_set_str_binary (x, "10111110110010011000110010011111101111000111111000110E536"); s = mpfr_get_str (NULL, &e, 10, 3, x, MPFR_RNDU); if (strcmp (s, "152") || e != 178) { printf ("Error in mpfr_get_str (32u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 3, x, MPFR_RNDD); if (strcmp (s, "151") || e != 178) { printf ("Error in mpfr_get_str (32d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 3356365711722467*2^540 ~ .120800000000000000000054*10^179 */ mpfr_set_str_binary (x, "1011111011001001100011001001111110111100011111100011E540"); s = mpfr_get_str (NULL, &e, 10, 4, x, MPFR_RNDU); if (strcmp (s, "1209") || e != 179) { printf ("Error in mpfr_get_str (33u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 4, x, MPFR_RNDD); if (strcmp (s, "1208") || e != 179) { printf ("Error in mpfr_get_str (33d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 6475049196144587*2^100 ~ .8208099999999999999999988*10^46 */ mpfr_set_str_binary (x, "10111000000010000010111011111001111010100011111001011E100"); s = mpfr_get_str (NULL, &e, 10, 5, x, MPFR_RNDU); if (strcmp (s, "82081") || e != 46) { printf ("Error in mpfr_get_str (34u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 5, x, MPFR_RNDD); if (strcmp (s, "82080") || e != 46) { printf ("Error in mpfr_get_str (34d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 6722280709661868*2^364 ~ .25260100000000000000000012*10^126 */ mpfr_set_str_binary (x, "10111111000011110000011110001110001111010010010101100E364"); s = mpfr_get_str (NULL, &e, 10, 6, x, MPFR_RNDU); if (strcmp (s, "252602") || e != 126) { printf ("Error in mpfr_get_str (35u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 6, x, MPFR_RNDD); if (strcmp (s, "252601") || e != 126) { printf ("Error in mpfr_get_str (35d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 5381065484265332*2^(-455) ~ .578389299999999999999999982*10^(-121) */ mpfr_set_str_binary (x, "10011000111100000110011110000101100111110011101110100E-455"); s = mpfr_get_str (NULL, &e, 10, 7, x, MPFR_RNDU); if (strcmp (s, "5783893") || e != -121) { printf ("Error in mpfr_get_str (36u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 7, x, MPFR_RNDD); if (strcmp (s, "5783892") || e != -121) { printf ("Error in mpfr_get_str (36d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 8369123604277281*2^(-852) ~ .27869147000000000000000000056*10^(-240) */ mpfr_set_str_binary (x, "11101101110111010110001101111100000111010100000100001E-852"); s = mpfr_get_str (NULL, &e, 10, 8, x, MPFR_RNDU); if (strcmp (s, "27869148") || e != -240) { printf ("Error in mpfr_get_str (37u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 8, x, MPFR_RNDD); if (strcmp (s, "27869147") || e != -240) { printf ("Error in mpfr_get_str (37d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 7976538478610756*2^377 ~ .245540326999999999999999999982*10^130 */ mpfr_set_str_binary (x, "11100010101101001111010010110100011100000100101000100E377"); s = mpfr_get_str (NULL, &e, 10, 9, x, MPFR_RNDU); if (strcmp (s, "245540327") || e != 130) { printf ("Error in mpfr_get_str (38u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 9, x, MPFR_RNDD); if (strcmp (s, "245540326") || e != 130) { printf ("Error in mpfr_get_str (38d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 8942832835564782*2^(-382) ~ .9078555839000000000000000000038*10^(-99) */ mpfr_set_str_binary (x, "11111110001010111010110000110011100110001010011101110E-382"); s = mpfr_get_str (NULL, &e, 10, 10, x, MPFR_RNDU); if (strcmp (s, "9078555840") || e != -99) { printf ("Error in mpfr_get_str (39u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 10, x, MPFR_RNDD); if (strcmp (s, "9078555839") || e != -99) { printf ("Error in mpfr_get_str (39d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 4471416417782391*2^(-380) ~ .18157111678000000000000000000077*10^(-98) */ mpfr_set_str_binary (x, "1111111000101011101011000011001110011000101001110111E-380"); s = mpfr_get_str (NULL, &e, 10, 11, x, MPFR_RNDU); if (strcmp (s, "18157111679") || e != -98) { printf ("Error in mpfr_get_str (40u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 11, x, MPFR_RNDD); if (strcmp (s, "18157111678") || e != -98) { printf ("Error in mpfr_get_str (40d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 7225450889282194*2^711 ~ .778380362292999999999999999999971*10^230 */ mpfr_set_str_binary (x, "11001101010111000001001100001100110010000001010010010E711"); s = mpfr_get_str (NULL, &e, 10, 12, x, MPFR_RNDU); if (strcmp (s, "778380362293") || e != 230) { printf ("Error in mpfr_get_str (41u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 12, x, MPFR_RNDD); if (strcmp (s, "778380362292") || e != 230) { printf ("Error in mpfr_get_str (41d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 3612725444641097*2^713 ~ .1556760724585999999999999999999942*10^231 */ mpfr_set_str_binary (x, "1100110101011100000100110000110011001000000101001001E713"); s = mpfr_get_str (NULL, &e, 10, 13, x, MPFR_RNDU); if (strcmp (s, "1556760724586") || e != 231) { printf ("Error in mpfr_get_str (42u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 13, x, MPFR_RNDD); if (strcmp (s, "1556760724585") || e != 231) { printf ("Error in mpfr_get_str (42d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 6965949469487146*2^(-248) ~ .15400733123779000000000000000000016*10^(-58) */ mpfr_set_str_binary (x, "11000101111110111111001111111101001101111000000101010E-248"); s = mpfr_get_str (NULL, &e, 10, 14, x, MPFR_RNDU); if (strcmp (s, "15400733123780") || e != -58) { printf ("Error in mpfr_get_str (43u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 14, x, MPFR_RNDD); if (strcmp (s, "15400733123779") || e != -58) { printf ("Error in mpfr_get_str (43d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 3482974734743573*2^(-244) ~ .12320586499023200000000000000000013*10^(-57) */ mpfr_set_str_binary (x, "1100010111111011111100111111110100110111100000010101E-244"); s = mpfr_get_str (NULL, &e, 10, 15, x, MPFR_RNDU); if (strcmp (s, "123205864990233") || e != -57) { printf ("Error in mpfr_get_str (44u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 15, x, MPFR_RNDD); if (strcmp (s, "123205864990232") || e != -57) { printf ("Error in mpfr_get_str (44d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 7542952370752766*2^(-919) ~ .170206189963739699999999999999999974*10^(-260) */ mpfr_set_str_binary (x, "11010110011000100011001110100100111011100110011111110E-919"); s = mpfr_get_str (NULL, &e, 10, 16, x, MPFR_RNDU); if (strcmp (s, "1702061899637397") || e != -260) { printf ("Error in mpfr_get_str (45u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 16, x, MPFR_RNDD); if (strcmp (s, "1702061899637396") || e != -260) { printf ("Error in mpfr_get_str (45d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 5592117679628511*2^165 ~ .26153245263757307000000000000000000074*10^66 */ mpfr_set_str_binary (x, "10011110111100000000001011011110101100010000011011111E165"); s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDU); if (strcmp (s, "26153245263757308") || e != 66) { printf ("Error in mpfr_get_str (46u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDD); if (strcmp (s, "26153245263757307") || e != 66) { printf ("Error in mpfr_get_str (46d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11010010110111100001011010000110010000100001011011101E1223"); s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDN); if (strcmp (s, "10716284017294180") || e != 385) { printf ("Error in mpfr_get_str (47n): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 18, x, MPFR_RNDU); if (strcmp (s, "107162840172941805") || e != 385) { printf ("Error in mpfr_get_str (47u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 18, x, MPFR_RNDD); if (strcmp (s, "107162840172941804") || e != 385) { printf ("Error in mpfr_get_str (47d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11111101111011000001010100001101101000010010001111E122620"); s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDN); if (strcmp (s, "22183435284042374") || e != 36928) { printf ("Error in mpfr_get_str (48n): s=%s e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 18, x, MPFR_RNDU); if (strcmp (s, "221834352840423736") || e != 36928) { printf ("Error in mpfr_get_str (48u): s=%s e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 18, x, MPFR_RNDD); if (strcmp (s, "221834352840423735") || e != 36928) { printf ("Error in mpfr_get_str (48d): s=%s e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 45); mpfr_set_str_binary (x, "1E45"); s = mpfr_get_str (NULL, &e, 32, 9, x, MPFR_RNDN); mpfr_free_str (s); mpfr_set_prec (x, 7); mpfr_set_str_binary (x, "0.1010101E10"); s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDU); mpfr_free_str (s); /* checks rounding of negative numbers */ mpfr_set_prec (x, 7); mpfr_set_str (x, "-11.5", 10, MPFR_RNDN); s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDD); if (strcmp (s, "-12")) { printf ("Error in mpfr_get_str for x=-11.5 and rnd=MPFR_RNDD\n" "got %s instead of -12\n", s); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDU); if (strcmp (s, "-11")) { printf ("Error in mpfr_get_str for x=-11.5 and rnd=MPFR_RNDU\n"); exit (1); } mpfr_free_str (s); /* bug found by Jean-Pierre Merlet, produced error in mpfr_get_str */ mpfr_set_prec (x, 128); mpfr_set_str_binary (x, "0.10111001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011010E3"); s = mpfr_get_str (NULL, &e, 10, 0, x, MPFR_RNDU); mpfr_free_str (s); mpfr_set_prec (x, 381); mpfr_set_str_binary (x, "0.111111111111111111111111111111111111111111111111111111111111111111101110110000100110011101101101001010111000101111000100100011110101010110101110100000010100001000110100000100011111001000010010000010001010111001011110000001110010111101100001111000101101100000010110000101100100000101010110010110001010100111001111100011100101100000100100111001100010010011110011011010110000001000010"); s = mpfr_get_str (NULL, &e, 10, 0, x, MPFR_RNDD); if (e != 0) { printf ("Error in mpfr_get_str for x=0.999999..., exponent is %d" " instead of 0\n", (int) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 5); mpfr_set_str_binary (x, "1101.1"); /* 13.5, or (16)_7 + 1/2 */ s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN); /* we are in the tie case: both surrounding numbers are (16)_7 and (20)_7: since (16)_7 = 13 is odd and (20)_7 = 14 is even, we should have s = "20" and e = 2 */ if (e != 2 || strcmp (s, "20")) { printf ("Error in mpfr_get_str for x=13.5, base 7\n"); printf ("Expected s=20, e=2, got s=%s, e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); /* try the same example, with input just below or above 13.5 */ mpfr_set_prec (x, 1000); mpfr_set_str_binary (x, "1101.1"); mpfr_nextabove (x); s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN); if (e != 2 || strcmp (s, "20")) { printf ("Error in mpfr_get_str for x=13.5+tiny, base 7\n"); printf ("Expected s=20, e=2, got s=%s, e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "1101.1"); mpfr_nextbelow (x); s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN); if (e != 2 || strcmp (s, "16")) { printf ("Error in mpfr_get_str for x=13.5-tiny, base 7\n"); printf ("Expected s=16, e=2, got s=%s, e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 7); mpfr_set_str_binary (x, "110000.1"); /* 48.5, or (66)_7 + 1/2 */ s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN); /* we are in the tie case: both surrounding numbers are (66)_7 and (100)_7: since (66)_7 = 48 is even and (100)_7 is odd, we should hase s = "66" and e = 2 */ if (e != 2 || strcmp (s, "66")) { printf ("Error in mpfr_get_str for x=48.5, base 7\n"); printf ("Expected s=66, e=2, got s=%s, e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); /* try the same example, with input just below or above 48.5 */ mpfr_set_prec (x, 1000); mpfr_set_str_binary (x, "110000.1"); mpfr_nextabove (x); s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN); if (e != 3 || strcmp (s, "10")) { printf ("Error in mpfr_get_str for x=48.5+tiny, base 7\n"); printf ("Expected s=10, e=3, got s=%s, e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "110000.1"); mpfr_nextbelow (x); s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN); if (e != 2 || strcmp (s, "66")) { printf ("Error in mpfr_get_str for x=48.5-tiny, base 7\n"); printf ("Expected s=66, e=2, got s=%s, e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); mpfr_clear (x); }
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 void test_generic (mp_prec_t p0, mp_prec_t p1, unsigned int N) { mp_prec_t prec, xprec, yprec; mpfr_t x, y, z, t; #ifdef TWO_ARGS mpfr_t u; #elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) mpfr_t u; double d; #endif mp_rnd_t rnd; int inexact, compare, compare2; unsigned int n; unsigned long ctrt = 0, ctrn = 0; mp_exp_t old_emin, old_emax; old_emin = mpfr_get_emin (); old_emax = mpfr_get_emax (); mpfr_init (x); mpfr_init (y); mpfr_init (z); mpfr_init (t); #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) mpfr_init (u); #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); /* Note: in precision p1, we test 4 special cases. */ for (n = 0; n < (prec == p1 ? N + 4 : N); n++) { 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); #ifdef TWO_ARGS mpfr_set_prec (u, xprec); #elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) mpfr_set_prec (u, IEEE_DBL_MANT_DIG); #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 tests_default_random (x, TEST_RANDOM_POS, TEST_RANDOM_EMIN, TEST_RANDOM_EMAX); #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) tests_default_random (u, TEST_RANDOM_POS2, TEST_RANDOM_EMIN, TEST_RANDOM_EMAX); #endif #endif } else { /* Special cases tested in precision p1 if n <= 3. They are useful really in the extended exponent range. */ set_emin (MPFR_EMIN_MIN); set_emax (MPFR_EMAX_MAX); if (n <= 1) { mpfr_set_si (x, n == 0 ? 1 : -1, GMP_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, GMP_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, GMP_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, GMP_RNDN); mpfr_setmax (u, mpfr_get_emax ()); #endif } } 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); #elif defined(DOUBLE_ARG2) d = mpfr_get_d (u, rnd); compare = TEST_FUNCTION (y, x, d, rnd); #else compare = TEST_FUNCTION (y, x, rnd); #endif TGENERIC_CHECK ("Bad inexact flag", (compare != 0) ^ (mpfr_inexflag_p () == 0)); ctrt++; 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)); else if (MPFR_IS_ZERO (y)) TGENERIC_CHECK ("Bad underflow flag", (compare != 0) ^ (mpfr_underflow_p () == 0)); } else if (mpfr_overflow_p ()) { TGENERIC_CHECK ("Bad compare value (overflow)", compare != 0); mpfr_nexttoinf (y); TGENERIC_CHECK ("Should have been max MPFR number", 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", 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 this triggers the mpfr_fmod bug fixed in r6235. */ mpfr_prec_round (x, mpfr_get_prec (x) + (randlimb () & 15), GMP_RNDN); #if defined(TWO_ARGS) mpfr_prec_round (u, mpfr_get_prec (u) + (randlimb () & 15), GMP_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); #else inexact = TEST_FUNCTION (z, x, rnd); #endif if (mpfr_erangeflag_p ()) goto next_n; if (mpfr_nan_p (z) || mpfr_cmp (t, z) != 0) { printf ("results differ for x="); mpfr_out_str (stdout, 2, xprec, x, GMP_RNDN); #ifdef TWO_ARGS printf ("\nu="); mpfr_out_str (stdout, 2, xprec, u, GMP_RNDN); #elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) printf ("\nu="); mpfr_out_str (stdout, 2, IEEE_DBL_MANT_DIG, u, GMP_RNDN); #endif printf (" prec=%u rnd_mode=%s\n", (unsigned) prec, mpfr_print_rnd_mode (rnd)); printf ("got "); mpfr_out_str (stdout, 2, prec, z, GMP_RNDN); puts (""); printf ("expected "); mpfr_out_str (stdout, 2, prec, t, GMP_RNDN); puts (""); printf ("approx "); mpfr_print_binary (y); puts (""); 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 (((inexact == 0) && (compare != 0)) || ((inexact > 0) && (compare <= 0)) || ((inexact < 0) && (compare >= 0))) { printf ("Wrong inexact flag for rnd=%s: expected %d, got %d" "\n", mpfr_print_rnd_mode (rnd), compare, inexact); printf ("x="); mpfr_print_binary (x); puts (""); #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) printf ("u="); mpfr_print_binary (u); puts (""); #endif printf ("y="); mpfr_print_binary (y); puts (""); printf ("t="); mpfr_print_binary (t); puts (""); 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 ()) { 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_print_binary (x); puts (""); #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) printf ("u="); mpfr_print_binary (u); puts (""); #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_clear (x); mpfr_clear (y); mpfr_clear (z); mpfr_clear (t); #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2) mpfr_clear (u); #endif }
static void overflow_inv (void) { mpfr_t x, y, z; int precx; int s, t; int inex; int rnd; mpfr_init2 (y, 2); mpfr_init2 (z, 8); mpfr_set_si (y, -1, MPFR_RNDN); for (precx = 10; precx <= 100; precx += 90) { const char *sp = precx == 10 ? "overflow_inv (precx = 10)" : "overflow_inv (precx = 100)"; mpfr_init2 (x, precx); for (s = -1; s <= 1; s += 2) { inex = mpfr_set_si_2exp (x, s, - mpfr_get_emax (), MPFR_RNDN); MPFR_ASSERTN (inex == 0); for (t = 0; t <= 5; t++) { /* If precx = 10: * x = s * 2^(-emax) * (1 + t * 2^(-9)), so that * 1/x = s * 2^emax * (1 - t * 2^(-9) + eps) with eps > 0. * Values of (1/x) / 2^emax and overflow condition for x > 0: * t = 0: 1 o: always * t = 1: 0.11111111 100000000011... o: MPFR_RNDN and MPFR_RNDU * t = 2: 0.11111111 000000001111... o: MPFR_RNDU * t = 3: 0.11111110 100000100011... o: never * * If precx = 100: * t = 0: always overflow * t > 0: overflow for MPFR_RNDN and MPFR_RNDU. */ RND_LOOP (rnd) { int inf, overflow; mpfr_rnd_t rnd2; if (rnd == MPFR_RNDA) rnd2 = s < 0 ? MPFR_RNDD : MPFR_RNDU; else rnd2 = (mpfr_rnd_t) rnd; overflow = t == 0 || ((mpfr_rnd_t) rnd == MPFR_RNDN && (precx > 10 || t == 1)) || (rnd2 == (s < 0 ? MPFR_RNDD : MPFR_RNDU) && (precx > 10 || t <= 2)); inf = overflow && ((mpfr_rnd_t) rnd == MPFR_RNDN || rnd2 == (s < 0 ? MPFR_RNDD : MPFR_RNDU)); mpfr_clear_flags (); inex = mpfr_pow (z, x, y, (mpfr_rnd_t) rnd); if (overflow ^ !! mpfr_overflow_p ()) { printf ("Bad overflow flag in %s\nfor mpfr_pow%s\n" "s = %d, t = %d, %s\n", sp, ext ? ", extended exponent range" : "", s, t, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); exit (1); } if (overflow && (inf ^ !! MPFR_IS_INF (z))) { printf ("Bad value in %s\nfor mpfr_pow%s\n" "s = %d, t = %d, %s\nGot ", sp, ext ? ", extended exponent range" : "", s, t, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN); printf (" instead of %s value.\n", inf ? "infinite" : "finite"); exit (1); } test_others (NULL, "-1", (mpfr_rnd_t) rnd, x, y, z, inex, __gmpfr_flags, sp); } /* RND_LOOP */ mpfr_nexttoinf (x); } /* for (t = ...) */ } /* for (s = ...) */ mpfr_clear (x); } /* for (precx = ...) */ mpfr_clears (y, z, (mpfr_ptr) 0); }