static void mpfr_const_log10 (mpfr_ptr log10) { mpfr_set_ui (log10, 10, MPFR_RNDN); /* exact since prec >= 4 */ mpfr_log (log10, log10, MPFR_RNDN); /* error <= 1/2 ulp */ }
static void check64 (void) { mpfr_t x, t, u; mpfr_init (x); mpfr_init (t); mpfr_init (u); mpfr_set_prec (x, 29); mpfr_set_str_binary (x, "1.1101001000101111011010010110e-3"); mpfr_set_prec (t, 58); mpfr_set_str_binary (t, "0.11100010011111001001100110010111110110011000000100101E-1"); mpfr_set_prec (u, 29); test_add (u, x, t, MPFR_RNDD); mpfr_set_str_binary (t, "1.0101011100001000011100111110e-1"); if (mpfr_cmp (u, t)) { printf ("mpfr_add(u, x, t) failed for prec(x)=29, prec(t)=58\n"); printf ("expected "); mpfr_out_str (stdout, 2, 29, t, MPFR_RNDN); puts (""); printf ("got "); mpfr_out_str (stdout, 2, 29, u, MPFR_RNDN); puts (""); exit(1); } mpfr_set_prec (x, 4); mpfr_set_str_binary (x, "-1.0E-2"); mpfr_set_prec (t, 2); mpfr_set_str_binary (t, "-1.1e-2"); mpfr_set_prec (u, 2); test_add (u, x, t, MPFR_RNDN); if (MPFR_MANT(u)[0] << 2) { printf ("result not normalized for prec=2\n"); mpfr_print_binary (u); puts (""); exit (1); } mpfr_set_str_binary (t, "-1.0e-1"); if (mpfr_cmp (u, t)) { printf ("mpfr_add(u, x, t) failed for prec(x)=4, prec(t)=2\n"); printf ("expected -1.0e-1\n"); printf ("got "); mpfr_out_str (stdout, 2, 4, u, MPFR_RNDN); puts (""); exit (1); } mpfr_set_prec (x, 8); mpfr_set_str_binary (x, "-0.10011010"); /* -77/128 */ mpfr_set_prec (t, 4); mpfr_set_str_binary (t, "-1.110e-5"); /* -7/128 */ mpfr_set_prec (u, 4); test_add (u, x, t, MPFR_RNDN); /* should give -5/8 */ mpfr_set_str_binary (t, "-1.010e-1"); if (mpfr_cmp (u, t)) { printf ("mpfr_add(u, x, t) failed for prec(x)=8, prec(t)=4\n"); printf ("expected -1.010e-1\n"); printf ("got "); mpfr_out_str (stdout, 2, 4, u, MPFR_RNDN); puts (""); exit (1); } mpfr_set_prec (x, 112); mpfr_set_prec (t, 98); mpfr_set_prec (u, 54); mpfr_set_str_binary (x, "-0.11111100100000000011000011100000101101010001000111E-401"); mpfr_set_str_binary (t, "0.10110000100100000101101100011111111011101000111000101E-464"); test_add (u, x, t, MPFR_RNDN); if (mpfr_cmp (u, x)) { printf ("mpfr_add(u, x, t) failed for prec(x)=112, prec(t)=98\n"); exit (1); } mpfr_set_prec (x, 92); mpfr_set_prec (t, 86); mpfr_set_prec (u, 53); mpfr_set_str (x, "-5.03525136761487735093e-74", 10, MPFR_RNDN); mpfr_set_str (t, "8.51539046314262304109e-91", 10, MPFR_RNDN); test_add (u, x, t, MPFR_RNDN); if (mpfr_cmp_str1 (u, "-5.0352513676148773509283672e-74") ) { printf ("mpfr_add(u, x, t) failed for prec(x)=92, prec(t)=86\n"); exit (1); } mpfr_set_prec(x, 53); mpfr_set_prec(t, 76); mpfr_set_prec(u, 76); mpfr_set_str_binary(x, "-0.10010010001001011011110000000000001010011011011110001E-32"); mpfr_set_str_binary(t, "-0.1011000101110010000101111111011111010001110011110111100110101011110010011111"); mpfr_sub(u, x, t, MPFR_RNDU); mpfr_set_str_binary(t, "0.1011000101110010000101111111011100111111101010011011110110101011101000000100"); if (mpfr_cmp(u,t)) { printf ("expect "); mpfr_print_binary(t); puts (""); printf ("mpfr_add failed for precisions 53-76\n"); exit (1); } mpfr_set_prec(x, 53); mpfr_set_prec(t, 108); mpfr_set_prec(u, 108); mpfr_set_str_binary(x, "-0.10010010001001011011110000000000001010011011011110001E-32"); mpfr_set_str_binary(t, "-0.101100010111001000010111111101111101000111001111011110011010101111001001111000111011001110011000000000111111"); mpfr_sub(u, x, t, MPFR_RNDU); mpfr_set_str_binary(t, "0.101100010111001000010111111101110011111110101001101111011010101110100000001011000010101110011000000000111111"); if (mpfr_cmp(u,t)) { printf ("expect "); mpfr_print_binary(t); puts (""); printf ("mpfr_add failed for precisions 53-108\n"); exit (1); } mpfr_set_prec(x, 97); mpfr_set_prec(t, 97); mpfr_set_prec(u, 97); mpfr_set_str_binary(x, "0.1111101100001000000001011000110111101000001011111000100001000101010100011111110010000000000000000E-39"); mpfr_set_ui(t, 1, MPFR_RNDN); test_add (u, x, t, MPFR_RNDN); mpfr_set_str_binary(x, "0.1000000000000000000000000000000000000000111110110000100000000101100011011110100000101111100010001E1"); if (mpfr_cmp(u,x)) { printf ("mpfr_add failed for precision 97\n"); exit (1); } mpfr_set_prec(x, 128); mpfr_set_prec(t, 128); mpfr_set_prec(u, 128); mpfr_set_str_binary(x, "0.10101011111001001010111011001000101100111101000000111111111011010100001100011101010001010111111101111010100110111111100101100010E-4"); mpfr_set(t, x, MPFR_RNDN); mpfr_sub(u, x, t, MPFR_RNDN); mpfr_set_prec(x, 96); mpfr_set_prec(t, 96); mpfr_set_prec(u, 96); mpfr_set_str_binary(x, "0.111000000001110100111100110101101001001010010011010011100111100011010100011001010011011011000010E-4"); mpfr_set(t, x, MPFR_RNDN); mpfr_sub(u, x, t, MPFR_RNDN); mpfr_set_prec(x, 85); mpfr_set_prec(t, 85); mpfr_set_prec(u, 85); mpfr_set_str_binary(x, "0.1111101110100110110110100010101011101001100010100011110110110010010011101100101111100E-4"); mpfr_set_str_binary(t, "0.1111101110100110110110100010101001001000011000111000011101100101110100001110101010110E-4"); mpfr_sub(u, x, t, MPFR_RNDU); mpfr_sub(x, x, t, MPFR_RNDU); if (mpfr_cmp(x, u) != 0) { printf ("Error in mpfr_sub: u=x-t and x=x-t give different results\n"); exit (1); } if ((MPFR_MANT(u)[(MPFR_PREC(u)-1)/mp_bits_per_limb] & ((mp_limb_t)1<<(mp_bits_per_limb-1)))==0) { printf ("Error in mpfr_sub: result is not msb-normalized (1)\n"); exit (1); } mpfr_set_prec(x, 65); mpfr_set_prec(t, 65); mpfr_set_prec(u, 65); mpfr_set_str_binary(x, "0.10011010101000110101010000000011001001001110001011101011111011101E623"); mpfr_set_str_binary(t, "0.10011010101000110101010000000011001001001110001011101011111011100E623"); mpfr_sub(u, x, t, MPFR_RNDU); if (mpfr_cmp_ui_2exp(u, 1, 558)) { /* 2^558 */ printf ("Error (1) in mpfr_sub\n"); exit (1); } mpfr_set_prec(x, 64); mpfr_set_prec(t, 64); mpfr_set_prec(u, 64); mpfr_set_str_binary(x, "0.1000011110101111011110111111000011101011101111101101101100000100E-220"); mpfr_set_str_binary(t, "0.1000011110101111011110111111000011101011101111101101010011111101E-220"); test_add (u, x, t, MPFR_RNDU); if ((MPFR_MANT(u)[0] & 1) != 1) { printf ("error in mpfr_add with rnd_mode=MPFR_RNDU\n"); printf ("b= "); mpfr_print_binary(x); puts (""); printf ("c= "); mpfr_print_binary(t); puts (""); printf ("b+c="); mpfr_print_binary(u); puts (""); exit (1); } /* bug found by Norbert Mueller, 14 Sep 2000 */ mpfr_set_prec(x, 56); mpfr_set_prec(t, 83); mpfr_set_prec(u, 10); mpfr_set_str_binary(x, "0.10001001011011001111101100110100000101111010010111010111E-7"); mpfr_set_str_binary(t, "0.10001001011011001111101100110100000101111010010111010111000000000111110110110000100E-7"); mpfr_sub(u, x, t, MPFR_RNDU); /* array bound write found by Norbert Mueller, 26 Sep 2000 */ mpfr_set_prec(x, 109); mpfr_set_prec(t, 153); mpfr_set_prec(u, 95); mpfr_set_str_binary(x,"0.1001010000101011101100111000110001111111111111111111111111111111111111111111111111111111111111100000000000000E33"); mpfr_set_str_binary(t,"-0.100101000010101110110011100011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011100101101000000100100001100110111E33"); test_add (u, x, t, MPFR_RNDN); /* array bound writes found by Norbert Mueller, 27 Sep 2000 */ mpfr_set_prec(x, 106); mpfr_set_prec(t, 53); mpfr_set_prec(u, 23); mpfr_set_str_binary(x, "-0.1000011110101111111001010001000100001011000000000000000000000000000000000000000000000000000000000000000000E-59"); mpfr_set_str_binary(t, "-0.10000111101011111110010100010001101100011100110100000E-59"); mpfr_sub(u, x, t, MPFR_RNDN); mpfr_set_prec(x, 177); mpfr_set_prec(t, 217); mpfr_set_prec(u, 160); mpfr_set_str_binary(x, "-0.111010001011010000111001001010010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E35"); mpfr_set_str_binary(t, "0.1110100010110100001110010010100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111011010011100001111001E35"); test_add (u, x, t, MPFR_RNDN); mpfr_set_prec(x, 214); mpfr_set_prec(t, 278); mpfr_set_prec(u, 207); mpfr_set_str_binary(x, "0.1000100110100110101101101101000000010000100111000001001110001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E66"); mpfr_set_str_binary(t, "-0.10001001101001101011011011010000000100001001110000010011100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111011111001001100011E66"); test_add (u, x, t, MPFR_RNDN); mpfr_set_prec(x, 32); mpfr_set_prec(t, 247); mpfr_set_prec(u, 223); mpfr_set_str_binary(x, "0.10000000000000000000000000000000E1"); mpfr_set_str_binary(t, "0.1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000110001110100000100011110000101110110011101110100110110111111011010111100100000000000000000000000000E0"); mpfr_sub(u, x, t, MPFR_RNDN); if ((MPFR_MANT(u)[(MPFR_PREC(u)-1)/mp_bits_per_limb] & ((mp_limb_t)1<<(mp_bits_per_limb-1)))==0) { printf ("Error in mpfr_sub: result is not msb-normalized (2)\n"); exit (1); } /* bug found by Nathalie Revol, 21 March 2001 */ mpfr_set_prec (x, 65); mpfr_set_prec (t, 65); mpfr_set_prec (u, 65); mpfr_set_str_binary (x, "0.11100100101101001100111011111111110001101001000011101001001010010E-35"); mpfr_set_str_binary (t, "0.10000000000000000000000000000000000001110010010110100110011110000E1"); mpfr_sub (u, t, x, MPFR_RNDU); if ((MPFR_MANT(u)[(MPFR_PREC(u)-1)/mp_bits_per_limb] & ((mp_limb_t)1<<(mp_bits_per_limb-1)))==0) { printf ("Error in mpfr_sub: result is not msb-normalized (3)\n"); exit (1); } /* bug found by Fabrice Rouillier, 27 Mar 2001 */ mpfr_set_prec (x, 107); mpfr_set_prec (t, 107); mpfr_set_prec (u, 107); mpfr_set_str_binary (x, "0.10111001001111010010001000000010111111011011011101000001001000101000000000000000000000000000000000000000000E315"); mpfr_set_str_binary (t, "0.10000000000000000000000000000000000101110100100101110110000001100101011111001000011101111100100100111011000E350"); mpfr_sub (u, x, t, MPFR_RNDU); if ((MPFR_MANT(u)[(MPFR_PREC(u)-1)/mp_bits_per_limb] & ((mp_limb_t)1<<(mp_bits_per_limb-1)))==0) { printf ("Error in mpfr_sub: result is not msb-normalized (4)\n"); exit (1); } /* checks that NaN flag is correctly reset */ mpfr_set_ui (t, 1, MPFR_RNDN); mpfr_set_ui (u, 1, MPFR_RNDN); mpfr_set_nan (x); test_add (x, t, u, MPFR_RNDN); if (mpfr_cmp_ui (x, 2)) { printf ("Error in mpfr_add: 1+1 gives "); mpfr_out_str(stdout, 10, 0, x, MPFR_RNDN); exit (1); } mpfr_clear(x); mpfr_clear(t); mpfr_clear(u); }
static void check_1minuseps (void) { static mpfr_prec_t prec_a[] = { MPFR_PREC_MIN, 30, 31, 32, 33, 62, 63, 64, 65, 126, 127, 128, 129 }; static int supp_b[] = { 0, 1, 2, 3, 4, 29, 30, 31, 32, 33, 34, 35, 61, 62, 63, 64, 65, 66, 67 }; mpfr_t a, b, c; unsigned int ia, ib, ic; mpfr_init2 (c, MPFR_PREC_MIN); for (ia = 0; ia < numberof (prec_a); ia++) for (ib = 0; ib < numberof(supp_b); ib++) { mpfr_prec_t prec_b; int rnd_mode; prec_b = prec_a[ia] + supp_b[ib]; mpfr_init2 (a, prec_a[ia]); mpfr_init2 (b, prec_b); mpfr_set_ui (c, 1, MPFR_RNDN); mpfr_div_ui (b, c, prec_a[ia], MPFR_RNDN); mpfr_sub (b, c, b, MPFR_RNDN); /* b = 1 - 2^(-prec_a) */ for (ic = 0; ic < numberof(supp_b); ic++) for (rnd_mode = 0; rnd_mode < MPFR_RND_MAX; rnd_mode++) { mpfr_t s; int inex_a, inex_s; mpfr_set_ui (c, 1, MPFR_RNDN); mpfr_div_ui (c, c, prec_a[ia] + supp_b[ic], MPFR_RNDN); inex_a = test_add (a, b, c, (mpfr_rnd_t) rnd_mode); mpfr_init2 (s, 256); inex_s = test_add (s, b, c, MPFR_RNDN); /* exact */ if (inex_s) { printf ("check_1minuseps: result should have been exact " "(ia = %u, ib = %u, ic = %u)\n", ia, ib, ic); exit (1); } inex_s = mpfr_prec_round (s, prec_a[ia], (mpfr_rnd_t) rnd_mode); if ((inex_a < 0 && inex_s >= 0) || (inex_a == 0 && inex_s != 0) || (inex_a > 0 && inex_s <= 0) || !mpfr_equal_p (a, s)) { printf ("check_1minuseps: results are different.\n"); printf ("ia = %u, ib = %u, ic = %u\n", ia, ib, ic); exit (1); } mpfr_clear (s); } mpfr_clear (a); mpfr_clear (b); } mpfr_clear (c); }
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) */ inexact = mpfr_mul (x, x, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); /* exact */ inexact = test_sqrt (z, x, MPFR_RNDN); /* even rule: z should be 2^(GMP_NUMB_BITS - 1) */ MPFR_ASSERTN (inexact < 0); inexact = mpfr_cmp_ui_2exp (z, 1, GMP_NUMB_BITS - 1); MPFR_ASSERTN (inexact == 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); }
/* Put in y an approximation of erfc(x) for large x, using formulae 7.1.23 and 7.1.24 from Abramowitz and Stegun. Returns e such that the error is bounded by 2^e ulp(y), or returns 0 in case of underflow. */ static mpfr_exp_t mpfr_erfc_asympt (mpfr_ptr y, mpfr_srcptr x) { mpfr_t t, xx, err; unsigned long k; mpfr_prec_t prec = MPFR_PREC(y); mpfr_exp_t exp_err; mpfr_init2 (t, prec); mpfr_init2 (xx, prec); mpfr_init2 (err, 31); /* let u = 2^(1-p), and let us represent the error as (1+u)^err with a bound for err */ mpfr_mul (xx, x, x, MPFR_RNDD); /* err <= 1 */ mpfr_ui_div (xx, 1, xx, MPFR_RNDU); /* upper bound for 1/(2x^2), err <= 2 */ mpfr_div_2ui (xx, xx, 1, MPFR_RNDU); /* exact */ mpfr_set_ui (t, 1, MPFR_RNDN); /* current term, exact */ mpfr_set (y, t, MPFR_RNDN); /* current sum */ mpfr_set_ui (err, 0, MPFR_RNDN); for (k = 1; ; k++) { mpfr_mul_ui (t, t, 2 * k - 1, MPFR_RNDU); /* err <= 4k-3 */ mpfr_mul (t, t, xx, MPFR_RNDU); /* err <= 4k */ /* for -1 < x < 1, and |nx| < 1, we have |(1+x)^n| <= 1+7/4|nx|. Indeed, for x>=0: log((1+x)^n) = n*log(1+x) <= n*x. Let y=n*x < 1, then exp(y) <= 1+7/4*y. For x<=0, let x=-x, we can prove by induction that (1-x)^n >= 1-n*x.*/ mpfr_mul_2si (err, err, MPFR_GET_EXP (y) - MPFR_GET_EXP (t), MPFR_RNDU); mpfr_add_ui (err, err, 14 * k, MPFR_RNDU); /* 2^(1-p) * t <= 2 ulp(t) */ mpfr_div_2si (err, err, MPFR_GET_EXP (y) - MPFR_GET_EXP (t), MPFR_RNDU); if (MPFR_GET_EXP (t) + (mpfr_exp_t) prec <= MPFR_GET_EXP (y)) { /* the truncation error is bounded by |t| < ulp(y) */ mpfr_add_ui (err, err, 1, MPFR_RNDU); break; } if (k & 1) mpfr_sub (y, y, t, MPFR_RNDN); else mpfr_add (y, y, t, MPFR_RNDN); } /* the error on y is bounded by err*ulp(y) */ mpfr_mul (t, x, x, MPFR_RNDU); /* rel. err <= 2^(1-p) */ mpfr_div_2ui (err, err, 3, MPFR_RNDU); /* err/8 */ mpfr_add (err, err, t, MPFR_RNDU); /* err/8 + xx */ mpfr_mul_2ui (err, err, 3, MPFR_RNDU); /* err + 8*xx */ mpfr_exp (t, t, MPFR_RNDU); /* err <= 1/2*ulp(t) + err(x*x)*t <= 1/2*ulp(t)+2*|x*x|*ulp(t) <= (2*|x*x|+1/2)*ulp(t) */ mpfr_mul (t, t, x, MPFR_RNDN); /* err <= 1/2*ulp(t) + (4*|x*x|+1)*ulp(t) <= (4*|x*x|+3/2)*ulp(t) */ mpfr_const_pi (xx, MPFR_RNDZ); /* err <= ulp(Pi) */ mpfr_sqrt (xx, xx, MPFR_RNDN); /* err <= 1/2*ulp(xx) + ulp(Pi)/2/sqrt(Pi) <= 3/2*ulp(xx) */ mpfr_mul (t, t, xx, MPFR_RNDN); /* err <= (8 |xx| + 13/2) * ulp(t) */ mpfr_div (y, y, t, MPFR_RNDN); /* the relative error on input y is bounded by (1+u)^err with u = 2^(1-p), that on t is bounded by (1+u)^(8 |xx| + 13/2), thus that on output y is bounded by 8 |xx| + 7 + err. */ if (MPFR_IS_ZERO(y)) { /* If y is zero, most probably we have underflow. We check it directly using the fact that erfc(x) <= exp(-x^2)/sqrt(Pi)/x for x >= 0. We compute an upper approximation of exp(-x^2)/sqrt(Pi)/x. */ mpfr_mul (t, x, x, MPFR_RNDD); /* t <= x^2 */ mpfr_neg (t, t, MPFR_RNDU); /* -x^2 <= t */ mpfr_exp (t, t, MPFR_RNDU); /* exp(-x^2) <= t */ mpfr_const_pi (xx, MPFR_RNDD); /* xx <= sqrt(Pi), cached */ mpfr_mul (xx, xx, x, MPFR_RNDD); /* xx <= sqrt(Pi)*x */ mpfr_div (y, t, xx, MPFR_RNDN); /* if y is zero, this means that the upper approximation of exp(-x^2)/sqrt(Pi)/x is nearer from 0 than from 2^(-emin-1), thus we have underflow. */ exp_err = 0; } else { mpfr_add_ui (err, err, 7, MPFR_RNDU); exp_err = MPFR_GET_EXP (err); } mpfr_clear (t); mpfr_clear (xx); mpfr_clear (err); return exp_err; }
/* The computation of z = pow(x,y) is done by z = exp(y * log(x)) = x^y For the special cases, see Section F.9.4.4 of the C standard: _ pow(±0, y) = ±inf for y an odd integer < 0. _ pow(±0, y) = +inf for y < 0 and not an odd integer. _ pow(±0, y) = ±0 for y an odd integer > 0. _ pow(±0, y) = +0 for y > 0 and not an odd integer. _ pow(-1, ±inf) = 1. _ pow(+1, y) = 1 for any y, even a NaN. _ pow(x, ±0) = 1 for any x, even a NaN. _ pow(x, y) = NaN for finite x < 0 and finite non-integer y. _ pow(x, -inf) = +inf for |x| < 1. _ pow(x, -inf) = +0 for |x| > 1. _ pow(x, +inf) = +0 for |x| < 1. _ pow(x, +inf) = +inf for |x| > 1. _ pow(-inf, y) = -0 for y an odd integer < 0. _ pow(-inf, y) = +0 for y < 0 and not an odd integer. _ pow(-inf, y) = -inf for y an odd integer > 0. _ pow(-inf, y) = +inf for y > 0 and not an odd integer. _ pow(+inf, y) = +0 for y < 0. _ pow(+inf, y) = +inf for y > 0. */ int mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode) { int inexact; int cmp_x_1; int y_is_integer; MPFR_SAVE_EXPO_DECL (expo); MPFR_LOG_FUNC (("x[%Pu]=%.*Rg y[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, mpfr_get_prec (y), mpfr_log_prec, y, rnd_mode), ("z[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (z), mpfr_log_prec, z, inexact)); if (MPFR_ARE_SINGULAR (x, y)) { /* pow(x, 0) returns 1 for any x, even a NaN. */ if (MPFR_UNLIKELY (MPFR_IS_ZERO (y))) return mpfr_set_ui (z, 1, rnd_mode); else if (MPFR_IS_NAN (x)) { MPFR_SET_NAN (z); MPFR_RET_NAN; } else if (MPFR_IS_NAN (y)) { /* pow(+1, NaN) returns 1. */ if (mpfr_cmp_ui (x, 1) == 0) return mpfr_set_ui (z, 1, rnd_mode); MPFR_SET_NAN (z); MPFR_RET_NAN; } else if (MPFR_IS_INF (y)) { if (MPFR_IS_INF (x)) { if (MPFR_IS_POS (y)) MPFR_SET_INF (z); else MPFR_SET_ZERO (z); MPFR_SET_POS (z); MPFR_RET (0); } else { int cmp; cmp = mpfr_cmpabs (x, __gmpfr_one) * MPFR_INT_SIGN (y); MPFR_SET_POS (z); if (cmp > 0) { /* Return +inf. */ MPFR_SET_INF (z); MPFR_RET (0); } else if (cmp < 0) { /* Return +0. */ MPFR_SET_ZERO (z); MPFR_RET (0); } else { /* Return 1. */ return mpfr_set_ui (z, 1, rnd_mode); } } } else if (MPFR_IS_INF (x)) { int negative; /* Determine the sign now, in case y and z are the same object */ negative = MPFR_IS_NEG (x) && is_odd (y); if (MPFR_IS_POS (y)) MPFR_SET_INF (z); else MPFR_SET_ZERO (z); if (negative) MPFR_SET_NEG (z); else MPFR_SET_POS (z); MPFR_RET (0); } else { int negative; MPFR_ASSERTD (MPFR_IS_ZERO (x)); /* Determine the sign now, in case y and z are the same object */ negative = MPFR_IS_NEG(x) && is_odd (y); if (MPFR_IS_NEG (y)) { MPFR_ASSERTD (! MPFR_IS_INF (y)); MPFR_SET_INF (z); mpfr_set_divby0 (); } else MPFR_SET_ZERO (z); if (negative) MPFR_SET_NEG (z); else MPFR_SET_POS (z); MPFR_RET (0); } } /* x^y for x < 0 and y not an integer is not defined */ y_is_integer = mpfr_integer_p (y); if (MPFR_IS_NEG (x) && ! y_is_integer) { MPFR_SET_NAN (z); MPFR_RET_NAN; } /* now the result cannot be NaN: (1) either x > 0 (2) or x < 0 and y is an integer */ cmp_x_1 = mpfr_cmpabs (x, __gmpfr_one); if (cmp_x_1 == 0) return mpfr_set_si (z, MPFR_IS_NEG (x) && is_odd (y) ? -1 : 1, rnd_mode); /* now we have: (1) either x > 0 (2) or x < 0 and y is an integer and in addition |x| <> 1. */ /* detect overflow: an overflow is possible if (a) |x| > 1 and y > 0 (b) |x| < 1 and y < 0. FIXME: this assumes 1 is always representable. FIXME2: maybe we can test overflow and underflow simultaneously. The idea is the following: first compute an approximation to y * log2|x|, using rounding to nearest. If |x| is not too near from 1, this approximation should be accurate enough, and in most cases enable one to prove that there is no underflow nor overflow. Otherwise, it should enable one to check only underflow or overflow, instead of both cases as in the present case. */ if (cmp_x_1 * MPFR_SIGN (y) > 0) { mpfr_t t; int negative, overflow; MPFR_SAVE_EXPO_MARK (expo); mpfr_init2 (t, 53); /* we want a lower bound on y*log2|x|: (i) if x > 0, it suffices to round log2(x) toward zero, and to round y*o(log2(x)) toward zero too; (ii) if x < 0, we first compute t = o(-x), with rounding toward 1, and then follow as in case (1). */ if (MPFR_SIGN (x) > 0) mpfr_log2 (t, x, MPFR_RNDZ); else { mpfr_neg (t, x, (cmp_x_1 > 0) ? MPFR_RNDZ : MPFR_RNDU); mpfr_log2 (t, t, MPFR_RNDZ); } mpfr_mul (t, t, y, MPFR_RNDZ); overflow = mpfr_cmp_si (t, __gmpfr_emax) > 0; mpfr_clear (t); MPFR_SAVE_EXPO_FREE (expo); if (overflow) { MPFR_LOG_MSG (("early overflow detection\n", 0)); negative = MPFR_SIGN(x) < 0 && is_odd (y); return mpfr_overflow (z, rnd_mode, negative ? -1 : 1); } } /* Basic underflow checking. One has: * - if y > 0, |x^y| < 2^(EXP(x) * y); * - if y < 0, |x^y| <= 2^((EXP(x) - 1) * y); * so that one can compute a value ebound such that |x^y| < 2^ebound. * If we have ebound <= emin - 2 (emin - 1 in directed rounding modes), * then there is an underflow and we can decide the return value. */ if (MPFR_IS_NEG (y) ? (MPFR_GET_EXP (x) > 1) : (MPFR_GET_EXP (x) < 0)) { mpfr_t tmp; mpfr_eexp_t ebound; int inex2; /* We must restore the flags. */ MPFR_SAVE_EXPO_MARK (expo); mpfr_init2 (tmp, sizeof (mpfr_exp_t) * CHAR_BIT); inex2 = mpfr_set_exp_t (tmp, MPFR_GET_EXP (x), MPFR_RNDN); MPFR_ASSERTN (inex2 == 0); if (MPFR_IS_NEG (y)) { inex2 = mpfr_sub_ui (tmp, tmp, 1, MPFR_RNDN); MPFR_ASSERTN (inex2 == 0); } mpfr_mul (tmp, tmp, y, MPFR_RNDU); if (MPFR_IS_NEG (y)) mpfr_nextabove (tmp); /* tmp doesn't necessarily fit in ebound, but that doesn't matter since we get the minimum value in such a case. */ ebound = mpfr_get_exp_t (tmp, MPFR_RNDU); mpfr_clear (tmp); MPFR_SAVE_EXPO_FREE (expo); if (MPFR_UNLIKELY (ebound <= __gmpfr_emin - (rnd_mode == MPFR_RNDN ? 2 : 1))) { /* warning: mpfr_underflow rounds away from 0 for MPFR_RNDN */ MPFR_LOG_MSG (("early underflow detection\n", 0)); return mpfr_underflow (z, rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode, MPFR_SIGN (x) < 0 && is_odd (y) ? -1 : 1); } } /* If y is an integer, we can use mpfr_pow_z (based on multiplications), but if y is very large (I'm not sure about the best threshold -- VL), we shouldn't use it, as it can be very slow and take a lot of memory (and even crash or make other programs crash, as several hundred of MBs may be necessary). Note that in such a case, either x = +/-2^b (this case is handled below) or x^y cannot be represented exactly in any precision supported by MPFR (the general case uses this property). */ if (y_is_integer && (MPFR_GET_EXP (y) <= 256)) { mpz_t zi; MPFR_LOG_MSG (("special code for y not too large integer\n", 0)); mpz_init (zi); mpfr_get_z (zi, y, MPFR_RNDN); inexact = mpfr_pow_z (z, x, zi, rnd_mode); mpz_clear (zi); return inexact; } /* Special case (+/-2^b)^Y which could be exact. If x is negative, then necessarily y is a large integer. */ { mpfr_exp_t b = MPFR_GET_EXP (x) - 1; MPFR_ASSERTN (b >= LONG_MIN && b <= LONG_MAX); /* FIXME... */ if (mpfr_cmp_si_2exp (x, MPFR_SIGN(x), b) == 0) { mpfr_t tmp; int sgnx = MPFR_SIGN (x); MPFR_LOG_MSG (("special case (+/-2^b)^Y\n", 0)); /* now x = +/-2^b, so x^y = (+/-1)^y*2^(b*y) is exact whenever b*y is an integer */ MPFR_SAVE_EXPO_MARK (expo); mpfr_init2 (tmp, MPFR_PREC (y) + sizeof (long) * CHAR_BIT); inexact = mpfr_mul_si (tmp, y, b, MPFR_RNDN); /* exact */ MPFR_ASSERTN (inexact == 0); /* Note: as the exponent range has been extended, an overflow is not possible (due to basic overflow and underflow checking above, as the result is ~ 2^tmp), and an underflow is not possible either because b is an integer (thus either 0 or >= 1). */ MPFR_CLEAR_FLAGS (); inexact = mpfr_exp2 (z, tmp, rnd_mode); mpfr_clear (tmp); if (sgnx < 0 && is_odd (y)) { mpfr_neg (z, z, rnd_mode); inexact = -inexact; } /* Without the following, the overflows3 test in tpow.c fails. */ MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (z, inexact, rnd_mode); } } MPFR_SAVE_EXPO_MARK (expo); /* Case where |y * log(x)| is very small. Warning: x can be negative, in that case y is a large integer. */ { mpfr_t t; mpfr_exp_t err; /* We need an upper bound on the exponent of y * log(x). */ mpfr_init2 (t, 16); if (MPFR_IS_POS(x)) mpfr_log (t, x, cmp_x_1 < 0 ? MPFR_RNDD : MPFR_RNDU); /* away from 0 */ else { /* if x < -1, round to +Inf, else round to zero */ mpfr_neg (t, x, (mpfr_cmp_si (x, -1) < 0) ? MPFR_RNDU : MPFR_RNDD); mpfr_log (t, t, (mpfr_cmp_ui (t, 1) < 0) ? MPFR_RNDD : MPFR_RNDU); } MPFR_ASSERTN (MPFR_IS_PURE_FP (t)); err = MPFR_GET_EXP (y) + MPFR_GET_EXP (t); mpfr_clear (t); MPFR_CLEAR_FLAGS (); MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (z, __gmpfr_one, - err, 0, (MPFR_SIGN (y) > 0) ^ (cmp_x_1 < 0), rnd_mode, expo, {}); } /* General case */ inexact = mpfr_pow_general (z, x, y, rnd_mode, y_is_integer, &expo); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (z, inexact, rnd_mode); }
int main (void) { mpfr_t x; mpfr_exp_t emin; tests_start_mpfr (); emin = mpfr_get_emin (); mpfr_init2 (x, IEEE_DBL_MANT_DIG); mpfr_set_d (x, 2.34763465, MPFR_RNDN); if (mpfr_cmp_d (x, 2.34763465) != 0) { printf ("Error in mpfr_cmp_d 2.34763465 and "); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar('\n'); exit (1); } if (mpfr_cmp_d (x, 2.345) <= 0) { printf ("Error in mpfr_cmp_d 2.345 and "); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar('\n'); exit (1); } if (mpfr_cmp_d (x, 2.4) >= 0) { printf ("Error in mpfr_cmp_d 2.4 and "); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar('\n'); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDZ); mpfr_neg (x, x, MPFR_RNDZ); if (mpfr_cmp_d (x, 0.0)) { printf ("Error in mpfr_cmp_d 0.0 and "); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar('\n'); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_ui_div (x, 1, x, MPFR_RNDU); if (mpfr_cmp_d (x, 0.0) == 0) { printf ("Error in mpfr_cmp_d (Inf, 0)\n"); exit (1); } /* Test in reduced exponent range. */ set_emin (1); mpfr_set_ui (x, 1, MPFR_RNDN); if (mpfr_cmp_d (x, 0.9) <= 0) { printf ("Error in reduced exponent range.\n"); exit (1); } set_emin (emin); #if !defined(MPFR_ERRDIVZERO) /* Check NAN */ { int c; mpfr_clear_flags (); c = mpfr_cmp_d (x, DBL_NAN); if (c != 0 || __gmpfr_flags != MPFR_FLAGS_ERANGE) { printf ("ERROR for NAN (1)\n"); printf ("Expected 0, got %d\n", c); printf ("Expected flags:"); flags_out (MPFR_FLAGS_ERANGE); printf ("Got flags: "); flags_out (__gmpfr_flags); #ifdef MPFR_NANISNAN printf ("The reason is that NAN == NAN. Please look at the configure " "output\nand Section \"In case of problem\" of the INSTALL " "file.\n"); #endif exit (1); } mpfr_set_nan (x); mpfr_clear_flags (); c = mpfr_cmp_d (x, 2.0); if (c != 0 || __gmpfr_flags != MPFR_FLAGS_ERANGE) { printf ("ERROR for NAN (2)\n"); printf ("Expected 0, got %d\n", c); printf ("Expected flags:"); flags_out (MPFR_FLAGS_ERANGE); printf ("Got flags: "); flags_out (__gmpfr_flags); #ifdef MPFR_NANISNAN printf ("The reason is that NAN == NAN. Please look at the configure " "output\nand Section \"In case of problem\" of the INSTALL " "file.\n"); #endif exit (1); } } #endif /* MPFR_ERRDIVZERO */ mpfr_clear (x); tests_end_mpfr (); return 0; }
static void special_overflow (void) { mpfr_t x, y; mpfr_exp_t emin, emax; int inex; emin = mpfr_get_emin (); emax = mpfr_get_emax (); set_emin (-125); set_emax (128); mpfr_init2 (x, 24); mpfr_init2 (y, 24); mpfr_set_str_binary (x, "0.101100100000000000110100E7"); mpfr_gamma (y, x, MPFR_RNDN); if (!mpfr_inf_p (y)) { printf ("Overflow error.\n"); mpfr_dump (y); exit (1); } /* problem mentioned by Kenneth Wilder, 18 Aug 2005 */ mpfr_set_prec (x, 29); mpfr_set_prec (y, 29); mpfr_set_str (x, "-200000000.5", 10, MPFR_RNDN); /* exact */ mpfr_gamma (y, x, MPFR_RNDN); if (!(mpfr_zero_p (y) && MPFR_SIGN (y) < 0)) { printf ("Error for gamma(-200000000.5)\n"); printf ("expected -0"); printf ("got "); mpfr_dump (y); exit (1); } mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_str (x, "-200000000.1", 10, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); if (!(mpfr_zero_p (y) && MPFR_SIGN (y) < 0)) { printf ("Error for gamma(-200000000.1), prec=53\n"); printf ("expected -0"); printf ("got "); mpfr_dump (y); exit (1); } /* another problem mentioned by Kenneth Wilder, 29 Aug 2005 */ mpfr_set_prec (x, 333); mpfr_set_prec (y, 14); mpfr_set_str (x, "-2.0000000000000000000000005", 10, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_prec (x, 14); mpfr_set_str_binary (x, "-11010011110001E66"); if (mpfr_cmp (x, y)) { printf ("Error for gamma(-2.0000000000000000000000005)\n"); printf ("expected "); mpfr_dump (x); printf ("got "); mpfr_dump (y); exit (1); } /* another tests from Kenneth Wilder, 31 Aug 2005 */ set_emax (200); set_emin (-200); mpfr_set_prec (x, 38); mpfr_set_prec (y, 54); mpfr_set_str_binary (x, "0.11101111011100111101001001010110101001E-166"); mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_prec (x, 54); mpfr_set_str_binary (x, "0.100010001101100001110110001010111111010000100101011E167"); if (mpfr_cmp (x, y)) { printf ("Error for gamma (test 1)\n"); printf ("expected "); mpfr_dump (x); printf ("got "); mpfr_dump (y); exit (1); } set_emax (1000); set_emin (-2000); mpfr_set_prec (x, 38); mpfr_set_prec (y, 71); mpfr_set_str_binary (x, "10101011011100001111111000010111110010E-1034"); /* 184083777010*2^(-1034) */ mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_prec (x, 71); mpfr_set_str_binary (x, "10111111001000011110010001000000000000110011110000000011101011111111100E926"); /* 1762885132679550982140*2^926 */ if (mpfr_cmp (x, y)) { printf ("Error for gamma (test 2)\n"); printf ("expected "); mpfr_dump (x); printf ("got "); mpfr_dump (y); exit (1); } mpfr_set_prec (x, 38); mpfr_set_prec (y, 88); mpfr_set_str_binary (x, "10111100111001010000100001100100100101E-104"); /* 202824096037*2^(-104) */ mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_prec (x, 88); mpfr_set_str_binary (x, "1010110101111000111010111100010110101010100110111000001011000111000011101100001101110010E-21"); /* 209715199999500283894743922*2^(-21) */ if (mpfr_cmp (x, y)) { printf ("Error for gamma (test 3)\n"); printf ("expected "); mpfr_dump (x); printf ("got "); mpfr_dump (y); exit (1); } mpfr_set_prec (x, 171); mpfr_set_prec (y, 38); mpfr_set_str (x, "-2993155353253689176481146537402947624254601559176535", 10, MPFR_RNDN); mpfr_div_2exp (x, x, 170, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_prec (x, 38); mpfr_set_str (x, "201948391737", 10, MPFR_RNDN); mpfr_mul_2exp (x, x, 92, MPFR_RNDN); if (mpfr_cmp (x, y)) { printf ("Error for gamma (test 5)\n"); printf ("expected "); mpfr_dump (x); printf ("got "); mpfr_dump (y); exit (1); } set_emin (-500000); mpfr_set_prec (x, 337); mpfr_set_prec (y, 38); mpfr_set_str (x, "-30000.000000000000000000000000000000000000000000001", 10, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_prec (x, 38); mpfr_set_str (x, "-3.623795987425E-121243", 10, MPFR_RNDN); if (mpfr_cmp (x, y)) { printf ("Error for gamma (test 7)\n"); printf ("expected "); mpfr_dump (x); printf ("got "); mpfr_dump (y); exit (1); } /* was producing infinite loop */ set_emin (emin); mpfr_set_prec (x, 71); mpfr_set_prec (y, 71); mpfr_set_str (x, "-200000000.1", 10, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); if (!(mpfr_zero_p (y) && MPFR_SIGN (y) < 0)) { printf ("Error for gamma (test 8)\n"); printf ("expected "); mpfr_dump (x); printf ("got "); mpfr_dump (y); exit (1); } set_emax (1073741823); mpfr_set_prec (x, 29); mpfr_set_prec (y, 29); mpfr_set_str (x, "423786866", 10, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error for gamma(423786866)\n"); exit (1); } /* check exact result */ mpfr_set_prec (x, 2); mpfr_set_ui (x, 3, MPFR_RNDN); inex = mpfr_gamma (x, x, MPFR_RNDN); if (inex != 0 || mpfr_cmp_ui (x, 2) != 0) { printf ("Error for gamma(3)\n"); exit (1); } mpfr_set_emax (1024); mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_str_binary (x, "101010110100110011111010000110001000111100000110101E-43"); mpfr_gamma (x, x, MPFR_RNDU); mpfr_set_str_binary (y, "110000011110001000111110110101011110000100001111111E971"); if (mpfr_cmp (x, y) != 0) { printf ("Error for gamma(4)\n"); printf ("expected "); mpfr_dump (y); printf ("got "); mpfr_dump (x); exit (1); } set_emin (emin); set_emax (emax); /* bug found by Kevin Rauch, 26 Oct 2007 */ mpfr_set_str (x, "1e19", 10, MPFR_RNDN); inex = mpfr_gamma (x, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && inex > 0); mpfr_clear (y); mpfr_clear (x); }
static void special (void) { mpfr_t x, y; int inex; mpfr_init (x); mpfr_init (y); mpfr_set_nan (x); mpfr_gamma (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error for gamma(NaN)\n"); exit (1); } mpfr_set_inf (x, -1); mpfr_gamma (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error for gamma(-Inf)\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_gamma (y, x, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error for gamma(+Inf)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error for gamma(+0)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) > 0) { printf ("Error for gamma(-0)\n"); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 1)) { printf ("Error for gamma(1)\n"); exit (1); } mpfr_set_si (x, -1, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error for gamma(-1)\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); #define CHECK_X1 "1.0762904832837976166" #define CHECK_Y1 "0.96134843256452096050" mpfr_set_str (x, CHECK_X1, 10, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_str (x, CHECK_Y1, 10, MPFR_RNDN); if (mpfr_cmp (y, x)) { printf ("mpfr_lngamma("CHECK_X1") is wrong:\n" "expected "); mpfr_print_binary (x); putchar ('\n'); printf ("got "); mpfr_print_binary (y); putchar ('\n'); exit (1); } #define CHECK_X2 "9.23709516716202383435e-01" #define CHECK_Y2 "1.0502315560291053398" mpfr_set_str (x, CHECK_X2, 10, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_str (x, CHECK_Y2, 10, MPFR_RNDN); if (mpfr_cmp (y, x)) { printf ("mpfr_lngamma("CHECK_X2") is wrong:\n" "expected "); mpfr_print_binary (x); putchar ('\n'); printf ("got "); mpfr_print_binary (y); putchar ('\n'); exit (1); } mpfr_set_prec (x, 8); mpfr_set_prec (y, 175); mpfr_set_ui (x, 33, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDU); mpfr_set_prec (x, 175); mpfr_set_str_binary (x, "0.110010101011010101101000010101010111000110011101001000101011000001100010111001101001011E118"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_gamma (1)\n"); exit (1); } mpfr_set_prec (x, 21); mpfr_set_prec (y, 8); mpfr_set_ui (y, 120, MPFR_RNDN); mpfr_gamma (x, y, MPFR_RNDZ); mpfr_set_prec (y, 21); mpfr_set_str_binary (y, "0.101111101110100110110E654"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_gamma (120)\n"); printf ("Expected "); mpfr_print_binary (y); puts (""); printf ("Got "); mpfr_print_binary (x); puts (""); exit (1); } mpfr_set_prec (x, 3); mpfr_set_prec (y, 206); mpfr_set_str_binary (x, "0.110e10"); inex = mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_prec (x, 206); mpfr_set_str_binary (x, "0.110111100001000001101010010001000111000100000100111000010011100011011111001100011110101000111101101100110001001100110100001001111110000101010000100100011100010011101110000001000010001100010000101001111E6250"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_gamma (768)\n"); exit (1); } if (inex <= 0) { printf ("Wrong flag for mpfr_gamma (768)\n"); exit (1); } /* worst case to exercise retry */ mpfr_set_prec (x, 1000); mpfr_set_prec (y, 869); mpfr_const_pi (x, MPFR_RNDN); mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_prec (x, 4); mpfr_set_prec (y, 4); mpfr_set_str_binary (x, "-0.1100E-66"); mpfr_gamma (y, x, MPFR_RNDN); mpfr_set_str_binary (x, "-0.1011E67"); if (mpfr_cmp (x, y)) { printf ("Error for gamma(-0.1100E-66)\n"); exit (1); } mpfr_clear (x); mpfr_clear (y); }
static void test_large (void) { mpfr_t x, y, z, t; mpfr_init (x); mpfr_init (y); mpfr_init (z); mpfr_init (t); mpfr_set_ui (x, 21, MPFR_RNDN); mpfr_set_ui (y, 28, MPFR_RNDN); mpfr_set_ui (z, 35, MPFR_RNDN); mpfr_mul_2ui (x, x, MPFR_EMAX_DEFAULT-6, MPFR_RNDN); mpfr_mul_2ui (y, y, MPFR_EMAX_DEFAULT-6, MPFR_RNDN); mpfr_mul_2ui (z, z, MPFR_EMAX_DEFAULT-6, MPFR_RNDN); mpfr_hypot (t, x, y, MPFR_RNDN); if (mpfr_cmp (z, t)) { printf ("Error in test_large: got\n"); mpfr_out_str (stdout, 2, 0, t, MPFR_RNDN); printf ("\ninstead of\n"); mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN); printf ("\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_set_prec (t, 53); mpfr_set_prec (y, 53); mpfr_set_str_binary (x, "0.11101100011110000011101000010101010011001101000001100E-1021"); mpfr_set_str_binary (y, "0.11111001010011000001110110001101011100001000010010100E-1021"); mpfr_hypot (t, x, y, MPFR_RNDN); mpfr_set_str_binary (z, "0.101010111100110111101110111110100110010011001010111E-1020"); if (mpfr_cmp (z, t)) { printf ("Error in test_large: got\n"); mpfr_out_str (stdout, 2, 0, t, MPFR_RNDN); printf ("\ninstead of\n"); mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN); printf ("\n"); exit (1); } mpfr_set_prec (x, 240); mpfr_set_prec (y, 22); mpfr_set_prec (z, 2); mpfr_set_prec (t, 2); mpfr_set_str_binary (x, "0.100111011010010010110100000100000001100010011100110101101111111101011110111011011101010110100101111000111100010100110000100101011110111011100110100110100101110101101100011000001100000001111101110100100100011011011010110111100110010101000111e-7"); mpfr_set_str_binary (y, "0.1111000010000011000111E-10"); mpfr_hypot (t, x, y, MPFR_RNDN); mpfr_set_str_binary (z, "0.11E-7"); if (mpfr_cmp (z, t)) { printf ("Error in test_large: got\n"); mpfr_out_str (stdout, 2, 0, t, MPFR_RNDN); printf ("\ninstead of\n"); mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN); printf ("\n"); exit (1); } mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); mpfr_clear (t); }
int mpfr_pow_si (mpfr_ptr y, mpfr_srcptr x, long int n, mp_rnd_t rnd_mode) { if (n > 0) return mpfr_pow_ui(y, x, n, rnd_mode); else { int inexact = 0; if (MPFR_IS_NAN(x)) { MPFR_SET_NAN(y); MPFR_RET_NAN; } MPFR_CLEAR_NAN(y); if (n == 0) return mpfr_set_ui(y, 1, GMP_RNDN); if (MPFR_IS_INF(x)) { MPFR_SET_ZERO(y); if (MPFR_SIGN(x) > 0 || ((unsigned) n & 1) == 0) MPFR_SET_POS(y); else MPFR_SET_NEG(y); MPFR_RET(0); } if (MPFR_IS_ZERO(x)) { MPFR_SET_INF(y); if (MPFR_SIGN(x) > 0 || ((unsigned) n & 1) == 0) MPFR_SET_POS(y); else MPFR_SET_NEG(y); MPFR_RET(0); } MPFR_CLEAR_INF(y); n = -n; /* General case */ { /* Declaration of the intermediary variable */ mpfr_t t, ti; /* Declaration of the size variable */ mp_prec_t Nx = MPFR_PREC(x); /* Precision of input variable */ mp_prec_t Ny = MPFR_PREC(y); /* Precision of input variable */ mp_prec_t Nt; /* Precision of the intermediary variable */ long int err; /* Precision of error */ /* compute the precision of intermediary variable */ Nt=MAX(Nx,Ny); /* the optimal number of bits : see algorithms.ps */ Nt=Nt+3+_mpfr_ceil_log2(Nt); /* initialise of intermediary variable */ mpfr_init(t); mpfr_init(ti); do { /* reactualisation of the precision */ mpfr_set_prec(t,Nt); mpfr_set_prec(ti,Nt); /* compute 1/(x^n) n>0*/ mpfr_pow_ui(ti,x,(unsigned long int)(n),GMP_RNDN); mpfr_ui_div(t,1,ti,GMP_RNDN); /* estimation of the error -- see pow function in algorithms.ps*/ err = Nt - 3; /* actualisation of the precision */ Nt += 10; } while (err<0 || !mpfr_can_round(t,err,GMP_RNDN,rnd_mode,Ny)); inexact = mpfr_set(y,t,rnd_mode); mpfr_clear(t); mpfr_clear(ti); } return inexact; } }
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); }
int main (int argc, char *argv[]) { mpfr_t w,z; unsigned long k; int i; tests_start_mpfr (); mpfr_inits2 (53, w, z, (mpfr_ptr) 0); for (i = 0; i < 3; i++) { mpfr_set_inf (w, 1); test_mul (i, 0, w, w, 10, MPFR_RNDZ); if (!MPFR_IS_INF(w)) { printf ("Result is not Inf (i = %d)\n", i); exit (1); } mpfr_set_nan (w); test_mul (i, 0, w, w, 10, MPFR_RNDZ); if (!MPFR_IS_NAN(w)) { printf ("Result is not NaN (i = %d)\n", i); exit (1); } for (k = 0 ; k < numberof(val) ; k+=3) { mpfr_set_str (w, val[k], 16, MPFR_RNDN); test_mul (i, 0, z, w, 10, MPFR_RNDZ); if (mpfr_cmp_str (z, val[k+1], 16, MPFR_RNDN)) { printf ("ERROR for x * 2^n (i = %d) for %s\n", i, val[k]); printf ("Expected: %s\n" "Got : ", val[k+1]); mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN); putchar ('\n'); exit (1); } test_mul (i, 1, z, w, 10, MPFR_RNDZ); if (mpfr_cmp_str (z, val[k+2], 16, MPFR_RNDN)) { printf ("ERROR for x / 2^n (i = %d) for %s\n", i, val[k]); printf ("Expected: %s\n" "Got : ", val[k+2]); mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN); putchar ('\n'); exit (1); } } mpfr_set_inf (w, 1); mpfr_nextbelow (w); test_mul (i, 0, w, w, 1, MPFR_RNDN); if (!mpfr_inf_p (w)) { printf ("Overflow error (i = %d)!\n", i); exit (1); } mpfr_set_ui (w, 0, MPFR_RNDN); mpfr_nextabove (w); test_mul (i, 1, w, w, 1, MPFR_RNDN); if (mpfr_cmp_ui (w, 0)) { printf ("Underflow error (i = %d)!\n", i); exit (1); } } if (MPFR_EXP_MAX >= LONG_MAX/2 && MPFR_EXP_MIN <= LONG_MAX/2-LONG_MAX-1) { unsigned long lmp1 = (unsigned long) LONG_MAX + 1; mpfr_set_ui (w, 1, MPFR_RNDN); mpfr_mul_2ui (w, w, LONG_MAX/2, MPFR_RNDZ); mpfr_div_2ui (w, w, lmp1, MPFR_RNDZ); mpfr_mul_2ui (w, w, lmp1 - LONG_MAX/2, MPFR_RNDZ); if (!mpfr_cmp_ui (w, 1)) { printf ("Underflow LONG_MAX error!\n"); exit (1); } } mpfr_clears (w, z, (mpfr_ptr) 0); underflow0 (); large0 (); tests_end_mpfr (); return 0; }
int mpfr_fac_ui (mpfr_ptr y, unsigned long int x, mp_rnd_t rnd_mode) { mpfr_t t; /* Variable of Intermediary Calculation*/ unsigned long i; int round, inexact; mp_prec_t Ny; /* Precision of output variable */ mp_prec_t Nt; /* Precision of Intermediary Calculation variable */ mp_prec_t err; /* Precision of error */ mp_rnd_t rnd; MPFR_SAVE_EXPO_DECL (expo); MPFR_ZIV_DECL (loop); /***** test x = 0 and x == 1******/ if (MPFR_UNLIKELY (x <= 1)) return mpfr_set_ui (y, 1, rnd_mode); /* 0! = 1 and 1! = 1 */ MPFR_SAVE_EXPO_MARK (expo); /* Initialisation of the Precision */ Ny = MPFR_PREC (y); /* compute the size of intermediary variable */ Nt = Ny + 2 * MPFR_INT_CEIL_LOG2 (x) + 7; mpfr_init2 (t, Nt); /* initialise of intermediary variable */ rnd = GMP_RNDZ; MPFR_ZIV_INIT (loop, Nt); for (;;) { /* compute factorial */ inexact = mpfr_set_ui (t, 1, rnd); for (i = 2 ; i <= x ; i++) { round = mpfr_mul_ui (t, t, i, rnd); /* assume the first inexact product gives the sign of difference: is that always correct? */ if (inexact == 0) inexact = round; } err = Nt - 1 - MPFR_INT_CEIL_LOG2 (Nt); round = !inexact || mpfr_can_round (t, err, rnd, GMP_RNDZ, Ny + (rnd_mode == GMP_RNDN)); if (MPFR_LIKELY (round)) { /* If inexact = 0, then t is exactly x!, so round is the correct inexact flag. Otherwise, t != x! since we rounded to zero or away. */ round = mpfr_set (y, t, rnd_mode); if (inexact == 0) { inexact = round; break; } else if ((inexact < 0 && round <= 0) || (inexact > 0 && round >= 0)) break; else /* inexact and round have opposite signs: we cannot compute the inexact flag. Restart using the symmetric rounding. */ rnd = (rnd == GMP_RNDZ) ? GMP_RNDU : GMP_RNDZ; } MPFR_ZIV_NEXT (loop, Nt); mpfr_set_prec (t, Nt); } MPFR_ZIV_FREE (loop); mpfr_clear (t); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (y, inexact, rnd_mode); }
static void check_specials (void) { mpfr_t x, y; mpfr_init2 (x, 123L); mpfr_init2 (y, 123L); mpfr_set_nan (x); mpfr_csch (y, x, MPFR_RNDN); if (! mpfr_nan_p (y)) { printf ("Error: csch(NaN) != NaN\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_csch (y, x, MPFR_RNDN); if (! (mpfr_zero_p (y) && MPFR_SIGN (y) >0)) { printf ("Error: csch(+Inf) != +0\n"); exit (1); } mpfr_set_inf (x, -1); mpfr_csch (y, x, MPFR_RNDN); if (! (mpfr_zero_p (y) && MPFR_SIGN (y) <0)) { printf ("Error: csch(-0) != -0\n"); exit (1); } /* csc(+/-0) = +/-Inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_csch (y, x, MPFR_RNDN); if (! (mpfr_inf_p (y) && mpfr_sgn (y) > 0)) { printf ("Error: csch(+0) != +Inf\n"); exit (1); } mpfr_neg (x, x, MPFR_RNDN); mpfr_csch (y, x, MPFR_RNDN); if (! (mpfr_inf_p (y) && mpfr_sgn (y) < 0)) { printf ("Error: csch(-0) != -Inf\n"); exit (1); } /* check huge x */ mpfr_set_str (x, "8e8", 10, MPFR_RNDN); mpfr_csch (y, x, MPFR_RNDN); if (! (mpfr_zero_p (y) && MPFR_SIGN (y) > 0)) { printf ("Error: csch(8e8) != +0\n"); exit (1); } mpfr_set_str (x, "-8e8", 10, MPFR_RNDN); mpfr_csch (y, x, MPFR_RNDN); if (! (mpfr_zero_p (y) && MPFR_SIGN (y) < 0)) { printf ("Error: csch(-8e8) != -0\n"); exit (1); } mpfr_clear (x); mpfr_clear (y); }
static void exprange (void) { mpfr_exp_t emin, emax; mpfr_t x, y, z; int inex1, inex2; unsigned int flags1, flags2; emin = mpfr_get_emin (); emax = mpfr_get_emax (); mpfr_init2 (x, 16); mpfr_inits2 (8, y, z, (mpfr_ptr) 0); mpfr_set_ui_2exp (x, 5, -1, MPFR_RNDN); mpfr_clear_flags (); inex1 = mpfr_gamma (y, x, MPFR_RNDN); flags1 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); mpfr_set_emin (0); mpfr_clear_flags (); inex2 = mpfr_gamma (z, x, MPFR_RNDN); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); mpfr_set_emin (emin); if (inex1 != inex2 || flags1 != flags2 || ! mpfr_equal_p (y, z)) { printf ("Error in exprange (test1)\n"); printf ("x = "); mpfr_dump (x); printf ("Expected inex1 = %d, flags1 = %u, ", SIGN (inex1), flags1); mpfr_dump (y); printf ("Got inex2 = %d, flags2 = %u, ", SIGN (inex2), flags2); mpfr_dump (z); exit (1); } mpfr_set_ui_2exp (x, 32769, -60, MPFR_RNDN); mpfr_clear_flags (); inex1 = mpfr_gamma (y, x, MPFR_RNDD); flags1 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); mpfr_set_emax (45); mpfr_clear_flags (); inex2 = mpfr_gamma (z, x, MPFR_RNDD); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); mpfr_set_emax (emax); if (inex1 != inex2 || flags1 != flags2 || ! mpfr_equal_p (y, z)) { printf ("Error in exprange (test2)\n"); printf ("x = "); mpfr_dump (x); printf ("Expected inex1 = %d, flags1 = %u, ", SIGN (inex1), flags1); mpfr_dump (y); printf ("Got inex2 = %d, flags2 = %u, ", SIGN (inex2), flags2); mpfr_dump (z); exit (1); } mpfr_set_emax (44); mpfr_clear_flags (); inex1 = mpfr_check_range (y, inex1, MPFR_RNDD); flags1 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); mpfr_clear_flags (); inex2 = mpfr_gamma (z, x, MPFR_RNDD); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); mpfr_set_emax (emax); if (inex1 != inex2 || flags1 != flags2 || ! mpfr_equal_p (y, z)) { printf ("Error in exprange (test3)\n"); printf ("x = "); mpfr_dump (x); printf ("Expected inex1 = %d, flags1 = %u, ", SIGN (inex1), flags1); mpfr_dump (y); printf ("Got inex2 = %d, flags2 = %u, ", SIGN (inex2), flags2); mpfr_dump (z); exit (1); } mpfr_set_ui_2exp (x, 1, -60, MPFR_RNDN); mpfr_clear_flags (); inex1 = mpfr_gamma (y, x, MPFR_RNDD); flags1 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); mpfr_set_emax (60); mpfr_clear_flags (); inex2 = mpfr_gamma (z, x, MPFR_RNDD); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); mpfr_set_emax (emax); if (inex1 != inex2 || flags1 != flags2 || ! mpfr_equal_p (y, z)) { printf ("Error in exprange (test4)\n"); printf ("x = "); mpfr_dump (x); printf ("Expected inex1 = %d, flags1 = %u, ", SIGN (inex1), flags1); mpfr_dump (y); printf ("Got inex2 = %d, flags2 = %u, ", SIGN (inex2), flags2); mpfr_dump (z); exit (1); } MPFR_ASSERTN (MPFR_EMIN_MIN == - MPFR_EMAX_MAX); mpfr_set_emin (MPFR_EMIN_MIN); mpfr_set_emax (MPFR_EMAX_MAX); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_nextabove (x); /* x = 2^(emin - 1) */ mpfr_set_inf (y, 1); inex1 = 1; flags1 = MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW; mpfr_clear_flags (); /* MPFR_RNDU: overflow, infinity since 1/x = 2^(emax + 1) */ inex2 = mpfr_gamma (z, x, MPFR_RNDU); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); if (inex1 != inex2 || flags1 != flags2 || ! mpfr_equal_p (y, z)) { printf ("Error in exprange (test5)\n"); printf ("x = "); mpfr_dump (x); printf ("Expected inex1 = %d, flags1 = %u, ", SIGN (inex1), flags1); mpfr_dump (y); printf ("Got inex2 = %d, flags2 = %u, ", SIGN (inex2), flags2); mpfr_dump (z); exit (1); } mpfr_clear_flags (); /* MPFR_RNDN: overflow, infinity since 1/x = 2^(emax + 1) */ inex2 = mpfr_gamma (z, x, MPFR_RNDN); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); if (inex1 != inex2 || flags1 != flags2 || ! mpfr_equal_p (y, z)) { printf ("Error in exprange (test6)\n"); printf ("x = "); mpfr_dump (x); printf ("Expected inex1 = %d, flags1 = %u, ", SIGN (inex1), flags1); mpfr_dump (y); printf ("Got inex2 = %d, flags2 = %u, ", SIGN (inex2), flags2); mpfr_dump (z); exit (1); } mpfr_nextbelow (y); inex1 = -1; mpfr_clear_flags (); /* MPFR_RNDD: overflow, maxnum since 1/x = 2^(emax + 1) */ inex2 = mpfr_gamma (z, x, MPFR_RNDD); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); if (inex1 != inex2 || flags1 != flags2 || ! mpfr_equal_p (y, z)) { printf ("Error in exprange (test7)\n"); printf ("x = "); mpfr_dump (x); printf ("Expected inex1 = %d, flags1 = %u, ", SIGN (inex1), flags1); mpfr_dump (y); printf ("Got inex2 = %d, flags2 = %u, ", SIGN (inex2), flags2); mpfr_dump (z); exit (1); } mpfr_mul_2ui (x, x, 1, MPFR_RNDN); /* x = 2^emin */ mpfr_set_inf (y, 1); inex1 = 1; flags1 = MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW; mpfr_clear_flags (); /* MPFR_RNDU: overflow, infinity since 1/x = 2^emax */ inex2 = mpfr_gamma (z, x, MPFR_RNDU); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); if (inex1 != inex2 || flags1 != flags2 || ! mpfr_equal_p (y, z)) { printf ("Error in exprange (test8)\n"); printf ("x = "); mpfr_dump (x); printf ("Expected inex1 = %d, flags1 = %u, ", SIGN (inex1), flags1); mpfr_dump (y); printf ("Got inex2 = %d, flags2 = %u, ", SIGN (inex2), flags2); mpfr_dump (z); exit (1); } mpfr_clear_flags (); /* MPFR_RNDN: overflow, infinity since 1/x = 2^emax */ inex2 = mpfr_gamma (z, x, MPFR_RNDN); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); if (inex1 != inex2 || flags1 != flags2 || ! mpfr_equal_p (y, z)) { printf ("Error in exprange (test9)\n"); printf ("x = "); mpfr_dump (x); printf ("Expected inex1 = %d, flags1 = %u, ", SIGN (inex1), flags1); mpfr_dump (y); printf ("Got inex2 = %d, flags2 = %u, ", SIGN (inex2), flags2); mpfr_dump (z); exit (1); } mpfr_nextbelow (y); inex1 = -1; flags1 = MPFR_FLAGS_INEXACT; mpfr_clear_flags (); /* MPFR_RNDD: no overflow, maxnum since 1/x = 2^emax and euler > 0 */ inex2 = mpfr_gamma (z, x, MPFR_RNDD); flags2 = __gmpfr_flags; MPFR_ASSERTN (mpfr_inexflag_p ()); if (inex1 != inex2 || flags1 != flags2 || ! mpfr_equal_p (y, z)) { printf ("Error in exprange (test10)\n"); printf ("x = "); mpfr_dump (x); printf ("Expected inex1 = %d, flags1 = %u, ", SIGN (inex1), flags1); mpfr_dump (y); printf ("Got inex2 = %d, flags2 = %u, ", SIGN (inex2), flags2); mpfr_dump (z); exit (1); } mpfr_set_emin (emin); mpfr_set_emax (emax); mpfr_clears (x, y, z, (mpfr_ptr) 0); }
static void check_nans (void) { mpfr_t x, y; int inexact; mpfr_init2 (x, 123); mpfr_init2 (y, 123); /* nan / 1.0 is nan */ mpfr_set_nan (x); mpfr_clear_flags (); inexact = mpfr_div_d (y, x, 1.0, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN ((__gmpfr_flags ^ MPFR_FLAGS_NAN) == 0); MPFR_ASSERTN (mpfr_nan_p (y)); /* +inf / 1.0 == +inf */ mpfr_set_inf (x, 1); mpfr_clear_flags (); inexact = mpfr_div_d (y, x, 1.0, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_POS (y)); /* -inf / 1.0 == -inf */ mpfr_set_inf (x, -1); mpfr_clear_flags (); inexact = mpfr_div_d (y, x, 1.0, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_NEG (y)); /* 0.0 / 0.0 is nan */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_div_d (y, x, 0.0, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN); MPFR_ASSERTN (mpfr_nan_p (y)); /* 1.0 / 0.0 == +inf */ mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_div_d (y, x, 0.0, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_POS (y)); /* -1.0 / 0.0 == -inf */ mpfr_set_si (x, -1, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_div_d (y, x, 0.0, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_NEG (y)); mpfr_clear (x); mpfr_clear (y); }
int main (int argc, char *argv[]) { mpfr_t x, y; tests_start_mpfr (); mpfr_init (x); mpfr_init (y); /* special values */ mpfr_set_nan (x); mpfr_y0 (y, x, GMP_RNDN); MPFR_ASSERTN(mpfr_nan_p (y)); mpfr_set_inf (x, 1); /* +Inf */ mpfr_y0 (y, x, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); mpfr_set_inf (x, -1); /* -Inf */ mpfr_y0 (y, x, GMP_RNDN); MPFR_ASSERTN(mpfr_nan_p (y)); mpfr_set_ui (x, 0, GMP_RNDN); /* +0 */ mpfr_y0 (y, x, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_NEG (y)); /* y0(+0)=-Inf */ mpfr_set_ui (x, 0, GMP_RNDN); mpfr_neg (x, x, GMP_RNDN); /* -0 */ mpfr_y0 (y, x, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_NEG (y)); /* y0(-0)=-Inf */ mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_ui (x, 1, GMP_RNDN); mpfr_y0 (y, x, GMP_RNDN); mpfr_set_str_binary (x, "0.00010110100110000000001000100110111100110101100011011111"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_y0 for x=1, rnd=GMP_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_si (x, -1, GMP_RNDN); mpfr_y0 (y, x, GMP_RNDN); if (!mpfr_nan_p (y)) { printf ("Error in mpfr_y0 for x=-1, rnd=GMP_RNDN\n"); printf ("Expected NaN\n"); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_clear (x); mpfr_clear (y); test_generic (2, 100, 1); data_check ("data/y0", mpfr_y0, "mpfr_y0"); tests_end_mpfr (); return 0; }
int main (void) { mpfr_t x; mp_exp_t emax; tests_start_mpfr (); mpfr_init (x); mpfr_set_nan (x); mpfr_prec_round (x, 2, GMP_RNDN); MPFR_ASSERTN(mpfr_nan_p (x)); mpfr_set_inf (x, 1); mpfr_prec_round (x, 2, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); mpfr_set_inf (x, -1); mpfr_prec_round (x, 2, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) < 0); mpfr_set_ui (x, 0, GMP_RNDN); mpfr_prec_round (x, 2, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_POS(x)); mpfr_set_ui (x, 0, GMP_RNDN); mpfr_neg (x, x, GMP_RNDN); mpfr_prec_round (x, 2, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_NEG(x)); emax = mpfr_get_emax (); set_emax (0); mpfr_set_prec (x, 3); mpfr_set_str_binary (x, "0.111"); mpfr_prec_round (x, 2, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); set_emax (emax); mpfr_set_prec (x, mp_bits_per_limb + 2); mpfr_set_ui (x, 1, GMP_RNDN); mpfr_nextbelow (x); mpfr_prec_round (x, mp_bits_per_limb + 1, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 1) == 0); mpfr_set_prec (x, 3); mpfr_set_ui (x, 5, GMP_RNDN); mpfr_prec_round (x, 2, GMP_RNDN); if (mpfr_cmp_ui(x, 4)) { printf ("Error in tround: got "); mpfr_out_str (stdout, 10, 0, x, GMP_RNDN); printf (" instead of 4\n"); exit (1); } /* check case when reallocation is needed */ mpfr_set_prec (x, 3); mpfr_set_ui (x, 5, GMP_RNDN); /* exact */ mpfr_prec_round (x, mp_bits_per_limb + 1, GMP_RNDN); if (mpfr_cmp_ui(x, 5)) { printf ("Error in tround: got "); mpfr_out_str (stdout, 10, 0, x, GMP_RNDN); printf (" instead of 5\n"); exit (1); } mpfr_clear(x); mpfr_init2 (x, 3); mpfr_set_si (x, -5, GMP_RNDN); /* exact */ mpfr_prec_round (x, mp_bits_per_limb + 1, GMP_RNDN); if (mpfr_cmp_si(x, -5)) { printf ("Error in tround: got "); mpfr_out_str (stdout, 10, 0, x, GMP_RNDN); printf (" instead of -5\n"); exit (1); } /* check case when new precision needs less limbs */ mpfr_set_prec (x, mp_bits_per_limb + 1); mpfr_set_ui (x, 5, GMP_RNDN); /* exact */ mpfr_prec_round (x, 3, GMP_RNDN); /* exact */ if (mpfr_cmp_ui(x, 5)) { printf ("Error in tround: got "); mpfr_out_str (stdout, 10, 0, x, GMP_RNDN); printf (" instead of 5\n"); exit (1); } mpfr_clear(x); tests_end_mpfr (); return 0; }
static void check_specials (void) { mpfr_t x, y; mpfr_init2 (x, 123L); mpfr_init2 (y, 123L); mpfr_set_nan (x); mpfr_sech (y, x, MPFR_RNDN); if (! mpfr_nan_p (y)) { printf ("Error: sech(NaN) != NaN\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_sech (y, x, MPFR_RNDN); if (! (MPFR_IS_ZERO (y) && MPFR_SIGN (y) > 0)) { printf ("Error: sech(+Inf) != +0\n"); exit (1); } mpfr_set_inf (x, -1); mpfr_sech (y, x, MPFR_RNDN); if (! (MPFR_IS_ZERO (y) && MPFR_SIGN (y) > 0)) { printf ("Error: sech(-Inf) != +0\n"); exit (1); } /* sec(+/-0) = 1 */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_sech (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 1)) { printf ("Error: sech(+0) != 1\n"); exit (1); } mpfr_neg (x, x, MPFR_RNDN); mpfr_sech (y, x, MPFR_RNDN); if (mpfr_cmp_ui (y, 1)) { printf ("Error: sech(-0) != 1\n"); exit (1); } /* check huge x */ mpfr_set_str (x, "8e8", 10, MPFR_RNDN); mpfr_sech (y, x, MPFR_RNDN); if (! (mpfr_zero_p (y) && MPFR_SIGN (y) > 0)) { printf ("Error: sech(8e8) != +0\n"); exit (1); } mpfr_set_str (x, "-8e8", 10, MPFR_RNDN); mpfr_sech (y, x, MPFR_RNDN); if (! (mpfr_zero_p (y) && MPFR_SIGN (y) > 0)) { printf ("Error: sech(-8e8) != +0\n"); exit (1); } mpfr_clear (x); mpfr_clear (y); }
int main (int argc, char *argv[]) { mpfr_t x, y; unsigned long k, bd, nc, i; char *str, *str2; mpfr_exp_t e; int base, logbase, prec, baseprec, ret, obase; tests_start_mpfr (); if (argc >= 2) /* tset_str <string> [<prec>] [<ibase>] [<obase>] */ { prec = (argc >= 3) ? atoi (argv[2]) : 53; base = (argc >= 4) ? atoi (argv[3]) : 2; obase = (argc >= 5) ? atoi (argv[4]) : 10; mpfr_init2 (x, prec); mpfr_set_str (x, argv[1], base, MPFR_RNDN); mpfr_out_str (stdout, obase, 0, x, MPFR_RNDN); puts (""); mpfr_clear (x); return 0; } mpfr_init2 (x, 2); nc = (argc > 1) ? atoi(argv[1]) : 53; if (nc < 100) nc = 100; bd = randlimb () & 8; str2 = str = (char*) (*__gmp_allocate_func) (nc); if (bd) { for(k = 1; k <= bd; k++) *(str2++) = (randlimb () & 1) + '0'; } else *(str2++) = '0'; *(str2++) = '.'; for (k = 1; k < nc - 17 - bd; k++) *(str2++) = '0' + (char) (randlimb () & 1); *(str2++) = 'e'; sprintf (str2, "%d", (int) (randlimb () & INT_MAX) + INT_MIN/2); mpfr_set_prec (x, nc + 10); mpfr_set_str_binary (x, str); mpfr_set_prec (x, 54); mpfr_set_str_binary (x, "0.100100100110110101001010010101111000001011100100101010E-529"); mpfr_init2 (y, 54); mpfr_set_str (y, "4.936a52bc17254@-133", 16, MPFR_RNDN); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (1a):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str_binary (x, "0.111111101101110010111010100110000111011001010100001101E-529"); mpfr_set_str (y, "0.fedcba98765434P-529", 16, MPFR_RNDN); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (1b):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } (*__gmp_free_func) (str, nc); mpfr_set_prec (x, 53); mpfr_set_str_binary (x, "+110101100.01010000101101000000100111001000101011101110E00"); mpfr_set_str_binary (x, "1.0"); if (mpfr_cmp_ui (x, 1)) { printf ("Error in mpfr_set_str_binary for s=1.0\n"); mpfr_clear(x); mpfr_clear(y); exit(1); } mpfr_set_str_binary (x, "+0000"); mpfr_set_str_binary (x, "+0000E0"); mpfr_set_str_binary (x, "0000E0"); if (mpfr_cmp_ui (x, 0)) { printf ("Error in mpfr_set_str_binary for s=0.0\n"); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (x, "+243495834958.53452345E1", 10, MPFR_RNDN); mpfr_set_str (x, "9007199254740993", 10, MPFR_RNDN); mpfr_set_str (x, "9007199254740992", 10, MPFR_RNDU); mpfr_set_str (x, "9007199254740992", 10, MPFR_RNDD); mpfr_set_str (x, "9007199254740992", 10, MPFR_RNDZ); /* check a random number printed and read is not modified */ prec = 53; mpfr_set_prec (x, prec); mpfr_set_prec (y, prec); for (i=0;i<N;i++) { mpfr_rnd_t rnd; mpfr_urandomb (x, RANDS); rnd = RND_RAND (); logbase = (randlimb () % 5) + 1; base = 1 << logbase; /* Warning: the number of bits needed to print exactly a number of 'prec' bits in base 2^logbase may be greater than ceil(prec/logbase), for example 0.11E-1 in base 2 cannot be written exactly with only one digit in base 4 */ if (base == 2) baseprec = prec; else baseprec = 1 + (prec - 2 + logbase) / logbase; str = mpfr_get_str (NULL, &e, base, baseprec, x, rnd); mpfr_set_str (y, str, base, rnd); MPFR_EXP(y) += logbase * (e - strlen (str)); if (mpfr_cmp (x, y)) { printf ("mpfr_set_str o mpfr_get_str <> id for rnd_mode=%s\n", mpfr_print_rnd_mode (rnd)); printf ("x="); mpfr_print_binary (x); puts (""); printf ("s=%s, exp=%d, base=%d\n", str, (int) e, base); printf ("y="); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } (*__gmp_free_func) (str, strlen (str) + 1); } for (i = 2; i <= 62; i++) { if (mpfr_set_str (x, "@NaN@(garbage)", i, MPFR_RNDN) != 0 || !mpfr_nan_p(x)) { printf ("mpfr_set_str failed on @NaN@(garbage)\n"); exit (1); } /* if (mpfr_set_str (x, "@Inf@garbage", i, MPFR_RNDN) != 0 || !mpfr_inf_p(x) || MPFR_SIGN(x) < 0) { printf ("mpfr_set_str failed on @Inf@garbage\n"); exit (1); } if (mpfr_set_str (x, "-@Inf@garbage", i, MPFR_RNDN) != 0 || !mpfr_inf_p(x) || MPFR_SIGN(x) > 0) { printf ("mpfr_set_str failed on -@Inf@garbage\n"); exit (1); } if (mpfr_set_str (x, "+@Inf@garbage", i, MPFR_RNDN) != 0 || !mpfr_inf_p(x) || MPFR_SIGN(x) < 0) { printf ("mpfr_set_str failed on +@Inf@garbage\n"); exit (1); } */ if (i > 16) continue; if (mpfr_set_str (x, "NaN", i, MPFR_RNDN) != 0 || !mpfr_nan_p(x)) { printf ("mpfr_set_str failed on NaN\n"); exit (1); } if (mpfr_set_str (x, "Inf", i, MPFR_RNDN) != 0 || !mpfr_inf_p(x) || MPFR_SIGN(x) < 0) { printf ("mpfr_set_str failed on Inf\n"); exit (1); } if (mpfr_set_str (x, "-Inf", i, MPFR_RNDN) != 0 || !mpfr_inf_p(x) || MPFR_SIGN(x) > 0) { printf ("mpfr_set_str failed on -Inf\n"); exit (1); } if (mpfr_set_str (x, "+Inf", i, MPFR_RNDN) != 0 || !mpfr_inf_p(x) || MPFR_SIGN(x) < 0) { printf ("mpfr_set_str failed on +Inf\n"); exit (1); } } /* check that mpfr_set_str works for uppercase letters too */ mpfr_set_prec (x, 10); mpfr_set_str (x, "B", 16, MPFR_RNDN); if (mpfr_cmp_ui (x, 11) != 0) { printf ("mpfr_set_str does not work for uppercase letters\n"); exit (1); } /* start of tests added by Alain Delplanque */ /* in this example an overflow can occur */ mpfr_set_prec (x, 64); mpfr_set_prec (y, 64); mpfr_set_str_binary (x, "1.0E-532"); mpfr_set_str (y, "0.71128279983522479470@-160", 10, MPFR_RNDU); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (2):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } /* in this example, I think there was a pb in the old function : result of mpfr_set_str_old for the same number , but with more precision is: 1.111111111110000000000000000111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100111000100001100000010101100111010e184 this result is the same as mpfr_set_str */ mpfr_set_prec (x, 64); mpfr_set_prec (y, 64); mpfr_set_str_binary (x, "1.111111111110000000000000000111111111111111111111111110000000001E184"); mpfr_set_str (y, "0.jo08hg31hc5mmpj5mjjmgn55p2h35g@39", 27, MPFR_RNDU); /* y = 49027884868983130654865109690613178467841148597221480052 */ if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (3):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } /* not exact rounding in mpfr_set_str same number with more precision is : 1.111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011011111101000001101110110010101101000010100110011101110010001110e195 this result is the same as mpfr_set_str */ /* problem was : can_round was call with MPFR_RNDN round mode, so can_round use an error : 1/2 * 2^err * ulp(y) instead of 2^err * ulp(y) I have increase err by 1 */ mpfr_set_prec (x, 64); /* it was round down instead of up */ mpfr_set_prec (y, 64); mpfr_set_str_binary (x, "1.111111111111111111111111111000000000000000000000000000000000001e195"); mpfr_set_str (y, "0.6e23ekb6acgh96abk10b6c9f2ka16i@45", 21, MPFR_RNDU); /* y = 100433627392042473064661483711179345482301462325708736552078 */ if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (4):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } /* may be an error in mpfr_set_str_old with more precision : 1.111111100000001111110000000000011111011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110111101010001110111011000010111001011100110110e180 */ mpfr_set_prec (x, 64); /* it was round down instead of up */ mpfr_set_prec (y, 64); mpfr_set_str_binary (x, "1.111111100000001111110000000000011111011111111111111111111111111e180"); mpfr_set_str (y, "0.10j8j2k82ehahha56390df0a1de030@41", 23, MPFR_RNDZ); /* y = 3053110535624388280648330929253842828159081875986159414 */ if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (5):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_prec (x, 64); mpfr_set_prec (y, 64); mpfr_set_str (y, "0.jrchfhpp9en7hidqm9bmcofid9q3jg@39", 28, MPFR_RNDU); /* y = 196159429139499688661464718784226062699788036696626429952 */ mpfr_set_str_binary (x, "0.1111111111111111111111111111111000000000000011100000001111100001E187"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (6):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_prec (x, 64); mpfr_set_prec (y, 64); mpfr_set_str (y, "0.h148m5ld5cf8gk1kd70b6ege92g6ba@47", 24, MPFR_RNDZ); /* y = 52652933527468502324759448399183654588831274530295083078827114496 */ mpfr_set_str_binary (x, "0.1111111111111100000000001000000000000000000011111111111111101111E215"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (7):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } /* worst cases for rounding to nearest in double precision */ mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_str (y, "5e125", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.10111101000101110110011000100000101001010000000111111E418"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (8):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (y, "69e267", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.10000101101111100101101100000110010011001010011011010E894"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (9):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (y, "623e100", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.10110010000001010011000101111001110101000001111011111E342"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (10):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (y, "3571e263", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.10110001001100100010011000110000111010100000110101010E886"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (11):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (y, "75569e-254", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.10101101001000110001011011001000111000110101010110011E-827"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (12):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (y, "920657e-23", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.10101001110101001100110000101110110111101111001101100E-56"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (13):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (y, "9210917e80", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.11101101000100011001000110100011111100110000000110010E289"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (14):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (y, "87575437e-309", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.11110000001110011001000000110000000100000010101101100E-1000"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (15):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (y, "245540327e122", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.10001101101100010001100011110000110001100010111001011E434"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (16):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (y, "491080654e122", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.10001101101100010001100011110000110001100010111001011E435"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (17):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } mpfr_set_str (y, "83356057653e193", 10, MPFR_RNDN); mpfr_set_str_binary (x, "0.10101010001001110011011011010111011100010101000011000E678"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_set_str (18):\n"); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); mpfr_clear (x); mpfr_clear (y); exit (1); } CHECK53(y, "83356057653e193", MPFR_RNDN, x, "0.10101010001001110011011011010111011100010101000011000E678", 18); CHECK53(y, "619534293513e124", MPFR_RNDN, x, "0.10001000011000010000000110000001111111110000011110001e452", 19); CHECK53(y, "3142213164987e-294", MPFR_RNDN, x, "0.11101001101000000100111011111101111001010001001101111e-935", 20); CHECK53(y, "36167929443327e-159", MPFR_RNDN, x, "0.11100111001110111110000101011001100110010100011111100e-483", 21); CHECK53(y, "904198236083175e-161", MPFR_RNDN, x, "0.11100111001110111110000101011001100110010100011111100e-485", 22); CHECK53(y, "3743626360493413e-165", MPFR_RNDN, x, "0.11000100000100011101001010111101011011011111011111001e-496", 23); CHECK53(y, "94080055902682397e-242", MPFR_RNDN, x, "0.10110010010011000000111100011100111100110011011001010e-747", 24); CHECK53(y, "7e-303", MPFR_RNDD, x, "0.10011001100111001000100110001110001000110111110001011e-1003", 25); CHECK53(y, "7e-303", MPFR_RNDU, x, "0.10011001100111001000100110001110001000110111110001100e-1003", 26); CHECK53(y, "93e-234", MPFR_RNDD, x, "0.10010011110110010111001001111001000010000000001110101E-770", 27); CHECK53(y, "93e-234", MPFR_RNDU, x, "0.10010011110110010111001001111001000010000000001110110E-770", 28); CHECK53(y, "755e174", MPFR_RNDD, x, "0.10111110110010011000110010011111101111000111111000101E588", 29); CHECK53(y, "755e174", MPFR_RNDU, x, "0.10111110110010011000110010011111101111000111111000110E588", 30); CHECK53(y, "8699e-276", MPFR_RNDD, x, "0.10010110100101101111100100100011011101100110100101100E-903", 31); CHECK53(y, "8699e-276", MPFR_RNDU, x, "0.10010110100101101111100100100011011101100110100101101E-903", 32); CHECK53(y, "82081e41", MPFR_RNDD, x, "0.10111000000010000010111011111001111010100011111001011E153", 33); CHECK53(y, "82081e41", MPFR_RNDU, x, "0.10111000000010000010111011111001111010100011111001100E153", 34); CHECK53(y, "584169e229", MPFR_RNDD, x, "0.11101011001010111000001011001110111000111100110101010E780", 35); CHECK53(y, "584169e229", MPFR_RNDU, x, "0.11101011001010111000001011001110111000111100110101011E780", 36); CHECK53(y, "5783893e-128", MPFR_RNDD, x, "0.10011000111100000110011110000101100111110011101110100E-402", 37); CHECK53(y, "5783893e-128", MPFR_RNDU, x, "0.10011000111100000110011110000101100111110011101110101E-402", 38); CHECK53(y, "87575437e-310", MPFR_RNDD, x, "0.11000000001011100000110011110011010000000010001010110E-1003", 39); CHECK53(y, "87575437e-310", MPFR_RNDU, x, "0.11000000001011100000110011110011010000000010001010111E-1003", 40); CHECK53(y, "245540327e121", MPFR_RNDD, x, "0.11100010101101001111010010110100011100000100101000100E430", 41); CHECK53(y, "245540327e121", MPFR_RNDU, x, "0.11100010101101001111010010110100011100000100101000101E430", 42); CHECK53(y, "9078555839e-109", MPFR_RNDD, x, "0.11111110001010111010110000110011100110001010011101101E-329", 43); CHECK53(y, "9078555839e-109", MPFR_RNDU, x, "0.11111110001010111010110000110011100110001010011101110E-329", 44); CHECK53(y, "42333842451e201", MPFR_RNDD, x, "0.10000000110001001101000100110110111110101011101011111E704", 45); CHECK53(y, "42333842451e201", MPFR_RNDU, x, "0.10000000110001001101000100110110111110101011101100000E704", 46); CHECK53(y, "778380362293e218", MPFR_RNDD, x, "0.11001101010111000001001100001100110010000001010010010E764", 47); CHECK53(y, "778380362293e218", MPFR_RNDU, x, "0.11001101010111000001001100001100110010000001010010011E764", 48); CHECK53(y, "7812878489261e-179", MPFR_RNDD, x, "0.10010011011011010111001111011101111101101101001110100E-551", 49); CHECK53(y, "7812878489261e-179", MPFR_RNDU, x, "0.10010011011011010111001111011101111101101101001110101E-551", 50); CHECK53(y, "77003665618895e-73", MPFR_RNDD, x, "0.11000101111110111111001111111101001101111000000101001E-196", 51); CHECK53(y, "77003665618895e-73", MPFR_RNDU, x, "0.11000101111110111111001111111101001101111000000101010E-196", 52); CHECK53(y, "834735494917063e-300", MPFR_RNDD, x, "0.11111110001101100001001101111100010011001110111010001E-947", 53); CHECK53(y, "834735494917063e-300", MPFR_RNDU, x, "0.11111110001101100001001101111100010011001110111010010E-947", 54); CHECK53(y, "6182410494241627e-119", MPFR_RNDD, x, "0.10001101110010110010001011000010001000101110100000111E-342", 55); CHECK53(y, "6182410494241627e-119", MPFR_RNDU, x, "0.10001101110010110010001011000010001000101110100001000E-342", 56); CHECK53(y, "26153245263757307e49", MPFR_RNDD, x, "0.10011110111100000000001011011110101100010000011011110E218", 57); CHECK53(y, "26153245263757307e49", MPFR_RNDU, x, "0.10011110111100000000001011011110101100010000011011111E218", 58); /* to check this problem : I convert limb (10--0 or 101--1) into base b with more than mp_bits_per_limb digits, so when convert into base 2 I should have the limb that I have choose */ /* this use mpfr_get_str */ { size_t nb_digit = mp_bits_per_limb; mp_limb_t check_limb[2] = {MPFR_LIMB_HIGHBIT, ~(MPFR_LIMB_HIGHBIT >> 1)}; int base[3] = {10, 16, 19}; mpfr_rnd_t rnd[3] = {MPFR_RNDU, MPFR_RNDN, MPFR_RNDD}; int cbase, climb, crnd; char *str; mpfr_set_prec (x, mp_bits_per_limb); /* x and y have only one limb */ mpfr_set_prec (y, mp_bits_per_limb); str = (char*) (*__gmp_allocate_func) (N + 20); mpfr_set_ui (x, 1, MPFR_RNDN); /* ensures that x is not NaN or Inf */ for (; nb_digit < N; nb_digit *= 10) for (cbase = 0; cbase < 3; cbase++) for (climb = 0; climb < 2; climb++) for (crnd = 0; crnd < 3; crnd++) { char *str1; mpfr_exp_t exp; *(MPFR_MANT(x)) = check_limb[climb]; MPFR_EXP(x) = 0; mpfr_get_str (str + 2, &exp, base[cbase], nb_digit, x, rnd[crnd]); str[0] = '-'; str[(str[2] == '-')] = '0'; str[(str[2] == '-') + 1] = '.'; for (str1 = str; *str1 != 0; str1++) ; sprintf (str1, "@%i", (int) exp); mpfr_set_str (y, str, base[cbase], rnd[2 - crnd]); if (mpfr_cmp (x, y) != 0) { printf ("Error in mpfr_set_str for nb_digit=%u, base=%d, " "rnd=%s:\n", (unsigned int) nb_digit, base[cbase], mpfr_print_rnd_mode (rnd[crnd])); printf ("instead of: "); mpfr_print_binary (x); puts (""); printf ("return : "); mpfr_print_binary (y); puts (""); exit (1); } } (*__gmp_free_func) (str, N + 20); } /* end of tests added by Alain Delplanque */ /* check that flags are correctly cleared */ mpfr_set_nan (x); mpfr_set_str (x, "+0.0", 10, MPFR_RNDN); if (!mpfr_number_p(x) || mpfr_cmp_ui (x, 0) != 0 || mpfr_sgn (x) < 0) { printf ("x <- +0.0 failed after x=NaN\n"); exit (1); } mpfr_set_str (x, "-0.0", 10, MPFR_RNDN); if (!mpfr_number_p(x) || mpfr_cmp_ui (x, 0) != 0 || mpfr_sgn (x) > 0) { printf ("x <- -0.0 failed after x=NaN\n"); exit (1); } /* check invalid input */ ret = mpfr_set_str (x, "1E10toto", 10, MPFR_RNDN); MPFR_ASSERTN (ret == -1); ret = mpfr_set_str (x, "1p10toto", 16, MPFR_RNDN); MPFR_ASSERTN (ret == -1); ret = mpfr_set_str (x, "", 16, MPFR_RNDN); MPFR_ASSERTN (ret == -1); ret = mpfr_set_str (x, "+", 16, MPFR_RNDN); MPFR_ASSERTN (ret == -1); ret = mpfr_set_str (x, "-", 16, MPFR_RNDN); MPFR_ASSERTN (ret == -1); ret = mpfr_set_str (x, "this_is_an_invalid_number_in_base_36", 36, MPFR_RNDN); MPFR_ASSERTN (ret == -1); ret = mpfr_set_str (x, "1.2.3", 10, MPFR_RNDN); MPFR_ASSERTN (ret == -1); mpfr_set_prec (x, 135); ret = mpfr_set_str (x, "thisisavalidnumberinbase36", 36, MPFR_RNDN); mpfr_set_prec (y, 135); mpfr_set_str (y, "23833565676460972739462619524519814462546", 10, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp (x, y) == 0 && ret == 0); /* coverage test for set_str_binary */ mpfr_set_str_binary (x, "NaN"); MPFR_ASSERTN(mpfr_nan_p (x)); mpfr_set_str_binary (x, "Inf"); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); mpfr_set_str_binary (x, "+Inf"); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); mpfr_set_str_binary (x, "-Inf"); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) < 0); mpfr_set_prec (x, 3); mpfr_set_str_binary (x, "0.01E2"); MPFR_ASSERTN(mpfr_cmp_ui (x, 1) == 0); mpfr_set_str_binary (x, "-0.01E2"); MPFR_ASSERTN(mpfr_cmp_si (x, -1) == 0); mpfr_clear (x); mpfr_clear (y); check_underflow (); bug20081028 (); tests_end_mpfr (); return 0; }
int main (int argc, char *argv[]) { mpfr_t x; mpfr_prec_t ret; unsigned long i; tests_start_mpfr (); mpfr_init2 (x, 53); /* Check special values */ mpfr_set_nan (x); ret = mpfr_min_prec (x); MPFR_ASSERTN (ret == 0); mpfr_set_inf (x, 1); ret = mpfr_min_prec (x); MPFR_ASSERTN (ret == 0); mpfr_set_inf (x, -1); ret = mpfr_min_prec (x); MPFR_ASSERTN (ret == 0); mpfr_set_ui (x, 0, MPFR_RNDN); ret = mpfr_min_prec (x); MPFR_ASSERTN (ret == 0); /* Some constants */ mpfr_set_ui (x, 1, MPFR_RNDN); ret = mpfr_min_prec (x); MPFR_ASSERTN (ret == 1); mpfr_set_ui (x, 17, MPFR_RNDN); ret = mpfr_min_prec (x); MPFR_ASSERTN (ret == 5); mpfr_set_ui (x, 42, MPFR_RNDN); ret = mpfr_min_prec (x); MPFR_ASSERTN (ret == 5); mpfr_set_prec (x, 256); for (i = 0; i <= 255; i++) { mpfr_set_ui_2exp (x, 1, i, MPFR_RNDN); mpfr_add_ui (x, x, 1, MPFR_RNDN); ret = mpfr_min_prec (x); if (ret != i + 1) { printf ("Error for x = 2^%lu + 1\n", i); printf ("Expected %lu, got %lu\n", i + 1, (unsigned long) ret); exit (1); } } for (i = MPFR_PREC_MIN; i <= 255; i++) { mpfr_set_prec (x, i); mpfr_set_ui_2exp (x, 1, i, MPFR_RNDN); mpfr_sub_ui (x, x, 1, MPFR_RNDN); ret = mpfr_min_prec (x); if (ret != i) { printf ("Error for x = 2^%lu - 1\n", i); printf ("Expected %lu, got %lu\n", i, (unsigned long) ret); exit (1); } } mpfr_clear (x); tests_end_mpfr (); return 0; }
static void special (void) { mpfr_t x, y; int inex; mpfr_init (x); mpfr_init (y); mpfr_set_nan (x); mpfr_lngamma (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error for lngamma(NaN)\n"); exit (1); } mpfr_set_inf (x, -1); mpfr_lngamma (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error for lngamma(-Inf)\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_lngamma (y, x, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error for lngamma(+Inf)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_lngamma (y, x, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error for lngamma(+0)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_lngamma (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error for lngamma(-0)\n"); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_lngamma (y, x, MPFR_RNDN); if (MPFR_IS_NAN (y) || mpfr_cmp_ui (y, 0) || MPFR_IS_NEG (y)) { printf ("Error for lngamma(1)\n"); exit (1); } mpfr_set_si (x, -1, MPFR_RNDN); mpfr_lngamma (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error for lngamma(-1)\n"); exit (1); } mpfr_set_ui (x, 2, MPFR_RNDN); mpfr_lngamma (y, x, MPFR_RNDN); if (MPFR_IS_NAN (y) || mpfr_cmp_ui (y, 0) || MPFR_IS_NEG (y)) { printf ("Error for lngamma(2)\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); #define CHECK_X1 "1.0762904832837976166" #define CHECK_Y1 "-0.039418362817587634939" mpfr_set_str (x, CHECK_X1, 10, MPFR_RNDN); mpfr_lngamma (y, x, MPFR_RNDN); mpfr_set_str (x, CHECK_Y1, 10, MPFR_RNDN); if (MPFR_IS_NAN (y) || mpfr_cmp (y, x)) { printf ("mpfr_lngamma("CHECK_X1") is wrong:\n" "expected "); mpfr_print_binary (x); putchar ('\n'); printf ("got "); mpfr_print_binary (y); putchar ('\n'); exit (1); } #define CHECK_X2 "9.23709516716202383435e-01" #define CHECK_Y2 "0.049010669407893718563" mpfr_set_str (x, CHECK_X2, 10, MPFR_RNDN); mpfr_lngamma (y, x, MPFR_RNDN); mpfr_set_str (x, CHECK_Y2, 10, MPFR_RNDN); if (MPFR_IS_NAN (y) || mpfr_cmp (y, x)) { printf ("mpfr_lngamma("CHECK_X2") is wrong:\n" "expected "); mpfr_print_binary (x); putchar ('\n'); printf ("got "); mpfr_print_binary (y); putchar ('\n'); exit (1); } mpfr_set_prec (x, 8); mpfr_set_prec (y, 175); mpfr_set_ui (x, 33, MPFR_RNDN); mpfr_lngamma (y, x, MPFR_RNDU); mpfr_set_prec (x, 175); mpfr_set_str_binary (x, "0.1010001100011101101011001101110010100001000001000001110011000001101100001111001001000101011011100100010101011110100111110101010100010011010010000101010111001100011000101111E7"); if (MPFR_IS_NAN (y) || mpfr_cmp (x, y)) { printf ("Error in mpfr_lngamma (1)\n"); exit (1); } mpfr_set_prec (x, 21); mpfr_set_prec (y, 8); mpfr_set_ui (y, 120, MPFR_RNDN); mpfr_lngamma (x, y, MPFR_RNDZ); mpfr_set_prec (y, 21); mpfr_set_str_binary (y, "0.111000101000001100101E9"); if (MPFR_IS_NAN (x) || mpfr_cmp (x, y)) { printf ("Error in mpfr_lngamma (120)\n"); printf ("Expected "); mpfr_print_binary (y); puts (""); printf ("Got "); mpfr_print_binary (x); puts (""); exit (1); } mpfr_set_prec (x, 3); mpfr_set_prec (y, 206); mpfr_set_str_binary (x, "0.110e10"); inex = mpfr_lngamma (y, x, MPFR_RNDN); mpfr_set_prec (x, 206); mpfr_set_str_binary (x, "0.10000111011000000011100010101001100110001110000111100011000100100110110010001011011110101001111011110110000001010100111011010000000011100110110101100111000111010011110010000100010111101010001101000110101001E13"); if (MPFR_IS_NAN (y) || mpfr_cmp (x, y)) { printf ("Error in mpfr_lngamma (768)\n"); exit (1); } if (inex >= 0) { printf ("Wrong flag for mpfr_lngamma (768)\n"); exit (1); } mpfr_set_prec (x, 4); mpfr_set_prec (y, 4); mpfr_set_str_binary (x, "0.1100E-66"); mpfr_lngamma (y, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.1100E6"); if (MPFR_IS_NAN (y) || mpfr_cmp (x, y)) { printf ("Error for lngamma(0.1100E-66)\n"); exit (1); } mpfr_set_prec (x, 256); mpfr_set_prec (y, 32); mpfr_set_si_2exp (x, -1, 200, MPFR_RNDN); mpfr_add_ui (x, x, 1, MPFR_RNDN); mpfr_div_2ui (x, x, 1, MPFR_RNDN); mpfr_lngamma (y, x, MPFR_RNDN); mpfr_set_prec (x, 32); mpfr_set_str_binary (x, "-0.10001000111011111011000010100010E207"); if (MPFR_IS_NAN (y) || mpfr_cmp (x, y)) { printf ("Error for lngamma(-2^199+0.5)\n"); printf ("Got "); mpfr_dump (y); printf ("instead of "); mpfr_dump (x); exit (1); } mpfr_set_prec (x, 256); mpfr_set_prec (y, 32); mpfr_set_si_2exp (x, -1, 200, MPFR_RNDN); mpfr_sub_ui (x, x, 1, MPFR_RNDN); mpfr_div_2ui (x, x, 1, MPFR_RNDN); mpfr_lngamma (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error for lngamma(-2^199-0.5)\n"); exit (1); } mpfr_clear (x); mpfr_clear (y); }
static void special (void) { mpfr_t x, y; unsigned xprec, yprec; mpfr_init (x); mpfr_init (y); mpfr_set_prec (x, 32); mpfr_set_prec (y, 32); mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_div_ui (y, x, 3, MPFR_RNDN); mpfr_set_prec (x, 100); mpfr_set_prec (y, 100); mpfr_urandomb (x, RANDS); mpfr_div_ui (y, x, 123456, MPFR_RNDN); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_div_ui (y, x, 123456789, MPFR_RNDN); if (mpfr_cmp_ui (y, 0)) { printf ("mpfr_div_ui gives non-zero for 0/ui\n"); exit (1); } /* bug found by Norbert Mueller, 21 Aug 2001 */ mpfr_set_prec (x, 110); mpfr_set_prec (y, 60); mpfr_set_str_binary (x, "0.110101110011111110011111001110011001110111000000111110001000111011000011E-44"); mpfr_div_ui (y, x, 17, MPFR_RNDN); mpfr_set_str_binary (x, "0.11001010100101100011101110000001100001010110101001010011011E-48"); if (mpfr_cmp (x, y)) { printf ("Error in x/17 for x=1/16!\n"); printf ("Expected "); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); printf ("\nGot "); mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); printf ("\n"); exit (1); } /* corner case */ mpfr_set_prec (x, 2 * mp_bits_per_limb); mpfr_set_prec (y, 2); mpfr_set_ui (x, 4, MPFR_RNDN); mpfr_nextabove (x); mpfr_div_ui (y, x, 2, MPFR_RNDN); /* exactly in the middle */ MPFR_ASSERTN(mpfr_cmp_ui (y, 2) == 0); (mpfr_div_ui) (y, x, 2, MPFR_RNDN); /* exactly in the middle */ MPFR_ASSERTN(mpfr_cmp_ui (y, 2) == 0); mpfr_set_prec (x, 3 * mp_bits_per_limb); mpfr_set_prec (y, 2); mpfr_set_ui (x, 2, MPFR_RNDN); mpfr_nextabove (x); mpfr_div_ui (y, x, 2, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); (mpfr_div_ui) (y, x, 2, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); mpfr_set_prec (x, 3 * mp_bits_per_limb); mpfr_set_prec (y, 2); mpfr_set_si (x, -4, MPFR_RNDN); mpfr_nextbelow (x); mpfr_div_ui (y, x, 2, MPFR_RNDD); MPFR_ASSERTN(mpfr_cmp_si (y, -3) == 0); (mpfr_div_ui) (y, x, 2, MPFR_RNDD); MPFR_ASSERTN(mpfr_cmp_si (y, -3) == 0); for (xprec = 53; xprec <= 128; xprec++) { mpfr_set_prec (x, xprec); mpfr_set_str_binary (x, "0.1100100100001111110011111000000011011100001100110111E2"); for (yprec = 53; yprec <= 128; yprec++) { mpfr_set_prec (y, yprec); mpfr_div_ui (y, x, 1, MPFR_RNDN); if (mpfr_cmp(x,y)) { printf ("division by 1.0 fails for xprec=%u, yprec=%u\n", xprec, yprec); printf ("expected "); mpfr_dump (x); printf ("got "); mpfr_dump (y); exit (1); } } } /* Bug reported by Mark Dickinson, 6 Nov 2007 */ mpfr_set_si (x, 0, MPFR_RNDN); mpfr_set_si (y, -1, MPFR_RNDN); mpfr_div_ui (y, x, 4, MPFR_RNDN); MPFR_ASSERTN(MPFR_IS_ZERO(y) && MPFR_IS_POS(y)); (mpfr_div_ui) (y, x, 4, MPFR_RNDN); MPFR_ASSERTN(MPFR_IS_ZERO(y) && MPFR_IS_POS(y)); mpfr_clear (x); mpfr_clear (y); }
static void check_special (void) { mpfr_t x, y; int res; char *s; mpfr_init (x); mpfr_init (y); /* Check dummy case */ res = mpfr_strtofr (x, "1234567.89E1", NULL, 10, MPFR_RNDN); mpfr_set_str (y, "1234567.89E1", 10, MPFR_RNDN); if (mpfr_cmp (x, y)) { printf ("Results differ between strtofr and set_str.\n" " set_str gives: "); mpfr_dump (y); printf (" strtofr gives: "); mpfr_dump (x); exit (1); } /* Check NAN */ mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */ res = mpfr_strtofr (x, "NaN", &s, 10, MPFR_RNDN); if (res != 0 || !mpfr_nan_p (x) || *s != 0) { printf ("Error for setting NAN (1)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */ res = mpfr_strtofr (x, "+NaN", &s, 10, MPFR_RNDN); if (res != 0 || !mpfr_nan_p (x) || *s != 0) { printf ("Error for setting +NAN (1)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */ res = mpfr_strtofr (x, " -NaN", &s, 10, MPFR_RNDN); if (res != 0 || !mpfr_nan_p (x) || *s != 0) { printf ("Error for setting -NAN (1)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */ res = mpfr_strtofr (x, "@nAn@xx", &s, 16, MPFR_RNDN); if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "xx") ) { printf ("Error for setting NAN (2)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */ res = mpfr_strtofr (x, "NAN(abcdEDF__1256)Hello", &s, 10, MPFR_RNDN); if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "Hello") ) { printf ("Error for setting NAN (3)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */ res = mpfr_strtofr (x, "NAN(abcdEDF)__1256)Hello", &s, 10, MPFR_RNDN); if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "__1256)Hello") ) { printf ("Error for setting NAN (4)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */ res = mpfr_strtofr (x, "NAN(abc%dEDF)__1256)Hello", &s, 10, MPFR_RNDN); if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "(abc%dEDF)__1256)Hello") ) { printf ("Error for setting NAN (5)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */ res = mpfr_strtofr (x, "NAN((abc))", &s, 10, MPFR_RNDN); if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "((abc))") ) { printf ("Error for setting NAN (6)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); /* make sure that x is modified */ res = mpfr_strtofr (x, "NAN()foo", &s, 10, MPFR_RNDN); if (res != 0 || !mpfr_nan_p (x) || strcmp(s, "foo") ) { printf ("Error for setting NAN (7)\n"); exit (1); } /* Check INF */ res = mpfr_strtofr (x, "INFINITY", &s, 8, MPFR_RNDN); if (res != 0 || !mpfr_inf_p (x) || *s != 0) { printf ("Error for setting INFINITY (1)\n s=%s\n x=", s); mpfr_dump (x); exit (1); } res = mpfr_strtofr (x, "INFANITY", &s, 8, MPFR_RNDN); if (res != 0 || !mpfr_inf_p (x) || strcmp(s, "ANITY")) { printf ("Error for setting INFINITY (2)\n s=%s\n x=", s); mpfr_dump (x); exit (1); } res = mpfr_strtofr (x, "@INF@*2", &s, 11, MPFR_RNDN); if (res != 0 || !mpfr_inf_p (x) || strcmp(s, "*2")) { printf ("Error for setting INFINITY (3)\n s=%s\n x=", s); mpfr_dump (x); exit (1); } /* Check Zero */ res = mpfr_strtofr (x, " 00000", &s, 11, MPFR_RNDN); if (res != 0 || !mpfr_zero_p (x) || s[0] != 0) { printf ("Error for setting ZERO (1)\n s=%s\n x=", s); mpfr_dump (x); exit (1); } /* Check base 62 */ res = mpfr_strtofr (x, "A", NULL, 62, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 10)) { printf ("Error for setting 'A' in base 62\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } res = mpfr_strtofr (x, "a", NULL, 62, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 36)) { printf ("Error for setting 'a' in base 62\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } res = mpfr_strtofr (x, "Z", NULL, 62, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 35)) { printf ("Error for setting 'Z' in base 62\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } res = mpfr_strtofr (x, "z", NULL, 62, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 61)) { printf ("Error for setting 'z' in base 62\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } res = mpfr_strtofr (x, "ZA", NULL, 62, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 2180)) { printf ("Error for setting 'ZA' in base 62\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } res = mpfr_strtofr (x, "za", NULL, 62, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 3818)) { printf ("Error for setting 'za' in base 62\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } res = mpfr_strtofr (x, "aZ", NULL, 62, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 2267)) { printf ("Error for setting 'aZ' in base 62\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } res = mpfr_strtofr (x, "Az", NULL, 62, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 681)) { printf ("Error for setting 'Az' in base 62\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* Check base 60 */ res = mpfr_strtofr (x, "Aa", NULL, 60, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 636)) { printf ("Error for setting 'Aa' in base 60\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } res = mpfr_strtofr (x, "Zz", &s, 60, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 35) || strcmp(s, "z") ) { printf ("Error for setting 'Zz' in base 60\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } /* Check base 61 */ res = mpfr_strtofr (x, "z", &s, 61, MPFR_RNDN); if (res != 0 || mpfr_cmp_ui (x, 0) || strcmp(s, "z") ) { printf ("Error for setting 'z' in base 61\n x="); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n'); exit (1); } mpfr_clear (x); mpfr_clear (y); }
int main (void) { mpfr_t x; int r; mp_prec_t p; tests_start_mpfr (); special (); mpfr_init (x); for (p=2; p<100; p++) { mpfr_set_prec (x, p); for (r = 0; r < GMP_RND_MAX; r++) { mpfr_set_ui (x, 1, GMP_RNDN); mpfr_cbrt (x, x, (mp_rnd_t) r); if (mpfr_cmp_ui (x, 1)) { printf ("Error in mpfr_cbrt for x=1, rnd=%s\ngot ", mpfr_print_rnd_mode ((mp_rnd_t) r)); mpfr_out_str (stdout, 2, 0, x, GMP_RNDN); printf ("\n"); exit (1); } mpfr_set_si (x, -1, GMP_RNDN); mpfr_cbrt (x, x, (mp_rnd_t) r); if (mpfr_cmp_si (x, -1)) { printf ("Error in mpfr_cbrt for x=-1, rnd=%s\ngot ", mpfr_print_rnd_mode ((mp_rnd_t) r)); mpfr_out_str (stdout, 2, 0, x, GMP_RNDN); printf ("\n"); exit (1); } if (p >= 5) { int i; for (i = -12; i <= 12; i++) { mpfr_set_ui (x, 27, GMP_RNDN); mpfr_mul_2si (x, x, 3*i, GMP_RNDN); mpfr_cbrt (x, x, GMP_RNDN); if (mpfr_cmp_si_2exp (x, 3, i)) { printf ("Error in mpfr_cbrt for " "x = 27.0 * 2^(%d), rnd=%s\ngot ", 3*i, mpfr_print_rnd_mode ((mp_rnd_t) r)); mpfr_out_str (stdout, 2, 0, x, GMP_RNDN); printf ("\ninstead of 3 * 2^(%d)\n", i); exit (1); } } } } } mpfr_clear (x); tests_end_mpfr (); return 0; }
static void check_1111 (void) { mpfr_t one; long n; mpfr_init2 (one, MPFR_PREC_MIN); mpfr_set_ui (one, 1, MPFR_RNDN); for (n = 0; n < NUM; n++) { mpfr_prec_t prec_a, prec_b, prec_c; mpfr_exp_t tb=0, tc, diff; mpfr_t a, b, c, s; int m = 512; int sb, sc; int inex_a, inex_s; mpfr_rnd_t rnd_mode; prec_a = MPFR_PREC_MIN + (randlimb () % m); prec_b = MPFR_PREC_MIN + (randlimb () % m); prec_c = MPFR_PREC_MIN + (randlimb () % m); mpfr_init2 (a, prec_a); mpfr_init2 (b, prec_b); mpfr_init2 (c, prec_c); sb = randlimb () % 3; if (sb != 0) { tb = 1 + (randlimb () % (prec_b - (sb != 2))); mpfr_div_2ui (b, one, tb, MPFR_RNDN); if (sb == 2) mpfr_neg (b, b, MPFR_RNDN); test_add (b, b, one, MPFR_RNDN); } else mpfr_set (b, one, MPFR_RNDN); tc = 1 + (randlimb () % (prec_c - 1)); mpfr_div_2ui (c, one, tc, MPFR_RNDN); sc = randlimb () % 2; if (sc) mpfr_neg (c, c, MPFR_RNDN); test_add (c, c, one, MPFR_RNDN); diff = (randlimb () % (2*m)) - m; mpfr_mul_2si (c, c, diff, MPFR_RNDN); rnd_mode = RND_RAND (); inex_a = test_add (a, b, c, rnd_mode); mpfr_init2 (s, MPFR_PREC_MIN + 2*m); inex_s = test_add (s, b, c, MPFR_RNDN); /* exact */ if (inex_s) { printf ("check_1111: result should have been exact.\n"); exit (1); } inex_s = mpfr_prec_round (s, prec_a, rnd_mode); if ((inex_a < 0 && inex_s >= 0) || (inex_a == 0 && inex_s != 0) || (inex_a > 0 && inex_s <= 0) || !mpfr_equal_p (a, s)) { printf ("check_1111: results are different.\n"); printf ("prec_a = %d, prec_b = %d, prec_c = %d\n", (int) prec_a, (int) prec_b, (int) prec_c); printf ("tb = %d, tc = %d, diff = %d, rnd = %s\n", (int) tb, (int) tc, (int) diff, mpfr_print_rnd_mode (rnd_mode)); printf ("sb = %d, sc = %d\n", sb, sc); printf ("a = "); mpfr_print_binary (a); puts (""); printf ("s = "); mpfr_print_binary (s); puts (""); printf ("inex_a = %d, inex_s = %d\n", inex_a, inex_s); exit (1); } mpfr_clear (a); mpfr_clear (b); mpfr_clear (c); mpfr_clear (s); } mpfr_clear (one); }
static void special (void) { mpfr_t x, y; mpfr_init (x); mpfr_init (y); /* cbrt(NaN) = NaN */ mpfr_set_nan (x); mpfr_cbrt (y, x, GMP_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: cbrt(NaN) <> NaN\n"); exit (1); } /* cbrt(+Inf) = +Inf */ mpfr_set_inf (x, 1); mpfr_cbrt (y, x, GMP_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error: cbrt(+Inf) <> +Inf\n"); exit (1); } /* cbrt(-Inf) = -Inf */ mpfr_set_inf (x, -1); mpfr_cbrt (y, x, GMP_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) > 0) { printf ("Error: cbrt(-Inf) <> -Inf\n"); exit (1); } /* cbrt(+/-0) = +/-0 */ mpfr_set_ui (x, 0, GMP_RNDN); mpfr_cbrt (y, x, GMP_RNDN); if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) < 0) { printf ("Error: cbrt(+0) <> +0\n"); exit (1); } mpfr_neg (x, x, GMP_RNDN); mpfr_cbrt (y, x, GMP_RNDN); if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) > 0) { printf ("Error: cbrt(-0) <> -0\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_set_str (x, "8.39005285514734966412e-01", 10, GMP_RNDN); mpfr_cbrt (x, x, GMP_RNDN); if (mpfr_cmp_str1 (x, "9.43166207799662426048e-01")) { printf ("Error in crbrt (1)\n"); exit (1); } mpfr_set_prec (x, 32); mpfr_set_prec (y, 32); mpfr_set_str_binary (x, "0.10000100001100101001001001011001"); mpfr_cbrt (x, x, GMP_RNDN); mpfr_set_str_binary (y, "0.11001101011000100111000111111001"); if (mpfr_cmp (x, y)) { printf ("Error in cbrt (2)\n"); exit (1); } mpfr_set_prec (x, 32); mpfr_set_prec (y, 32); mpfr_set_str_binary (x, "-0.1100001110110000010101011001011"); mpfr_cbrt (x, x, GMP_RNDD); mpfr_set_str_binary (y, "-0.11101010000100100101000101011001"); if (mpfr_cmp (x, y)) { printf ("Error in cbrt (3)\n"); exit (1); } mpfr_set_prec (x, 82); mpfr_set_prec (y, 27); mpfr_set_str_binary (x, "0.1010001111011101011011000111001011001101100011110110010011011011011010011001100101e-7"); mpfr_cbrt (y, x, GMP_RNDD); mpfr_set_str_binary (x, "0.101011110001110001000100011E-2"); if (mpfr_cmp (x, y)) { printf ("Error in cbrt (4)\n"); exit (1); } mpfr_set_prec (x, 204); mpfr_set_prec (y, 38); mpfr_set_str_binary (x, "0.101000000001101000000001100111111011111001110110100001111000100110100111001101100111110001110001011011010110010011100101111001111100001010010100111011101100000011011000101100010000000011000101001010001001E-5"); mpfr_cbrt (y, x, GMP_RNDD); mpfr_set_str_binary (x, "0.10001001111010011011101000010110110010E-1"); if (mpfr_cmp (x, y)) { printf ("Error in cbrt (5)\n"); exit (1); } mpfr_clear (x); mpfr_clear (y); }
/* Implements asymptotic expansion for jn or yn (formulae 9.2.5 and 9.2.6 from Abramowitz & Stegun). Assumes |z| > p log(2)/2, where p is the target precision (z can be negative only for jn). Return 0 if the expansion does not converge enough (the value 0 as inexact flag should not happen for normal input). */ static int FUNCTION (mpfr_ptr res, long n, mpfr_srcptr z, mpfr_rnd_t r) { mpfr_t s, c, P, Q, t, iz, err_t, err_s, err_u; mpfr_prec_t w; long k; int inex, stop, diverge = 0; mpfr_exp_t err2, err; MPFR_ZIV_DECL (loop); mpfr_init (c); w = MPFR_PREC(res) + MPFR_INT_CEIL_LOG2(MPFR_PREC(res)) + 4; MPFR_ZIV_INIT (loop, w); for (;;) { mpfr_set_prec (c, w); mpfr_init2 (s, w); mpfr_init2 (P, w); mpfr_init2 (Q, w); mpfr_init2 (t, w); mpfr_init2 (iz, w); mpfr_init2 (err_t, 31); mpfr_init2 (err_s, 31); mpfr_init2 (err_u, 31); /* Approximate sin(z) and cos(z). In the following, err <= k means that the approximate value y and the true value x are related by y = x * (1 + u)^k with |u| <= 2^(-w), following Higham's method. */ mpfr_sin_cos (s, c, z, MPFR_RNDN); if (MPFR_IS_NEG(z)) mpfr_neg (s, s, MPFR_RNDN); /* compute jn/yn(|z|), fix sign later */ /* The absolute error on s/c is bounded by 1/2 ulp(1/2) <= 2^(-w-1). */ mpfr_add (t, s, c, MPFR_RNDN); mpfr_sub (c, s, c, MPFR_RNDN); mpfr_swap (s, t); /* now s approximates sin(z)+cos(z), and c approximates sin(z)-cos(z), with total absolute error bounded by 2^(1-w). */ /* precompute 1/(8|z|) */ mpfr_si_div (iz, MPFR_IS_POS(z) ? 1 : -1, z, MPFR_RNDN); /* err <= 1 */ mpfr_div_2ui (iz, iz, 3, MPFR_RNDN); /* compute P and Q */ mpfr_set_ui (P, 1, MPFR_RNDN); mpfr_set_ui (Q, 0, MPFR_RNDN); mpfr_set_ui (t, 1, MPFR_RNDN); /* current term */ mpfr_set_ui (err_t, 0, MPFR_RNDN); /* error on t */ mpfr_set_ui (err_s, 0, MPFR_RNDN); /* error on P and Q (sum of errors) */ for (k = 1, stop = 0; stop < 4; k++) { /* compute next term: t(k)/t(k-1) = (2n+2k-1)(2n-2k+1)/(8kz) */ mpfr_mul_si (t, t, 2 * (n + k) - 1, MPFR_RNDN); /* err <= err_k + 1 */ mpfr_mul_si (t, t, 2 * (n - k) + 1, MPFR_RNDN); /* err <= err_k + 2 */ mpfr_div_ui (t, t, k, MPFR_RNDN); /* err <= err_k + 3 */ mpfr_mul (t, t, iz, MPFR_RNDN); /* err <= err_k + 5 */ /* the relative error on t is bounded by (1+u)^(5k)-1, which is bounded by 6ku for 6ku <= 0.02: first |5 log(1+u)| <= |5.5u| for |u| <= 0.15, then |exp(5.5u)-1| <= 6u for |u| <= 0.02. */ mpfr_mul_ui (err_t, t, 6 * k, MPFR_IS_POS(t) ? MPFR_RNDU : MPFR_RNDD); mpfr_abs (err_t, err_t, MPFR_RNDN); /* exact */ /* the absolute error on t is bounded by err_t * 2^(-w) */ mpfr_abs (err_u, t, MPFR_RNDU); mpfr_mul_2ui (err_u, err_u, w, MPFR_RNDU); /* t * 2^w */ mpfr_add (err_u, err_u, err_t, MPFR_RNDU); /* max|t| * 2^w */ if (stop >= 2) { /* take into account the neglected terms: t * 2^w */ mpfr_div_2ui (err_s, err_s, w, MPFR_RNDU); if (MPFR_IS_POS(t)) mpfr_add (err_s, err_s, t, MPFR_RNDU); else mpfr_sub (err_s, err_s, t, MPFR_RNDU); mpfr_mul_2ui (err_s, err_s, w, MPFR_RNDU); stop ++; } /* if k is odd, add to Q, otherwise to P */ else if (k & 1) { /* if k = 1 mod 4, add, otherwise subtract */ if ((k & 2) == 0) mpfr_add (Q, Q, t, MPFR_RNDN); else mpfr_sub (Q, Q, t, MPFR_RNDN); /* check if the next term is smaller than ulp(Q): if EXP(err_u) <= EXP(Q), since the current term is bounded by err_u * 2^(-w), it is bounded by ulp(Q) */ if (MPFR_EXP(err_u) <= MPFR_EXP(Q)) stop ++; else stop = 0; } else { /* if k = 0 mod 4, add, otherwise subtract */ if ((k & 2) == 0) mpfr_add (P, P, t, MPFR_RNDN); else mpfr_sub (P, P, t, MPFR_RNDN); /* check if the next term is smaller than ulp(P) */ if (MPFR_EXP(err_u) <= MPFR_EXP(P)) stop ++; else stop = 0; } mpfr_add (err_s, err_s, err_t, MPFR_RNDU); /* the sum of the rounding errors on P and Q is bounded by err_s * 2^(-w) */ /* stop when start to diverge */ if (stop < 2 && ((MPFR_IS_POS(z) && mpfr_cmp_ui (z, (k + 1) / 2) < 0) || (MPFR_IS_NEG(z) && mpfr_cmp_si (z, - ((k + 1) / 2)) > 0))) { /* if we have to stop the series because it diverges, then increasing the precision will most probably fail, since we will stop to the same point, and thus compute a very similar approximation */ diverge = 1; stop = 2; /* force stop */ } } /* the sum of the total errors on P and Q is bounded by err_s * 2^(-w) */ /* Now combine: the sum of the rounding errors on P and Q is bounded by err_s * 2^(-w), and the absolute error on s/c is bounded by 2^(1-w) */ if ((n & 1) == 0) /* n even: P * (sin + cos) + Q (cos - sin) for jn Q * (sin + cos) + P (sin - cos) for yn */ { #ifdef MPFR_JN mpfr_mul (c, c, Q, MPFR_RNDN); /* Q * (sin - cos) */ mpfr_mul (s, s, P, MPFR_RNDN); /* P * (sin + cos) */ #else mpfr_mul (c, c, P, MPFR_RNDN); /* P * (sin - cos) */ mpfr_mul (s, s, Q, MPFR_RNDN); /* Q * (sin + cos) */ #endif err = MPFR_EXP(c); if (MPFR_EXP(s) > err) err = MPFR_EXP(s); #ifdef MPFR_JN mpfr_sub (s, s, c, MPFR_RNDN); #else mpfr_add (s, s, c, MPFR_RNDN); #endif } else /* n odd: P * (sin - cos) + Q (cos + sin) for jn, Q * (sin - cos) - P (cos + sin) for yn */ { #ifdef MPFR_JN mpfr_mul (c, c, P, MPFR_RNDN); /* P * (sin - cos) */ mpfr_mul (s, s, Q, MPFR_RNDN); /* Q * (sin + cos) */ #else mpfr_mul (c, c, Q, MPFR_RNDN); /* Q * (sin - cos) */ mpfr_mul (s, s, P, MPFR_RNDN); /* P * (sin + cos) */ #endif err = MPFR_EXP(c); if (MPFR_EXP(s) > err) err = MPFR_EXP(s); #ifdef MPFR_JN mpfr_add (s, s, c, MPFR_RNDN); #else mpfr_sub (s, c, s, MPFR_RNDN); #endif } if ((n & 2) != 0) mpfr_neg (s, s, MPFR_RNDN); if (MPFR_EXP(s) > err) err = MPFR_EXP(s); /* the absolute error on s is bounded by P*err(s/c) + Q*err(s/c) + err(P)*(s/c) + err(Q)*(s/c) + 3 * 2^(err - w - 1) <= (|P|+|Q|) * 2^(1-w) + err_s * 2^(1-w) + 2^err * 2^(1-w), since |c|, |old_s| <= 2. */ err2 = (MPFR_EXP(P) >= MPFR_EXP(Q)) ? MPFR_EXP(P) + 2 : MPFR_EXP(Q) + 2; /* (|P| + |Q|) * 2^(1 - w) <= 2^(err2 - w) */ err = MPFR_EXP(err_s) >= err ? MPFR_EXP(err_s) + 2 : err + 2; /* err_s * 2^(1-w) + 2^old_err * 2^(1-w) <= 2^err * 2^(-w) */ err2 = (err >= err2) ? err + 1 : err2 + 1; /* now the absolute error on s is bounded by 2^(err2 - w) */ /* multiply by sqrt(1/(Pi*z)) */ mpfr_const_pi (c, MPFR_RNDN); /* Pi, err <= 1 */ mpfr_mul (c, c, z, MPFR_RNDN); /* err <= 2 */ mpfr_si_div (c, MPFR_IS_POS(z) ? 1 : -1, c, MPFR_RNDN); /* err <= 3 */ mpfr_sqrt (c, c, MPFR_RNDN); /* err<=5/2, thus the absolute error is bounded by 3*u*|c| for |u| <= 0.25 */ mpfr_mul (err_t, c, s, MPFR_SIGN(c)==MPFR_SIGN(s) ? MPFR_RNDU : MPFR_RNDD); mpfr_abs (err_t, err_t, MPFR_RNDU); mpfr_mul_ui (err_t, err_t, 3, MPFR_RNDU); /* 3*2^(-w)*|old_c|*|s| [see below] is bounded by err_t * 2^(-w) */ err2 += MPFR_EXP(c); /* |old_c| * 2^(err2 - w) [see below] is bounded by 2^(err2-w) */ mpfr_mul (c, c, s, MPFR_RNDN); /* the absolute error on c is bounded by 1/2 ulp(c) + 3*2^(-w)*|old_c|*|s| + |old_c| * 2^(err2 - w) */ /* compute err_t * 2^(-w) + 1/2 ulp(c) = (err_t + 2^EXP(c)) * 2^(-w) */ err = (MPFR_EXP(err_t) > MPFR_EXP(c)) ? MPFR_EXP(err_t) + 1 : MPFR_EXP(c) + 1; /* err_t * 2^(-w) + 1/2 ulp(c) <= 2^(err - w) */ /* now err_t * 2^(-w) bounds 1/2 ulp(c) + 3*2^(-w)*|old_c|*|s| */ err = (err >= err2) ? err + 1 : err2 + 1; /* the absolute error on c is bounded by 2^(err - w) */ mpfr_clear (s); mpfr_clear (P); mpfr_clear (Q); mpfr_clear (t); mpfr_clear (iz); mpfr_clear (err_t); mpfr_clear (err_s); mpfr_clear (err_u); err -= MPFR_EXP(c); if (MPFR_LIKELY (MPFR_CAN_ROUND (c, w - err, MPFR_PREC(res), r))) break; if (diverge != 0) { mpfr_set (c, z, r); /* will force inex=0 below, which means the asymptotic expansion failed */ break; } MPFR_ZIV_NEXT (loop, w); } MPFR_ZIV_FREE (loop); inex = (MPFR_IS_POS(z) || ((n & 1) == 0)) ? mpfr_set (res, c, r) : mpfr_neg (res, c, r); mpfr_clear (c); return inex; }
static void check_special (void) { mpfr_t a, d, q; mpfr_exp_t emax, emin; int i; mpfr_init2 (a, 100L); mpfr_init2 (d, 100L); mpfr_init2 (q, 100L); /* 1/nan == nan */ mpfr_set_ui (a, 1L, MPFR_RNDN); MPFR_SET_NAN (d); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN); /* nan/1 == nan */ MPFR_SET_NAN (a); mpfr_set_ui (d, 1L, MPFR_RNDN); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN); /* +inf/1 == +inf */ MPFR_SET_INF (a); MPFR_SET_POS (a); mpfr_set_ui (d, 1L, MPFR_RNDN); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q)); MPFR_ASSERTN (mpfr_sgn (q) > 0); MPFR_ASSERTN (__gmpfr_flags == 0); /* +inf/-1 == -inf */ MPFR_SET_INF (a); MPFR_SET_POS (a); mpfr_set_si (d, -1, MPFR_RNDN); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q)); MPFR_ASSERTN (mpfr_sgn (q) < 0); MPFR_ASSERTN (__gmpfr_flags == 0); /* -inf/1 == -inf */ MPFR_SET_INF (a); MPFR_SET_NEG (a); mpfr_set_ui (d, 1L, MPFR_RNDN); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q)); MPFR_ASSERTN (mpfr_sgn (q) < 0); MPFR_ASSERTN (__gmpfr_flags == 0); /* -inf/-1 == +inf */ MPFR_SET_INF (a); MPFR_SET_NEG (a); mpfr_set_si (d, -1, MPFR_RNDN); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q)); MPFR_ASSERTN (mpfr_sgn (q) > 0); MPFR_ASSERTN (__gmpfr_flags == 0); /* 1/+inf == +0 */ mpfr_set_ui (a, 1L, MPFR_RNDN); MPFR_SET_INF (d); MPFR_SET_POS (d); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_number_p (q)); MPFR_ASSERTN (mpfr_sgn (q) == 0); MPFR_ASSERTN (MPFR_IS_POS (q)); MPFR_ASSERTN (__gmpfr_flags == 0); /* 1/-inf == -0 */ mpfr_set_ui (a, 1L, MPFR_RNDN); MPFR_SET_INF (d); MPFR_SET_NEG (d); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_number_p (q)); MPFR_ASSERTN (mpfr_sgn (q) == 0); MPFR_ASSERTN (MPFR_IS_NEG (q)); MPFR_ASSERTN (__gmpfr_flags == 0); /* -1/+inf == -0 */ mpfr_set_si (a, -1, MPFR_RNDN); MPFR_SET_INF (d); MPFR_SET_POS (d); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_number_p (q)); MPFR_ASSERTN (mpfr_sgn (q) == 0); MPFR_ASSERTN (MPFR_IS_NEG (q)); MPFR_ASSERTN (__gmpfr_flags == 0); /* -1/-inf == +0 */ mpfr_set_si (a, -1, MPFR_RNDN); MPFR_SET_INF (d); MPFR_SET_NEG (d); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_number_p (q)); MPFR_ASSERTN (mpfr_sgn (q) == 0); MPFR_ASSERTN (MPFR_IS_POS (q)); MPFR_ASSERTN (__gmpfr_flags == 0); /* 0/0 == nan */ mpfr_set_ui (a, 0L, MPFR_RNDN); mpfr_set_ui (d, 0L, MPFR_RNDN); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN); /* +inf/+inf == nan */ MPFR_SET_INF (a); MPFR_SET_POS (a); MPFR_SET_INF (d); MPFR_SET_POS (d); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN); /* 1/+0 = +inf */ mpfr_set_ui (a, 1, MPFR_RNDZ); mpfr_set_ui (d, 0, MPFR_RNDZ); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0); /* 1/-0 = -inf */ mpfr_set_ui (a, 1, MPFR_RNDZ); mpfr_set_ui (d, 0, MPFR_RNDZ); mpfr_neg (d, d, MPFR_RNDZ); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) < 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0); /* -1/+0 = -inf */ mpfr_set_si (a, -1, MPFR_RNDZ); mpfr_set_ui (d, 0, MPFR_RNDZ); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) < 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0); /* -1/-0 = +inf */ mpfr_set_si (a, -1, MPFR_RNDZ); mpfr_set_ui (d, 0, MPFR_RNDZ); mpfr_neg (d, d, MPFR_RNDZ); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0); /* +inf/+0 = +inf */ MPFR_SET_INF (a); MPFR_SET_POS (a); mpfr_set_ui (d, 0, MPFR_RNDZ); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0); MPFR_ASSERTN (__gmpfr_flags == 0); /* +inf/-0 = -inf */ MPFR_SET_INF (a); MPFR_SET_POS (a); mpfr_set_ui (d, 0, MPFR_RNDZ); mpfr_neg (d, d, MPFR_RNDZ); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) < 0); MPFR_ASSERTN (__gmpfr_flags == 0); /* -inf/+0 = -inf */ MPFR_SET_INF (a); MPFR_SET_NEG (a); mpfr_set_ui (d, 0, MPFR_RNDZ); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) < 0); MPFR_ASSERTN (__gmpfr_flags == 0); /* -inf/-0 = +inf */ MPFR_SET_INF (a); MPFR_SET_NEG (a); mpfr_set_ui (d, 0, MPFR_RNDZ); mpfr_neg (d, d, MPFR_RNDZ); mpfr_clear_flags (); MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */ MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0); MPFR_ASSERTN (__gmpfr_flags == 0); /* check overflow */ emax = mpfr_get_emax (); set_emax (1); mpfr_set_ui (a, 1, MPFR_RNDZ); mpfr_set_ui (d, 1, MPFR_RNDZ); mpfr_div_2exp (d, d, 1, MPFR_RNDZ); mpfr_clear_flags (); test_div (q, a, d, MPFR_RNDU); /* 1 / 0.5 = 2 -> overflow */ MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0); MPFR_ASSERTN (__gmpfr_flags == (MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT)); set_emax (emax); /* check underflow */ emin = mpfr_get_emin (); set_emin (-1); mpfr_set_ui (a, 1, MPFR_RNDZ); mpfr_div_2exp (a, a, 2, MPFR_RNDZ); mpfr_set_prec (d, mpfr_get_prec (q) + 8); for (i = -1; i <= 1; i++) { int sign; /* Test 2^(-2) / (+/- (2 + eps)), with eps < 0, eps = 0, eps > 0. -> underflow. With div.c r5513, this test fails for eps > 0 in MPFR_RNDN. */ mpfr_set_ui (d, 2, MPFR_RNDZ); if (i < 0) mpfr_nextbelow (d); if (i > 0) mpfr_nextabove (d); for (sign = 0; sign <= 1; sign++) { mpfr_clear_flags (); test_div (q, a, d, MPFR_RNDZ); /* result = 0 */ MPFR_ASSERTN (__gmpfr_flags == (MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT)); MPFR_ASSERTN (sign ? MPFR_IS_NEG (q) : MPFR_IS_POS (q)); MPFR_ASSERTN (MPFR_IS_ZERO (q)); mpfr_clear_flags (); test_div (q, a, d, MPFR_RNDN); /* result = 0 iff eps >= 0 */ MPFR_ASSERTN (__gmpfr_flags == (MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT)); MPFR_ASSERTN (sign ? MPFR_IS_NEG (q) : MPFR_IS_POS (q)); if (i < 0) mpfr_nexttozero (q); MPFR_ASSERTN (MPFR_IS_ZERO (q)); mpfr_neg (d, d, MPFR_RNDN); } } set_emin (emin); mpfr_clear (a); mpfr_clear (d); mpfr_clear (q); }