static void test_genericq (mpfr_prec_t p0, mpfr_prec_t p1, unsigned int N, int (*func)(mpfr_ptr, mpfr_srcptr, mpq_srcptr, mpfr_rnd_t), const char *op) { mpfr_prec_t prec; mpfr_t arg1, dst_big, dst_small, tmp; mpq_t arg2; mpfr_rnd_t rnd; int inexact, compare, compare2; unsigned int n; mpfr_inits (arg1, dst_big, dst_small, tmp, (mpfr_ptr) 0); mpq_init (arg2); for (prec = p0; prec <= p1; prec++) { mpfr_set_prec (arg1, prec); mpfr_set_prec (tmp, prec); mpfr_set_prec (dst_small, prec); for (n=0; n<N; n++) { mpfr_urandomb (arg1, RANDS); mpq_set_ui (arg2, randlimb (), randlimb() ); mpq_canonicalize (arg2); rnd = RND_RAND (); mpfr_set_prec (dst_big, prec+10); compare = func(dst_big, arg1, arg2, rnd); if (mpfr_can_round (dst_big, prec+10, rnd, rnd, prec)) { mpfr_set (tmp, dst_big, rnd); inexact = func(dst_small, arg1, arg2, rnd); if (mpfr_cmp (tmp, dst_small)) { printf ("Results differ for prec=%u rnd_mode=%s and %s_q:\n" "arg1=", (unsigned) prec, mpfr_print_rnd_mode (rnd), op); mpfr_print_binary (arg1); printf("\narg2="); mpq_out_str(stdout, 2, arg2); printf ("\ngot "); mpfr_print_binary (dst_small); printf ("\nexpected "); mpfr_print_binary (tmp); printf ("\napprox "); mpfr_print_binary (dst_big); putchar('\n'); exit (1); } compare2 = mpfr_cmp (tmp, dst_big); /* if rounding to nearest, cannot know the sign of t - f(x) because of composed rounding: y = o(f(x)) and t = o(y) */ if (compare * compare2 >= 0) compare = compare + compare2; else compare = inexact; /* cannot determine sign(t-f(x)) */ if (((inexact == 0) && (compare != 0)) || ((inexact > 0) && (compare <= 0)) || ((inexact < 0) && (compare >= 0))) { printf ("Wrong inexact flag for rnd=%s and %s_q:\n" "expected %d, got %d", mpfr_print_rnd_mode (rnd), op, compare, inexact); printf ("\narg1="); mpfr_print_binary (arg1); printf ("\narg2="); mpq_out_str(stdout, 2, arg2); printf ("\ndstl="); mpfr_print_binary (dst_big); printf ("\ndsts="); mpfr_print_binary (dst_small); printf ("\ntmp ="); mpfr_print_binary (tmp); putchar('\n'); exit (1); } } } } mpq_clear (arg2); mpfr_clears (arg1, dst_big, dst_small, tmp, (mpfr_ptr) 0); }

static void special (void) { mpfr_t x, y; int i; mpfr_init (x); mpfr_init (y); /* root(NaN) = NaN */ mpfr_set_nan (x); mpfr_root (y, x, 17, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: root(NaN,17) <> NaN\n"); exit (1); } /* root(+Inf) = +Inf */ mpfr_set_inf (x, 1); mpfr_root (y, x, 42, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error: root(+Inf,42) <> +Inf\n"); exit (1); } /* root(-Inf, 17) = -Inf */ mpfr_set_inf (x, -1); mpfr_root (y, x, 17, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) > 0) { printf ("Error: root(-Inf,17) <> -Inf\n"); exit (1); } /* root(-Inf, 42) = NaN */ mpfr_set_inf (x, -1); mpfr_root (y, x, 42, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: root(-Inf,42) <> -Inf\n"); exit (1); } /* root(+/-0) = +/-0 */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_root (y, x, 17, MPFR_RNDN); if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) < 0) { printf ("Error: root(+0,17) <> +0\n"); exit (1); } mpfr_neg (x, x, MPFR_RNDN); mpfr_root (y, x, 42, MPFR_RNDN); if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) > 0) { printf ("Error: root(-0,42) <> -0\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_set_str (x, "8.39005285514734966412e-01", 10, MPFR_RNDN); mpfr_root (x, x, 3, MPFR_RNDN); if (mpfr_cmp_str1 (x, "9.43166207799662426048e-01")) { printf ("Error in root3 (1)\n"); printf ("expected 9.43166207799662426048e-01\n"); printf ("got "); mpfr_dump (x); exit (1); } mpfr_set_prec (x, 32); mpfr_set_prec (y, 32); mpfr_set_str_binary (x, "0.10000100001100101001001001011001"); mpfr_root (x, x, 3, MPFR_RNDN); mpfr_set_str_binary (y, "0.11001101011000100111000111111001"); if (mpfr_cmp (x, y)) { printf ("Error in root3 (2)\n"); exit (1); } mpfr_set_prec (x, 32); mpfr_set_prec (y, 32); mpfr_set_str_binary (x, "-0.1100001110110000010101011001011"); mpfr_root (x, x, 3, MPFR_RNDD); mpfr_set_str_binary (y, "-0.11101010000100100101000101011001"); if (mpfr_cmp (x, y)) { printf ("Error in root3 (3)\n"); exit (1); } mpfr_set_prec (x, 82); mpfr_set_prec (y, 27); mpfr_set_str_binary (x, "0.1010001111011101011011000111001011001101100011110110010011011011011010011001100101e-7"); mpfr_root (y, x, 3, MPFR_RNDD); mpfr_set_str_binary (x, "0.101011110001110001000100011E-2"); if (mpfr_cmp (x, y)) { printf ("Error in root3 (4)\n"); exit (1); } mpfr_set_prec (x, 204); mpfr_set_prec (y, 38); mpfr_set_str_binary (x, "0.101000000001101000000001100111111011111001110110100001111000100110100111001101100111110001110001011011010110010011100101111001111100001010010100111011101100000011011000101100010000000011000101001010001001E-5"); mpfr_root (y, x, 3, MPFR_RNDD); mpfr_set_str_binary (x, "0.10001001111010011011101000010110110010E-1"); if (mpfr_cmp (x, y)) { printf ("Error in root3 (5)\n"); exit (1); } /* Worst case found on 2006-11-25 */ mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_str_binary (x, "1.0100001101101101001100110001001000000101001101100011E28"); mpfr_root (y, x, 35, MPFR_RNDN); mpfr_set_str_binary (x, "1.1100000010110101100011101011000010100001101100100011E0"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_root (y, x, 35, MPFR_RNDN) for\n" "x = 1.0100001101101101001100110001001000000101001101100011E28\n" "Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } /* Worst cases found on 2006-11-26 */ mpfr_set_str_binary (x, "1.1111010011101110001111010110000101110000110110101100E17"); mpfr_root (y, x, 36, MPFR_RNDD); mpfr_set_str_binary (x, "1.0110100111010001101001010111001110010100111111000010E0"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_root (y, x, 36, MPFR_RNDD) for\n" "x = 1.1111010011101110001111010110000101110000110110101100E17\n" "Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_str_binary (x, "1.1100011101101101100010110001000001110001111110010000E23"); mpfr_root (y, x, 36, MPFR_RNDU); mpfr_set_str_binary (x, "1.1001010100001110000110111111100011011101110011000100E0"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_root (y, x, 36, MPFR_RNDU) for\n" "x = 1.1100011101101101100010110001000001110001111110010000E23\n" "Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } /* Check for k = 1 */ mpfr_set_ui (x, 17, MPFR_RNDN); i = mpfr_root (y, x, 1, MPFR_RNDN); if (mpfr_cmp_ui (x, 17) || i != 0) { printf ("Error in root (17^(1/1))\n"); exit (1); } #if 0 /* Check for k == 0: For 0 <= x < 1 => +0. For x = 1 => 1. For x > 1, => +Inf. For x < 0 => NaN. */ i = mpfr_root (y, x, 0, MPFR_RNDN); if (!MPFR_IS_INF (y) || !MPFR_IS_POS (y) || i != 0) { printf ("Error in root 17^(1/0)\n"); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); i = mpfr_root (y, x, 0, MPFR_RNDN); if (mpfr_cmp_ui (y, 1) || i != 0) { printf ("Error in root 1^(1/0)\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); i = mpfr_root (y, x, 0, MPFR_RNDN); if (!MPFR_IS_ZERO (y) || !MPFR_IS_POS (y) || i != 0) { printf ("Error in root 0+^(1/0)\n"); exit (1); } MPFR_CHANGE_SIGN (x); i = mpfr_root (y, x, 0, MPFR_RNDN); if (!MPFR_IS_ZERO (y) || !MPFR_IS_POS (y) || i != 0) { printf ("Error in root 0-^(1/0)\n"); exit (1); } mpfr_set_ui_2exp (x, 17, -5, MPFR_RNDD); i = mpfr_root (y, x, 0, MPFR_RNDN); if (!MPFR_IS_ZERO (y) || !MPFR_IS_POS (y) || i != 0) { printf ("Error in root (17/2^5)^(1/0)\n"); exit (1); } #endif mpfr_set_ui (x, 0, MPFR_RNDN); i = mpfr_root (y, x, 0, MPFR_RNDN); if (!MPFR_IS_NAN (y) || i != 0) { printf ("Error in root 0+^(1/0)\n"); exit (1); } /* Check for k==2 */ mpfr_set_si (x, -17, MPFR_RNDD); i = mpfr_root (y, x, 2, MPFR_RNDN); if (!MPFR_IS_NAN (y) || i != 0) { printf ("Error in root (-17)^(1/2)\n"); exit (1); } mpfr_clear (x); mpfr_clear (y); }

static void test1 (void) { mpfr_t x, y; mpfr_init2 (x, 32); mpfr_init2 (y, 42); mpfr_set_str_binary (x, "1.1111111101000111011010010010100e-1"); mpfr_zeta (y, x, MPFR_RNDN); /* shouldn't crash */ mpfr_set_prec (x, 40); mpfr_set_prec (y, 50); mpfr_set_str_binary (x, "1.001101001101000010011010110100110000101e-1"); mpfr_zeta (y, x, MPFR_RNDU); mpfr_set_prec (x, 50); mpfr_set_str_binary (x, "-0.11111100011100111111101111100011110111001111111111E1"); if (mpfr_cmp (x, y)) { printf ("Error for input on 40 bits, output on 50 bits\n"); printf ("Expected "); mpfr_print_binary (x); puts (""); printf ("Got "); mpfr_print_binary (y); puts (""); mpfr_set_str_binary (x, "1.001101001101000010011010110100110000101e-1"); mpfr_zeta (y, x, MPFR_RNDU); mpfr_print_binary (x); puts (""); mpfr_print_binary (y); puts (""); exit (1); } mpfr_set_prec (x, 2); mpfr_set_prec (y, 55); mpfr_set_str_binary (x, "0.11e3"); mpfr_zeta (y, x, MPFR_RNDN); mpfr_set_prec (x, 55); mpfr_set_str_binary (x, "0.1000001000111000010011000010011000000100100100100010010E1"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_zeta (1)\n"); printf ("Expected "); mpfr_print_binary (x); puts (""); printf ("Got "); mpfr_print_binary (y); puts (""); exit (1); } mpfr_set_prec (x, 3); mpfr_set_prec (y, 47); mpfr_set_str_binary (x, "0.111e4"); mpfr_zeta (y, x, MPFR_RNDN); mpfr_set_prec (x, 47); mpfr_set_str_binary (x, "1.0000000000000100000000111001001010111100101011"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_zeta (2)\n"); exit (1); } /* coverage test */ mpfr_set_prec (x, 7); mpfr_set_str_binary (x, "1.000001"); mpfr_set_prec (y, 2); mpfr_zeta (y, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 64) == 0); /* another coverage test */ mpfr_set_prec (x, 24); mpfr_set_ui (x, 2, MPFR_RNDN); mpfr_set_prec (y, 2); mpfr_zeta (y, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 3, -1) == 0); mpfr_set_nan (x); mpfr_zeta (y, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (y)); mpfr_set_inf (x, 1); mpfr_zeta (y, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); mpfr_set_inf (x, -1); mpfr_zeta (y, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (y)); mpfr_clear (x); mpfr_clear (y); }

int main (int argc, char *argv[]) { mpfr_t x, y; long n; if (argc > 1) { mpfr_init2 (x, atoi (argv[1])); mpfr_set_str (x, argv[3], 10, MPFR_RNDN); mpfr_jn (x, atoi (argv[2]), x, MPFR_RNDN); mpfr_out_str (stdout, 10, 10, x, MPFR_RNDN); printf ("\n"); mpfr_clear (x); return 0; } tests_start_mpfr (); mpfr_init (x); mpfr_init (y); /* special values */ mpfr_set_nan (x); mpfr_jn (y, 17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (y)); mpfr_set_inf (x, 1); /* +Inf */ mpfr_jn (y, 17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); mpfr_set_inf (x, -1); /* -Inf */ mpfr_jn (y, 17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); mpfr_set_ui (x, 0, MPFR_RNDN); /* +0 */ mpfr_jn (y, 0, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); /* j0(+0)=1 */ mpfr_jn (y, 17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); /* j17(+0)=+0 */ mpfr_jn (y, -17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_NEG (y)); /* j-17(+0)=-0 */ mpfr_jn (y, 42, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); /* j42(+0)=+0 */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); /* -0 */ mpfr_jn (y, 0, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); /* j0(-0)=1 */ mpfr_jn (y, 17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_NEG (y)); /* j17(-0)=-0 */ mpfr_jn (y, -17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); /* j-17(-0)=+0 */ mpfr_jn (y, 42, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); /* j42(-0)=+0 */ mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_jn (y, 0, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.1100001111100011111111101101111010111101110001111"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=0, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_si (x, -1, MPFR_RNDN); mpfr_jn (y, 0, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.1100001111100011111111101101111010111101110001111"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=0, x=-1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_jn (y, 1, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.0111000010100111001001111011101001011100001100011011"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=1, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_jn (y, 17, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.1100011111001010101001001001000110110000010001011E-65"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=17, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_jn (y, 42, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.10000111100011010100111011100111101101000100000001001E-211"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=42, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_jn (y, -42, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.10000111100011010100111011100111101101000100000001001E-211"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=-42, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_si (x, -1, MPFR_RNDN); mpfr_jn (y, 42, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.10000111100011010100111011100111101101000100000001001E-211"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=42, x=-1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_si (x, -1, MPFR_RNDN); mpfr_jn (y, -42, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.10000111100011010100111011100111101101000100000001001E-211"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=-42, x=-1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_jn (y, 4, x, MPFR_RNDN); mpfr_set_str_binary (x, "-0.0001110001011001100010100111100111100000111110111011111"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=4, x=17, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_jn (y, 16, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.0011101111100111101111010100000111111001111001001010011"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=16, x=17, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_jn (y, 256, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.11111101111100110000000010111101101011101011110001011E-894"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=256, x=17, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_jn (y, 65536, x, MPFR_RNDN); mpfr_set_str_binary (x, "100010010010011010110101100001000100011100010111011E-751747"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=65536, x=17, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_jn (y, 131072, x, MPFR_RNDN); mpfr_set_str_binary (x, "1000001001110011111001110110000010011010000001001101E-1634508"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=131072, x=17, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_jn (y, 262144, x, MPFR_RNDN); mpfr_set_str_binary (x, "1010011011000100111011001011110001000010000010111111E-3531100"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=262144, x=17, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_jn (y, 524288, x, MPFR_RNDN); mpfr_set_str_binary (x, "110000001010001111011011000011001011010100010001011E-7586426"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=524288, x=17, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } n = LONG_MAX; /* ensures n is odd */ if (n % 2 == 0) n --; mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_jn (y, n, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.0"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=%ld, x=17, rnd=MPFR_RNDN\n", n); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_si (x, -17, MPFR_RNDN); mpfr_jn (y, n, x, MPFR_RNDN); mpfr_set_str_binary (x, "-0.0"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=%ld, x=-17, rnd=MPFR_RNDN\n", n); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_jn (y, -n, x, MPFR_RNDN); mpfr_set_str_binary (x, "-0.0"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=%ld, x=17, rnd=MPFR_RNDN\n", -n); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_si (x, -17, MPFR_RNDN); mpfr_jn (y, -n, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.0"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_jn for n=%ld, x=-17, rnd=MPFR_RNDN\n", -n); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_clear (x); mpfr_clear (y); tests_end_mpfr (); return 0; }

int mpfr_yn (mpfr_ptr res, long n, mpfr_srcptr z, mp_rnd_t r) { int inex; unsigned long absn; MPFR_LOG_FUNC (("x[%#R]=%R n=%d rnd=%d", z, z, n, r), ("y[%#R]=%R", res, res)); absn = SAFE_ABS (unsigned long, n); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (z))) { if (MPFR_IS_NAN (z)) { MPFR_SET_NAN (res); /* y(n,NaN) = NaN */ MPFR_RET_NAN; } /* y(n,z) tends to zero when z goes to +Inf, oscillating around 0. We choose to return +0 in that case. */ else if (MPFR_IS_INF (z)) { if (MPFR_SIGN(z) > 0) return mpfr_set_ui (res, 0, r); else /* y(n,-Inf) = NaN */ { MPFR_SET_NAN (res); MPFR_RET_NAN; } } else /* y(n,z) tends to -Inf for n >= 0 or n even, to +Inf otherwise, when z goes to zero */ { MPFR_SET_INF(res); if (n >= 0 || (n & 1) == 0) MPFR_SET_NEG(res); else MPFR_SET_POS(res); MPFR_RET(0); } } /* for z < 0, y(n,z) is imaginary except when j(n,|z|) = 0, which we assume does not happen for a rational z. */ if (MPFR_SIGN(z) < 0) { MPFR_SET_NAN (res); MPFR_RET_NAN; } /* now z is not singular, and z > 0 */ /* Deal with tiny arguments. We have: y0(z) = 2 log(z)/Pi + 2 (euler - log(2))/Pi + O(log(z)*z^2), more precisely for 0 <= z <= 1/2, with g(z) = 2/Pi + 2(euler-log(2))/Pi/log(z), g(z) - 0.41*z^2 < y0(z)/log(z) < g(z) thus since log(z) is negative: g(z)*log(z) < y0(z) < (g(z) - z^2/2)*log(z) and since |g(z)| >= 0.63 for 0 <= z <= 1/2, the relative error on y0(z)/log(z) is bounded by 0.41*z^2/0.63 <= 0.66*z^2. Note: we use both the main term in log(z) and the constant term, because otherwise the relative error would be only in 1/log(|log(z)|). */ if (n == 0 && MPFR_EXP(z) < - (mp_exp_t) (MPFR_PREC(res) / 2)) { mpfr_t l, h, t, logz; mp_prec_t prec; int ok, inex2; prec = MPFR_PREC(res) + 10; mpfr_init2 (l, prec); mpfr_init2 (h, prec); mpfr_init2 (t, prec); mpfr_init2 (logz, prec); /* first enclose log(z) + euler - log(2) = log(z/2) + euler */ mpfr_log (logz, z, GMP_RNDD); /* lower bound of log(z) */ mpfr_set (h, logz, GMP_RNDU); /* exact */ mpfr_nextabove (h); /* upper bound of log(z) */ mpfr_const_euler (t, GMP_RNDD); /* lower bound of euler */ mpfr_add (l, logz, t, GMP_RNDD); /* lower bound of log(z) + euler */ mpfr_nextabove (t); /* upper bound of euler */ mpfr_add (h, h, t, GMP_RNDU); /* upper bound of log(z) + euler */ mpfr_const_log2 (t, GMP_RNDU); /* upper bound of log(2) */ mpfr_sub (l, l, t, GMP_RNDD); /* lower bound of log(z/2) + euler */ mpfr_nextbelow (t); /* lower bound of log(2) */ mpfr_sub (h, h, t, GMP_RNDU); /* upper bound of log(z/2) + euler */ mpfr_const_pi (t, GMP_RNDU); /* upper bound of Pi */ mpfr_div (l, l, t, GMP_RNDD); /* lower bound of (log(z/2)+euler)/Pi */ mpfr_nextbelow (t); /* lower bound of Pi */ mpfr_div (h, h, t, GMP_RNDD); /* upper bound of (log(z/2)+euler)/Pi */ mpfr_mul_2ui (l, l, 1, GMP_RNDD); /* lower bound on g(z)*log(z) */ mpfr_mul_2ui (h, h, 1, GMP_RNDU); /* upper bound on g(z)*log(z) */ /* we now have l <= g(z)*log(z) <= h, and we need to add -z^2/2*log(z) to h */ mpfr_mul (t, z, z, GMP_RNDU); /* upper bound on z^2 */ /* since logz is negative, a lower bound corresponds to an upper bound for its absolute value */ mpfr_neg (t, t, GMP_RNDD); mpfr_div_2ui (t, t, 1, GMP_RNDD); mpfr_mul (t, t, logz, GMP_RNDU); /* upper bound on z^2/2*log(z) */ /* an underflow may happen in the above instructions, clear flag */ mpfr_clear_underflow (); mpfr_add (h, h, t, GMP_RNDU); inex = mpfr_prec_round (l, MPFR_PREC(res), r); inex2 = mpfr_prec_round (h, MPFR_PREC(res), r); /* we need h=l and inex=inex2 */ ok = (inex == inex2) && (mpfr_cmp (l, h) == 0); if (ok) mpfr_set (res, h, r); /* exact */ mpfr_clear (l); mpfr_clear (h); mpfr_clear (t); mpfr_clear (logz); if (ok) return inex; } /* small argument check for y1(z) = -2/Pi/z + O(log(z)): for 0 <= z <= 1, |y1(z) + 2/Pi/z| <= 0.25 */ if (n == 1 && MPFR_EXP(z) + 1 < - (mp_exp_t) MPFR_PREC(res)) { mpfr_t y; mp_prec_t prec; mp_exp_t err1; int ok; MPFR_BLOCK_DECL (flags); /* since 2/Pi > 0.5, and |y1(z)| >= |2/Pi/z|, if z <= 2^(-emax-1), then |y1(z)| > 2^emax */ prec = MPFR_PREC(res) + 10; mpfr_init2 (y, prec); mpfr_const_pi (y, GMP_RNDU); /* Pi*(1+u)^2, where here and below u represents a quantity <= 1/2^prec */ mpfr_mul (y, y, z, GMP_RNDU); /* Pi*z * (1+u)^4, upper bound */ MPFR_BLOCK (flags, mpfr_ui_div (y, 2, y, GMP_RNDZ)); /* 2/Pi/z * (1+u)^6, lower bound, with possible overflow */ if (MPFR_OVERFLOW (flags)) { mpfr_clear (y); return mpfr_overflow (res, r, -1); } mpfr_neg (y, y, GMP_RNDN); /* (1+u)^6 can be written 1+7u [for another value of u], thus the error on 2/Pi/z is less than 7ulp(y). The truncation error is less than 1/4, thus if ulp(y)>=1/4, the total error is less than 8ulp(y), otherwise it is less than 1/4+7/8 <= 2. */ if (MPFR_EXP(y) + 2 >= MPFR_PREC(y)) /* ulp(y) >= 1/4 */ err1 = 3; else /* ulp(y) <= 1/8 */ err1 = (mp_exp_t) MPFR_PREC(y) - MPFR_EXP(y) + 1; ok = MPFR_CAN_ROUND (y, prec - err1, MPFR_PREC(res), r); if (ok) inex = mpfr_set (res, y, r); mpfr_clear (y); if (ok) return inex; } /* we can use the asymptotic expansion as soon as z > p log(2)/2, but to get some margin we use it for z > p/2 */ if (mpfr_cmp_ui (z, MPFR_PREC(res) / 2 + 3) > 0) { inex = mpfr_yn_asympt (res, n, z, r); if (inex != 0) return inex; } /* General case */ { mp_prec_t prec; mp_exp_t err1, err2, err3; mpfr_t y, s1, s2, s3; MPFR_ZIV_DECL (loop); mpfr_init (y); mpfr_init (s1); mpfr_init (s2); mpfr_init (s3); prec = MPFR_PREC(res) + 2 * MPFR_INT_CEIL_LOG2 (MPFR_PREC (res)) + 13; MPFR_ZIV_INIT (loop, prec); for (;;) { mpfr_set_prec (y, prec); mpfr_set_prec (s1, prec); mpfr_set_prec (s2, prec); mpfr_set_prec (s3, prec); mpfr_mul (y, z, z, GMP_RNDN); mpfr_div_2ui (y, y, 2, GMP_RNDN); /* z^2/4 */ /* store (z/2)^n temporarily in s2 */ mpfr_pow_ui (s2, z, absn, GMP_RNDN); mpfr_div_2si (s2, s2, absn, GMP_RNDN); /* compute S1 * (z/2)^(-n) */ if (n == 0) { mpfr_set_ui (s1, 0, GMP_RNDN); err1 = 0; } else err1 = mpfr_yn_s1 (s1, y, absn - 1); mpfr_div (s1, s1, s2, GMP_RNDN); /* (z/2)^(-n) * S1 */ /* See algorithms.tex: the relative error on s1 is bounded by (3n+3)*2^(e+1-prec). */ err1 = MPFR_INT_CEIL_LOG2 (3 * absn + 3) + err1 + 1; /* rel_err(s1) <= 2^(err1-prec), thus err(s1) <= 2^err1 ulps */ /* compute (z/2)^n * S3 */ mpfr_neg (y, y, GMP_RNDN); /* -z^2/4 */ err3 = mpfr_yn_s3 (s3, y, s2, absn); /* (z/2)^n * S3 */ /* the error on s3 is bounded by 2^err3 ulps */ /* add s1+s3 */ err1 += MPFR_EXP(s1); mpfr_add (s1, s1, s3, GMP_RNDN); /* the error is bounded by 1/2 + 2^err1*2^(- EXP(s1)) + 2^err3*2^(EXP(s3) - EXP(s1)) */ err3 += MPFR_EXP(s3); err1 = (err3 > err1) ? err3 + 1 : err1 + 1; err1 -= MPFR_EXP(s1); err1 = (err1 >= 0) ? err1 + 1 : 1; /* now the error on s1 is bounded by 2^err1*ulp(s1) */ /* compute S2 */ mpfr_div_2ui (s2, z, 1, GMP_RNDN); /* z/2 */ mpfr_log (s2, s2, GMP_RNDN); /* log(z/2) */ mpfr_const_euler (s3, GMP_RNDN); err2 = MPFR_EXP(s2) > MPFR_EXP(s3) ? MPFR_EXP(s2) : MPFR_EXP(s3); mpfr_add (s2, s2, s3, GMP_RNDN); /* log(z/2) + gamma */ err2 -= MPFR_EXP(s2); mpfr_mul_2ui (s2, s2, 1, GMP_RNDN); /* 2*(log(z/2) + gamma) */ mpfr_jn (s3, absn, z, GMP_RNDN); /* Jn(z) */ mpfr_mul (s2, s2, s3, GMP_RNDN); /* 2*(log(z/2) + gamma)*Jn(z) */ err2 += 4; /* the error on s2 is bounded by 2^err2 ulps, see algorithms.tex */ /* add all three sums */ err1 += MPFR_EXP(s1); /* the error on s1 is bounded by 2^err1 */ err2 += MPFR_EXP(s2); /* the error on s2 is bounded by 2^err2 */ mpfr_sub (s2, s2, s1, GMP_RNDN); /* s2 - (s1+s3) */ err2 = (err1 > err2) ? err1 + 1 : err2 + 1; err2 -= MPFR_EXP(s2); err2 = (err2 >= 0) ? err2 + 1 : 1; /* now the error on s2 is bounded by 2^err2*ulp(s2) */ mpfr_const_pi (y, GMP_RNDN); /* error bounded by 1 ulp */ mpfr_div (s2, s2, y, GMP_RNDN); /* error bounded by 2^(err2+1)*ulp(s2) */ err2 ++; if (MPFR_LIKELY (MPFR_CAN_ROUND (s2, prec - err2, MPFR_PREC(res), r))) break; MPFR_ZIV_NEXT (loop, prec); } MPFR_ZIV_FREE (loop); inex = (n >= 0 || (n & 1) == 0) ? mpfr_set (res, s2, r) : mpfr_neg (res, s2, r); mpfr_clear (y); mpfr_clear (s1); mpfr_clear (s2); mpfr_clear (s3); } return inex; }

int mpc_sin_cos (mpc_ptr rop_sin, mpc_ptr rop_cos, mpc_srcptr op, mpc_rnd_t rnd_sin, mpc_rnd_t rnd_cos) /* Feature not documented in the texinfo file: One of rop_sin or rop_cos may be NULL, in which case it is not computed, and the corresponding ternary inexact value is set to 0 (exact). */ { if (!mpc_fin_p (op)) return mpc_sin_cos_nonfinite (rop_sin, rop_cos, op, rnd_sin, rnd_cos); else if (mpfr_zero_p (MPC_IM (op))) return mpc_sin_cos_real (rop_sin, rop_cos, op, rnd_sin, rnd_cos); else if (mpfr_zero_p (MPC_RE (op))) return mpc_sin_cos_imag (rop_sin, rop_cos, op, rnd_sin, rnd_cos); else { /* let op = a + i*b, then sin(op) = sin(a)*cosh(b) + i*cos(a)*sinh(b) and cos(op) = cos(a)*cosh(b) - i*sin(a)*sinh(b). For Re(sin(op)) (and analogously, the other parts), we use the following algorithm, with rounding to nearest for all operations and working precision w: (1) x = o(sin(a)) (2) y = o(cosh(b)) (3) r = o(x*y) then the error on r is at most 4 ulps, since we can write r = sin(a)*cosh(b)*(1+t)^3 with |t| <= 2^(-w), thus for w >= 2, r = sin(a)*cosh(b)*(1+4*t) with |t| <= 2^(-w), thus the relative error is bounded by 4*2^(-w) <= 4*ulp(r). */ mpfr_t s, c, sh, ch, sch, csh; mpfr_prec_t prec; int ok; int inex_re, inex_im, inex_sin, inex_cos; prec = 2; if (rop_sin != NULL) prec = MPC_MAX (prec, MPC_MAX_PREC (rop_sin)); if (rop_cos != NULL) prec = MPC_MAX (prec, MPC_MAX_PREC (rop_cos)); mpfr_init2 (s, 2); mpfr_init2 (c, 2); mpfr_init2 (sh, 2); mpfr_init2 (ch, 2); mpfr_init2 (sch, 2); mpfr_init2 (csh, 2); do { ok = 1; prec += mpc_ceil_log2 (prec) + 5; mpfr_set_prec (s, prec); mpfr_set_prec (c, prec); mpfr_set_prec (sh, prec); mpfr_set_prec (ch, prec); mpfr_set_prec (sch, prec); mpfr_set_prec (csh, prec); mpfr_sin_cos (s, c, MPC_RE(op), GMP_RNDN); mpfr_sinh_cosh (sh, ch, MPC_IM(op), GMP_RNDN); if (rop_sin != NULL) { /* real part of sine */ mpfr_mul (sch, s, ch, GMP_RNDN); ok = (!mpfr_number_p (sch)) || mpfr_can_round (sch, prec - 2, GMP_RNDN, GMP_RNDZ, MPC_PREC_RE (rop_sin) + (MPC_RND_RE (rnd_sin) == GMP_RNDN)); if (ok) { /* imaginary part of sine */ mpfr_mul (csh, c, sh, GMP_RNDN); ok = (!mpfr_number_p (csh)) || mpfr_can_round (csh, prec - 2, GMP_RNDN, GMP_RNDZ, MPC_PREC_IM (rop_sin) + (MPC_RND_IM (rnd_sin) == GMP_RNDN)); } } if (rop_cos != NULL && ok) { /* real part of cosine */ mpfr_mul (c, c, ch, GMP_RNDN); ok = (!mpfr_number_p (c)) || mpfr_can_round (c, prec - 2, GMP_RNDN, GMP_RNDZ, MPC_PREC_RE (rop_cos) + (MPC_RND_RE (rnd_cos) == GMP_RNDN)); if (ok) { /* imaginary part of cosine */ mpfr_mul (s, s, sh, GMP_RNDN); mpfr_neg (s, s, GMP_RNDN); ok = (!mpfr_number_p (s)) || mpfr_can_round (s, prec - 2, GMP_RNDN, GMP_RNDZ, MPC_PREC_IM (rop_cos) + (MPC_RND_IM (rnd_cos) == GMP_RNDN)); } } } while (ok == 0); if (rop_sin != NULL) { inex_re = mpfr_set (MPC_RE (rop_sin), sch, MPC_RND_RE (rnd_sin)); if (mpfr_inf_p (sch)) inex_re = mpfr_sgn (sch); inex_im = mpfr_set (MPC_IM (rop_sin), csh, MPC_RND_IM (rnd_sin)); if (mpfr_inf_p (csh)) inex_im = mpfr_sgn (csh); inex_sin = MPC_INEX (inex_re, inex_im); } else inex_sin = MPC_INEX (0,0); /* return exact if not computed */ if (rop_cos != NULL) { inex_re = mpfr_set (MPC_RE (rop_cos), c, MPC_RND_RE (rnd_cos)); if (mpfr_inf_p (c)) inex_re = mpfr_sgn (c); inex_im = mpfr_set (MPC_IM (rop_cos), s, MPC_RND_IM (rnd_cos)); if (mpfr_inf_p (s)) inex_im = mpfr_sgn (s); inex_cos = MPC_INEX (inex_re, inex_im); } else inex_cos = MPC_INEX (0,0); /* return exact if not computed */ mpfr_clear (s); mpfr_clear (c); mpfr_clear (sh); mpfr_clear (ch); mpfr_clear (sch); mpfr_clear (csh); return (MPC_INEX12 (inex_sin, inex_cos)); } }

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; }

/* evaluates erf(x) using the expansion at x=0: erf(x) = 2/sqrt(Pi) * sum((-1)^k*x^(2k+1)/k!/(2k+1), k=0..infinity) Assumes x is neither NaN nor infinite nor zero. Assumes also that e*x^2 <= n (target precision). */ static int mpfr_erf_0 (mpfr_ptr res, mpfr_srcptr x, double xf2, mpfr_rnd_t rnd_mode) { mpfr_prec_t n, m; mpfr_exp_t nuk, sigmak; double tauk; mpfr_t y, s, t, u; unsigned int k; int log2tauk; int inex; MPFR_ZIV_DECL (loop); n = MPFR_PREC (res); /* target precision */ /* initial working precision */ m = n + (mpfr_prec_t) (xf2 / LOG2) + 8 + MPFR_INT_CEIL_LOG2 (n); mpfr_init2 (y, m); mpfr_init2 (s, m); mpfr_init2 (t, m); mpfr_init2 (u, m); MPFR_ZIV_INIT (loop, m); for (;;) { mpfr_mul (y, x, x, MPFR_RNDU); /* err <= 1 ulp */ mpfr_set_ui (s, 1, MPFR_RNDN); mpfr_set_ui (t, 1, MPFR_RNDN); tauk = 0.0; for (k = 1; ; k++) { mpfr_mul (t, y, t, MPFR_RNDU); mpfr_div_ui (t, t, k, MPFR_RNDU); mpfr_div_ui (u, t, 2 * k + 1, MPFR_RNDU); sigmak = MPFR_GET_EXP (s); if (k % 2) mpfr_sub (s, s, u, MPFR_RNDN); else mpfr_add (s, s, u, MPFR_RNDN); sigmak -= MPFR_GET_EXP(s); nuk = MPFR_GET_EXP(u) - MPFR_GET_EXP(s); if ((nuk < - (mpfr_exp_t) m) && ((double) k >= xf2)) break; /* tauk <- 1/2 + tauk * 2^sigmak + (1+8k)*2^nuk */ tauk = 0.5 + mul_2exp (tauk, sigmak) + mul_2exp (1.0 + 8.0 * (double) k, nuk); } mpfr_mul (s, x, s, MPFR_RNDU); MPFR_SET_EXP (s, MPFR_GET_EXP (s) + 1); mpfr_const_pi (t, MPFR_RNDZ); mpfr_sqrt (t, t, MPFR_RNDZ); mpfr_div (s, s, t, MPFR_RNDN); tauk = 4.0 * tauk + 11.0; /* final ulp-error on s */ log2tauk = __gmpfr_ceil_log2 (tauk); if (MPFR_LIKELY (MPFR_CAN_ROUND (s, m - log2tauk, n, rnd_mode))) break; /* Actualisation of the precision */ MPFR_ZIV_NEXT (loop, m); mpfr_set_prec (y, m); mpfr_set_prec (s, m); mpfr_set_prec (t, m); mpfr_set_prec (u, m); } MPFR_ZIV_FREE (loop); inex = mpfr_set (res, s, rnd_mode); mpfr_clear (y); mpfr_clear (t); mpfr_clear (u); mpfr_clear (s); return inex; }

static void special (void) { mpfr_t x, y; mpfr_init (x); mpfr_init (y); MPFR_SET_INF(x); mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_acosh (x, y, MPFR_RNDN); if (MPFR_IS_INF(x) || MPFR_IS_NAN(x) ) { printf ("Inf flag not clears in acosh!\n"); exit (1); } if (mpfr_cmp_ui (x, 0)) { printf ("Error: mpfr_acosh(1) <> 0\n"); exit (1); } MPFR_SET_NAN(x); mpfr_acosh (x, y, MPFR_RNDN); if (MPFR_IS_NAN(x) || MPFR_IS_INF(x) ) { printf ("NAN flag not clears in acosh!\n"); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_acosh (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: mpfr_acosh(0) <> NaN\n"); exit (1); } mpfr_set_si (x, -1, MPFR_RNDN); mpfr_acosh (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: mpfr_acosh(-1) <> NaN\n"); exit (1); } MPFR_SET_NAN(x); mpfr_acosh (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: mpfr_acosh(NaN) <> NaN\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_acosh (y, x, MPFR_RNDN); if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0) { printf ("Error: mpfr_acosh(+Inf) <> +Inf\n"); exit (1); } mpfr_set_inf (x, -1); mpfr_acosh (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: mpfr_acosh(-Inf) <> NaN\n"); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_div_2exp (x, x, 1, MPFR_RNDN); mpfr_acosh (y, x, MPFR_RNDN); if (!mpfr_nan_p (y)) { printf ("Error: mpfr_acosh(1/2) <> NaN\n"); exit (1); } mpfr_set_prec (x, 32); mpfr_set_prec (y, 32); mpfr_set_str_binary (x, "1.000001101011101111001011"); mpfr_acosh (y, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.111010100101101001010001101001E-2"); if (mpfr_cmp (x, y)) { printf ("Error: mpfr_acosh (1)\n"); exit (1); } 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_y1 (y, x, GMP_RNDN); MPFR_ASSERTN(mpfr_nan_p (y)); mpfr_set_inf (x, 1); /* +Inf */ mpfr_y1 (y, x, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); mpfr_set_inf (x, -1); /* -Inf */ mpfr_y1 (y, x, GMP_RNDN); MPFR_ASSERTN(mpfr_nan_p (y)); mpfr_set_ui (x, 0, GMP_RNDN); /* +0 */ mpfr_y1 (y, x, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_NEG (y)); /* y1(+0)=-Inf */ mpfr_set_ui (x, 0, GMP_RNDN); mpfr_neg (x, x, GMP_RNDN); /* -0 */ mpfr_y1 (y, x, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_NEG (y)); /* y1(-0)=-Inf */ mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_ui (x, 1, GMP_RNDN); mpfr_y1 (y, x, GMP_RNDN); mpfr_set_str_binary (x, "-0.110001111111110110010000001111101011001101011100101"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_y1 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_y1 (y, x, GMP_RNDN); if (!mpfr_nan_p (y)) { printf ("Error in mpfr_y1 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/y1", mpfr_y1, "mpfr_y1"); tests_end_mpfr (); return 0; }

int mpfr_grandom (mpfr_ptr rop1, mpfr_ptr rop2, gmp_randstate_t rstate, mpfr_rnd_t rnd) { int inex1, inex2, s1, s2; mpz_t x, y, xp, yp, t, a, b, s; mpfr_t sfr, l, r1, r2; mpfr_prec_t tprec, tprec0; inex2 = inex1 = 0; if (rop2 == NULL) /* only one output requested. */ { tprec0 = MPFR_PREC (rop1); } else { tprec0 = MAX (MPFR_PREC (rop1), MPFR_PREC (rop2)); } tprec0 += 11; /* We use "Marsaglia polar method" here (cf. George Marsaglia, Normal (Gaussian) random variables for supercomputers The Journal of Supercomputing, Volume 5, Number 1, 49â€“55 DOI: 10.1007/BF00155857). First we draw uniform x and y in [0,1] using mpz_urandomb (in fixed precision), and scale them to [-1, 1]. */ mpz_init (xp); mpz_init (yp); mpz_init (x); mpz_init (y); mpz_init (t); mpz_init (s); mpz_init (a); mpz_init (b); mpfr_init2 (sfr, MPFR_PREC_MIN); mpfr_init2 (l, MPFR_PREC_MIN); mpfr_init2 (r1, MPFR_PREC_MIN); if (rop2 != NULL) mpfr_init2 (r2, MPFR_PREC_MIN); mpz_set_ui (xp, 0); mpz_set_ui (yp, 0); for (;;) { tprec = tprec0; do { mpz_urandomb (xp, rstate, tprec); mpz_urandomb (yp, rstate, tprec); mpz_mul (a, xp, xp); mpz_mul (b, yp, yp); mpz_add (s, a, b); } while (mpz_sizeinbase (s, 2) > tprec * 2); /* x^2 + y^2 <= 2^{2tprec} */ for (;;) { /* FIXME: compute s as s += 2x + 2y + 2 */ mpz_add_ui (a, xp, 1); mpz_add_ui (b, yp, 1); mpz_mul (a, a, a); mpz_mul (b, b, b); mpz_add (s, a, b); if ((mpz_sizeinbase (s, 2) <= 2 * tprec) || ((mpz_sizeinbase (s, 2) == 2 * tprec + 1) && (mpz_scan1 (s, 0) == 2 * tprec))) goto yeepee; /* Extend by 32 bits */ mpz_mul_2exp (xp, xp, 32); mpz_mul_2exp (yp, yp, 32); mpz_urandomb (x, rstate, 32); mpz_urandomb (y, rstate, 32); mpz_add (xp, xp, x); mpz_add (yp, yp, y); tprec += 32; mpz_mul (a, xp, xp); mpz_mul (b, yp, yp); mpz_add (s, a, b); if (mpz_sizeinbase (s, 2) > tprec * 2) break; } } yeepee: /* FIXME: compute s with s -= 2x + 2y + 2 */ mpz_mul (a, xp, xp); mpz_mul (b, yp, yp); mpz_add (s, a, b); /* Compute the signs of the output */ mpz_urandomb (x, rstate, 2); s1 = mpz_tstbit (x, 0); s2 = mpz_tstbit (x, 1); for (;;) { /* s = xp^2 + yp^2 (loop invariant) */ mpfr_set_prec (sfr, 2 * tprec); mpfr_set_prec (l, tprec); mpfr_set_z (sfr, s, MPFR_RNDN); /* exact */ mpfr_mul_2si (sfr, sfr, -2 * tprec, MPFR_RNDN); /* exact */ mpfr_log (l, sfr, MPFR_RNDN); mpfr_neg (l, l, MPFR_RNDN); mpfr_mul_2si (l, l, 1, MPFR_RNDN); mpfr_div (l, l, sfr, MPFR_RNDN); mpfr_sqrt (l, l, MPFR_RNDN); mpfr_set_prec (r1, tprec); mpfr_mul_z (r1, l, xp, MPFR_RNDN); mpfr_div_2ui (r1, r1, tprec, MPFR_RNDN); /* exact */ if (s1) mpfr_neg (r1, r1, MPFR_RNDN); if (MPFR_CAN_ROUND (r1, tprec - 2, MPFR_PREC (rop1), rnd)) { if (rop2 != NULL) { mpfr_set_prec (r2, tprec); mpfr_mul_z (r2, l, yp, MPFR_RNDN); mpfr_div_2ui (r2, r2, tprec, MPFR_RNDN); /* exact */ if (s2) mpfr_neg (r2, r2, MPFR_RNDN); if (MPFR_CAN_ROUND (r2, tprec - 2, MPFR_PREC (rop2), rnd)) break; } else break; } /* Extend by 32 bits */ mpz_mul_2exp (xp, xp, 32); mpz_mul_2exp (yp, yp, 32); mpz_urandomb (x, rstate, 32); mpz_urandomb (y, rstate, 32); mpz_add (xp, xp, x); mpz_add (yp, yp, y); tprec += 32; mpz_mul (a, xp, xp); mpz_mul (b, yp, yp); mpz_add (s, a, b); } inex1 = mpfr_set (rop1, r1, rnd); if (rop2 != NULL) { inex2 = mpfr_set (rop2, r2, rnd); inex2 = mpfr_check_range (rop2, inex2, rnd); } inex1 = mpfr_check_range (rop1, inex1, rnd); if (rop2 != NULL) mpfr_clear (r2); mpfr_clear (r1); mpfr_clear (l); mpfr_clear (sfr); mpz_clear (b); mpz_clear (a); mpz_clear (s); mpz_clear (t); mpz_clear (y); mpz_clear (x); mpz_clear (yp); mpz_clear (xp); return INEX (inex1, inex2); }

/* Test n random bad cases. A precision py in [pymin,pymax] and * a number y of precision py are chosen randomly. One computes * x = inv(y) in precision px = py + psup (rounded to nearest). * Then (in general), y is a bad case for fct in precision py (in * the directed rounding modes, but also in the rounding-to-nearest * mode for some lower precision: see data_check). * fct, inv, name: data related to the function. * pos, emin, emax: arguments for tests_default_random. * For debugging purpose (e.g. in case of crash or infinite loop), * you can set the MPFR_DEBUG_BADCASES environment variable to 1 in * order to output information about the tested worst cases. You can * also enable logging (when supported), but this may give too much * information. */ void bad_cases (int (*fct)(FLIST), int (*inv)(FLIST), const char *name, int pos, mpfr_exp_t emin, mpfr_exp_t emax, mpfr_prec_t pymin, mpfr_prec_t pymax, mpfr_prec_t psup, int n) { mpfr_t x, y, z; char *dbgenv; int i, dbg; mpfr_exp_t old_emin, old_emax; old_emin = mpfr_get_emin (); old_emax = mpfr_get_emax (); dbgenv = getenv ("MPFR_DEBUG_BADCASES"); dbg = dbgenv != 0 ? atoi (dbgenv) : 0; /* debug level */ mpfr_inits (x, y, z, (mpfr_ptr) 0); for (i = 0; i < n; i++) { mpfr_prec_t px, py, pz; int inex; if (dbg) printf ("bad_cases: i = %d\n", i); py = pymin + (randlimb () % (pymax - pymin + 1)); mpfr_set_prec (y, py); tests_default_random (y, pos, emin, emax, 0); if (dbg) { printf ("bad_cases: yprec =%4ld, y = ", (long) py); mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN); printf ("\n"); } px = py + psup; mpfr_set_prec (x, px); mpfr_clear_flags (); inv (x, y, MPFR_RNDN); if (mpfr_nanflag_p () || mpfr_overflow_p () || mpfr_underflow_p ()) { if (dbg) printf ("bad_cases: no normal inverse\n"); goto next_i; } if (dbg > 1) { printf ("bad_cases: x = "); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); printf ("\n"); } pz = px; do { pz += 32; mpfr_set_prec (z, pz); if (fct (z, x, MPFR_RNDN) == 0) { if (dbg) printf ("bad_cases: exact case\n"); goto next_i; } if (dbg) { if (dbg > 1) { printf ("bad_cases: %s(x) ~= ", name); mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN); } else { printf ("bad_cases: [MPFR_RNDZ] ~= "); mpfr_out_str (stdout, 16, 40, z, MPFR_RNDZ); } printf ("\n"); } inex = mpfr_prec_round (z, py, MPFR_RNDN); if (mpfr_nanflag_p () || mpfr_overflow_p () || mpfr_underflow_p () || ! mpfr_equal_p (z, y)) { if (dbg) printf ("bad_cases: inverse doesn't match\n"); goto next_i; } } while (inex == 0); /* We really have a bad case. */ do py--; while (py >= MPFR_PREC_MIN && mpfr_prec_round (z, py, MPFR_RNDZ) == 0); py++; /* py is now the smallest output precision such that we have a bad case in the directed rounding modes. */ if (mpfr_prec_round (y, py, MPFR_RNDZ) != 0) { printf ("Internal error for i = %d\n", i); exit (1); } if ((inex > 0 && MPFR_IS_POS (z)) || (inex < 0 && MPFR_IS_NEG (z))) { mpfr_nexttozero (y); if (mpfr_zero_p (y)) goto next_i; } if (dbg) { printf ("bad_cases: yprec =%4ld, y = ", (long) py); mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN); printf ("\n"); } /* Note: y is now the expected result rounded toward zero. */ test5rm (fct, x, y, z, MPFR_RNDZ, 0, name); next_i: /* In case the exponent range has been changed by tests_default_random()... */ mpfr_set_emin (old_emin); mpfr_set_emax (old_emax); } mpfr_clears (x, y, z, (mpfr_ptr) 0); }

/* Check data in file f for function foo, with name 'name'. Each line consists of the file f one: xprec yprec rnd x y where: xprec is the input precision yprec is the output precision rnd is the rounding mode (n, z, u, d, a, Z, *) x is the input (hexadecimal format) y is the expected output (hexadecimal format) for foo(x) with rounding rnd If rnd is Z, y is the expected output in round-toward-zero, and the four directed rounding modes are tested, then the round-to-nearest mode is tested in precision yprec-1. This is useful for worst cases, where yprec is the minimum value such that one has a worst case in a directed rounding mode. If rnd is *, y must be an exact case. All the rounding modes are tested and the ternary value is checked (it must be 0). */ void data_check (const char *f, int (*foo) (FLIST), const char *name) { FILE *fp; long int xprec, yprec; /* not mpfr_prec_t because of the fscanf */ mpfr_t x, y, z; mpfr_rnd_t rnd; char r; int c; fp = fopen (f, "r"); if (fp == NULL) fp = src_fopen (f, "r"); if (fp == NULL) { char *v = (char *) MPFR_VERSION_STRING; /* In the '-dev' versions, assume that the data file exists and return an error if the file cannot be opened to make sure that such failures are detected. */ while (*v != '\0') v++; if (v[-4] == '-' && v[-3] == 'd' && v[-2] == 'e' && v[-1] == 'v') { printf ("Error: unable to open file '%s'\n", f); exit (1); } else return; } mpfr_init (x); mpfr_init (y); mpfr_init (z); while (!feof (fp)) { /* skip whitespace, for consistency */ if (fscanf (fp, " ") == EOF) { if (ferror (fp)) { perror ("data_check"); exit (1); } else break; /* end of file */ } if ((c = getc (fp)) == EOF) { if (ferror (fp)) { perror ("data_check"); exit (1); } else break; /* end of file */ } if (c == '#') /* comment: read entire line */ { do { c = getc (fp); } while (!feof (fp) && c != '\n'); } else { ungetc (c, fp); c = fscanf (fp, "%ld %ld %c", &xprec, &yprec, &r); MPFR_ASSERTN (MPFR_PREC_COND (xprec)); MPFR_ASSERTN (MPFR_PREC_COND (yprec)); if (c == EOF) { perror ("data_check"); exit (1); } else if (c != 3) { printf ("Error: corrupted line in file '%s'\n", f); exit (1); } switch (r) { case 'n': rnd = MPFR_RNDN; break; case 'z': case 'Z': rnd = MPFR_RNDZ; break; case 'u': rnd = MPFR_RNDU; break; case 'd': rnd = MPFR_RNDD; break; case '*': rnd = MPFR_RND_MAX; /* non-existing rounding mode */ break; default: printf ("Error: unexpected rounding mode" " in file '%s': %c\n", f, (int) r); exit (1); } mpfr_set_prec (x, xprec); mpfr_set_prec (y, yprec); if (mpfr_inp_str (x, fp, 0, MPFR_RNDN) == 0) { printf ("Error: corrupted argument in file '%s'\n", f); exit (1); } if (mpfr_inp_str (y, fp, 0, MPFR_RNDN) == 0) { printf ("Error: corrupted result in file '%s'\n", f); exit (1); } if (getc (fp) != '\n') { printf ("Error: result not followed by \\n in file '%s'\n", f); exit (1); } /* Skip whitespace, in particular at the end of the file. */ if (fscanf (fp, " ") == EOF && ferror (fp)) { perror ("data_check"); exit (1); } if (r == '*') { int rndint; RND_LOOP (rndint) test5rm (foo, x, y, z, (mpfr_rnd_t) rndint, 2, name); } else test5rm (foo, x, y, z, rnd, r != 'Z', name); } } mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); fclose (fp); }

/* The test_one argument is seen a boolean. If it is true and rnd is a rounding mode toward infinity, then the function is tested in only one rounding mode (the one provided in rnd) and the variable rndnext is not used (due to the break). If it is true and rnd is a rounding mode toward or away from zero, then the function is tested twice, first with the provided rounding mode and second with the rounding mode toward the corresponding infinity (determined by the sign of the result). If it is false, then the function is tested in the 5 rounding modes, and rnd must initially be MPFR_RNDZ; thus rndnext will be initialized in the first iteration. If the test_one argument is 2, then this means that y is exact, and the ternary value is checked. As examples of use, see the calls to test5rm from the data_check and bad_cases functions. */ static void test5rm (int (*fct) (FLIST), mpfr_srcptr x, mpfr_ptr y, mpfr_ptr z, mpfr_rnd_t rnd, int test_one, const char *name) { mpfr_prec_t yprec = MPFR_PREC (y); mpfr_rnd_t rndnext = MPFR_RND_MAX; /* means uninitialized */ MPFR_ASSERTN (test_one || rnd == MPFR_RNDZ); mpfr_set_prec (z, yprec); while (1) { int inex; MPFR_ASSERTN (rnd != MPFR_RND_MAX); inex = fct (z, x, rnd); if (! (mpfr_equal_p (y, z) || (mpfr_nan_p (y) && mpfr_nan_p (z)))) { printf ("Error for %s with xprec=%lu, yprec=%lu, rnd=%s\nx = ", name, (unsigned long) MPFR_PREC (x), (unsigned long) yprec, mpfr_print_rnd_mode (rnd)); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); printf ("\nexpected "); mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN); printf ("\ngot "); mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN); printf ("\n"); exit (1); } if (test_one == 2 && inex != 0) { printf ("Error for %s with xprec=%lu, yprec=%lu, rnd=%s\nx = ", name, (unsigned long) MPFR_PREC (x), (unsigned long) yprec, mpfr_print_rnd_mode (rnd)); mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); printf ("\nexact case, but non-zero ternary value (%d)\n", inex); exit (1); } if (rnd == MPFR_RNDN) break; if (test_one) { if (rnd == MPFR_RNDU || rnd == MPFR_RNDD) break; if (MPFR_IS_NEG (y)) rnd = (rnd == MPFR_RNDA) ? MPFR_RNDD : MPFR_RNDU; else rnd = (rnd == MPFR_RNDA) ? MPFR_RNDU : MPFR_RNDD; } else if (rnd == MPFR_RNDZ) { rnd = MPFR_IS_NEG (y) ? MPFR_RNDU : MPFR_RNDD; rndnext = MPFR_RNDA; } else { rnd = rndnext; if (rnd == MPFR_RNDA) { mpfr_nexttoinf (y); rndnext = (MPFR_IS_NEG (y)) ? MPFR_RNDD : MPFR_RNDU; } else if (rndnext != MPFR_RNDN) rndnext = MPFR_RNDN; else { if (yprec == MPFR_PREC_MIN) break; mpfr_prec_round (y, --yprec, MPFR_RNDZ); mpfr_set_prec (z, yprec); } } } }

int mpfr_zeta_ui (mpfr_ptr z, unsigned long m, mpfr_rnd_t r) { MPFR_ZIV_DECL (loop); if (m == 0) { mpfr_set_ui (z, 1, r); mpfr_div_2ui (z, z, 1, r); MPFR_CHANGE_SIGN (z); MPFR_RET (0); } else if (m == 1) { MPFR_SET_INF (z); MPFR_SET_POS (z); mpfr_set_divby0 (); return 0; } else /* m >= 2 */ { mpfr_prec_t p = MPFR_PREC(z); unsigned long n, k, err, kbits; mpz_t d, t, s, q; mpfr_t y; int inex; if (r == MPFR_RNDA) r = MPFR_RNDU; /* since the result is always positive */ if (m >= p) /* 2^(-m) < ulp(1) = 2^(1-p). This means that 2^(-m) <= 1/2*ulp(1). We have 3^(-m)+4^(-m)+... < 2^(-m) i.e. zeta(m) < 1+2*2^(-m) for m >= 3 */ { if (m == 2) /* necessarily p=2 */ return mpfr_set_ui_2exp (z, 13, -3, r); else if (r == MPFR_RNDZ || r == MPFR_RNDD || (r == MPFR_RNDN && m > p)) { mpfr_set_ui (z, 1, r); return -1; } else { mpfr_set_ui (z, 1, r); mpfr_nextabove (z); return 1; } } /* now treat also the case where zeta(m) - (1+1/2^m) < 1/2*ulp(1), and the result is either 1+2^(-m) or 1+2^(-m)+2^(1-p). */ mpfr_init2 (y, 31); if (m >= p / 2) /* otherwise 4^(-m) > 2^(-p) */ { /* the following is a lower bound for log(3)/log(2) */ mpfr_set_str_binary (y, "1.100101011100000000011010001110"); mpfr_mul_ui (y, y, m, MPFR_RNDZ); /* lower bound for log2(3^m) */ if (mpfr_cmp_ui (y, p + 2) >= 0) { mpfr_clear (y); mpfr_set_ui (z, 1, MPFR_RNDZ); mpfr_div_2ui (z, z, m, MPFR_RNDZ); mpfr_add_ui (z, z, 1, MPFR_RNDZ); if (r != MPFR_RNDU) return -1; mpfr_nextabove (z); return 1; } } mpz_init (s); mpz_init (d); mpz_init (t); mpz_init (q); p += MPFR_INT_CEIL_LOG2(p); /* account of the n term in the error */ p += MPFR_INT_CEIL_LOG2(p) + 15; /* initial value */ MPFR_ZIV_INIT (loop, p); for(;;) { /* 0.39321985067869744 = log(2)/log(3+sqrt(8)) */ n = 1 + (unsigned long) (0.39321985067869744 * (double) p); err = n + 4; mpfr_set_prec (y, p); /* computation of the d[k] */ mpz_set_ui (s, 0); mpz_set_ui (t, 1); mpz_mul_2exp (t, t, 2 * n - 1); /* t[n] */ mpz_set (d, t); for (k = n; k > 0; k--) { count_leading_zeros (kbits, k); kbits = GMP_NUMB_BITS - kbits; /* if k^m is too large, use mpz_tdiv_q */ if (m * kbits > 2 * GMP_NUMB_BITS) { /* if we know in advance that k^m > d, then floor(d/k^m) will be zero below, so there is no need to compute k^m */ kbits = (kbits - 1) * m + 1; /* k^m has at least kbits bits */ if (kbits > mpz_sizeinbase (d, 2)) mpz_set_ui (q, 0); else { mpz_ui_pow_ui (q, k, m); mpz_tdiv_q (q, d, q); } } else /* use several mpz_tdiv_q_ui calls */ { unsigned long km = k, mm = m - 1; while (mm > 0 && km < ULONG_MAX / k) { km *= k; mm --; } mpz_tdiv_q_ui (q, d, km); while (mm > 0) { km = k; mm --; while (mm > 0 && km < ULONG_MAX / k) { km *= k; mm --; } mpz_tdiv_q_ui (q, q, km); } } if (k % 2) mpz_add (s, s, q); else mpz_sub (s, s, q); /* we have d[k] = sum(t[i], i=k+1..n) with t[i] = n*(n+i-1)!*4^i/(n-i)!/(2i)! t[k-1]/t[k] = k*(2k-1)/(n-k+1)/(n+k-1)/2 */ #if (GMP_NUMB_BITS == 32) #define KMAX 46341 /* max k such that k*(2k-1) < 2^32 */ #elif (GMP_NUMB_BITS == 64) #define KMAX 3037000500 #endif #ifdef KMAX if (k <= KMAX) mpz_mul_ui (t, t, k * (2 * k - 1)); else #endif { mpz_mul_ui (t, t, k); mpz_mul_ui (t, t, 2 * k - 1); } mpz_fdiv_q_2exp (t, t, 1); /* Warning: the test below assumes that an unsigned long has no padding bits. */ if (n < 1UL << ((sizeof(unsigned long) * CHAR_BIT) / 2)) /* (n - k + 1) * (n + k - 1) < n^2 */ mpz_divexact_ui (t, t, (n - k + 1) * (n + k - 1)); else { mpz_divexact_ui (t, t, n - k + 1); mpz_divexact_ui (t, t, n + k - 1); } mpz_add (d, d, t); } /* multiply by 1/(1-2^(1-m)) = 1 + 2^(1-m) + 2^(2-m) + ... */ mpz_fdiv_q_2exp (t, s, m - 1); do { err ++; mpz_add (s, s, t); mpz_fdiv_q_2exp (t, t, m - 1); } while (mpz_cmp_ui (t, 0) > 0); /* divide by d[n] */ mpz_mul_2exp (s, s, p); mpz_tdiv_q (s, s, d); mpfr_set_z (y, s, MPFR_RNDN); mpfr_div_2ui (y, y, p, MPFR_RNDN); err = MPFR_INT_CEIL_LOG2 (err); if (MPFR_LIKELY(MPFR_CAN_ROUND (y, p - err, MPFR_PREC(z), r))) break; MPFR_ZIV_NEXT (loop, p); } MPFR_ZIV_FREE (loop); mpz_clear (d); mpz_clear (t); mpz_clear (q); mpz_clear (s); inex = mpfr_set (z, y, r); mpfr_clear (y); return inex; } }

int main (int argc, char *argv[]) { mpfr_t x, y; long n; mpfr_prec_t prec = 53; tests_start_mpfr (); mpfr_init (x); mpfr_init (y); if (argc != 1) { if (argc != 4) { printf ("Usage: tyn n x prec\n"); exit (1); } n = atoi (argv[1]); prec = atoi (argv[3]); mpfr_set_prec (x, prec); mpfr_set_prec (y, prec); mpfr_set_str (x, argv[2], 10, MPFR_RNDN); mpfr_yn (y, n, x, MPFR_RNDN); printf ("Y(%ld,", n); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); printf (")="); mpfr_out_str (stdout, 10, 0, y, MPFR_RNDN); printf ("\n"); goto end; } /* special values */ mpfr_set_nan (x); mpfr_yn (y, 17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (y)); mpfr_set_inf (x, 1); /* +Inf */ mpfr_yn (y, 17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS (y)); mpfr_set_inf (x, -1); /* -Inf */ mpfr_yn (y, 17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (y)); mpfr_set_ui (x, 0, MPFR_RNDN); /* +0 */ mpfr_yn (y, 0, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_NEG (y)); /* y0(+0)=-Inf */ mpfr_yn (y, 17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_NEG (y)); /* y17(+0)=-Inf */ mpfr_yn (y, -17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_POS (y)); /* y(-17,+0)=+Inf */ mpfr_yn (y, -42, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_NEG (y)); /* y(-42,+0)=-Inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); /* -0 */ mpfr_yn (y, 0, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_NEG (y)); /* y0(-0)=-Inf */ mpfr_yn (y, 17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_NEG (y)); /* y17(-0)=-Inf */ mpfr_yn (y, -17, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_POS (y)); /* y(-17,-0)=+Inf */ mpfr_yn (y, -42, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (y) && MPFR_IS_NEG (y)); /* y(-42,-0)=-Inf */ mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_yn (y, 0, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.00010110100110000000001000100110111100110101100011011111"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_yn for n=0, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_yn (y, 1, x, MPFR_RNDN); mpfr_set_str_binary (x, "-0.110001111111110110010000001111101011001101011100101"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_yn for n=1, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_yn (y, -1, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.110001111111110110010000001111101011001101011100101"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_yn for n=-1, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_yn (y, 2, x, MPFR_RNDN); mpfr_set_str_binary (x, "-1.101001101001001100100010101001000101101000010010001"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_yn for n=2, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_yn (y, -2, x, MPFR_RNDN); mpfr_set_str_binary (x, "-1.101001101001001100100010101001000101101000010010001"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_yn for n=-2, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_yn (y, 17, x, MPFR_RNDN); mpfr_set_str_binary (x, "-0.11000100111000100010101101011000110011001101100001011E60"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_yn for n=17, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_yn (y, -17, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.11000100111000100010101101011000110011001101100001011E60"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_yn for n=-17, x=1, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_yn (y, 1, x, MPFR_RNDN); mpfr_set_str_binary (x, "0.00101010110011011111001100000001101011011001111111"); if (mpfr_cmp (x, y)) { printf ("Error in mpfr_yn for n=1, x=17, rnd=MPFR_RNDN\n"); printf ("Expected "); mpfr_dump (x); printf ("Got "); mpfr_dump (y); exit (1); } end: mpfr_clear (x); mpfr_clear (y); tests_end_mpfr (); return 0; }

int main (int argc, char *argv[]) { mpfr_t x; mpfr_t y; FILE *f; int i; tests_start_mpfr (); mpfr_init (x); mpfr_init (y); mpfr_set_prec (x, 15); f = src_fopen ("inp_str.data", "r"); if (f == NULL) { printf ("Error, can't open inp_str.data\n"); exit (1); } i = mpfr_inp_str (x, f, 10, MPFR_RNDN); if (i == 0 || mpfr_cmp_ui (x, 31415)) { printf ("Error in reading 1st line from file inp_str.data (%d)\n", i); mpfr_dump (x); exit (1); } getc (f); i = mpfr_inp_str (x, f, 10, MPFR_RNDN); if ((i == 0) || mpfr_cmp_ui (x, 31416)) { printf ("Error in reading 2nd line from file inp_str.data (%d)\n", i); mpfr_dump (x); exit (1); } getc (f); i = mpfr_inp_str (x, f, 10, MPFR_RNDN); if (i != 0) { printf ("Error in reading 3rd line from file inp_str.data (%d)\n", i); mpfr_dump (x); exit (1); } mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_str (y, "1.0010010100001110100101001110011010111011100001110010e226", 2, MPFR_RNDN); for (i = 2; i < 63; i++) { getc (f); if (mpfr_inp_str (x, f, i, MPFR_RNDN) == 0 || !mpfr_equal_p (x, y)) { printf ("Error in reading %dth line from file inp_str.data\n", i+2); mpfr_dump (x); exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); } fclose (f); mpfr_clear (x); mpfr_clear (y); tests_end_mpfr (); return 0; }

int main (int argc, char *argv[]) { mpfr_t x, y, z; unsigned long k, n; volatile double d; double dd; tests_start_mpfr (); mpfr_test_init (); #ifndef MPFR_DOUBLE_SPEC printf ("Warning! The MPFR_DOUBLE_SPEC macro is not defined. This means\n" "that you do not have a conforming C implementation and problems\n" "may occur with conversions between MPFR numbers and standard\n" "floating-point types. Please contact the MPFR team.\n"); #elif MPFR_DOUBLE_SPEC == 0 /* printf ("The type 'double' of your C implementation does not seem to\n" "correspond to the IEEE-754 double precision. Though code has\n" "been written to support such implementations, tests have been\n" "done only on IEEE-754 double-precision implementations and\n" "conversions between MPFR numbers and standard floating-point\n" "types may be inaccurate. You may wish to contact the MPFR team\n" "for further testing.\n"); */ printf ("The type 'double' of your C implementation does not seem to\n" "correspond to the IEEE-754 double precision. Such particular\n" "implementations are not supported yet, and conversions between\n" "MPFR numbers and standard floating-point types may be very\n" "inaccurate.\n"); printf ("FLT_RADIX = %ld\n", (long) FLT_RADIX); printf ("DBL_MANT_DIG = %ld\n", (long) DBL_MANT_DIG); printf ("DBL_MIN_EXP = %ld\n", (long) DBL_MIN_EXP); printf ("DBL_MAX_EXP = %ld\n", (long) DBL_MAX_EXP); #endif mpfr_init (x); mpfr_set_nan (x); d = mpfr_get_d (x, MPFR_RNDN); if (! DOUBLE_ISNAN (d)) { printf ("ERROR for NAN (1)\n"); #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_ui (x, 0, MPFR_RNDN); mpfr_set_d (x, d, MPFR_RNDN); if (! mpfr_nan_p (x)) { printf ("ERROR for NAN (2)\n"); #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); } d = 0.0; mpfr_set_d (x, d, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_POS(x)); d = -d; mpfr_set_d (x, d, MPFR_RNDN); if (mpfr_cmp_ui (x, 0) != 0 || MPFR_IS_POS(x)) { printf ("Error in mpfr_set_d on -0\n"); exit (1); } mpfr_set_inf (x, 1); d = mpfr_get_d (x, MPFR_RNDN); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_d (x, d, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); mpfr_set_inf (x, -1); d = mpfr_get_d (x, MPFR_RNDN); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_d (x, d, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) < 0); mpfr_set_prec (x, 2); /* checks that denormalized are not flushed to zero */ d = DBL_MIN; /* 2^(-1022) */ for (n=0; n<52; n++, d /= 2.0) if (d != 0.0) /* should be 2^(-1022-n) */ { mpfr_set_d (x, d, MPFR_RNDN); if (mpfr_cmp_ui_2exp (x, 1, -1022-n)) { printf ("Wrong result for d=2^(%ld), ", -1022-n); printf ("got "); mpfr_out_str (stdout, 10, 10, x, MPFR_RNDN); printf ("\n"); mpfr_print_binary (x); puts (""); exit (1); } } /* checks that rounds to nearest sets the last bit to zero in case of equal distance */ mpfr_set_d (x, 5.0, MPFR_RNDN); if (mpfr_cmp_ui (x, 4)) { printf ("Error in tset_d: expected 4.0, got "); mpfr_print_binary (x); putchar('\n'); exit (1); } mpfr_set_d (x, -5.0, MPFR_RNDN); if (mpfr_cmp_si (x, -4)) { printf ("Error in tset_d: expected -4.0, got "); mpfr_print_binary (x); putchar('\n'); exit (1); } mpfr_set_d (x, 9.84891017624509146344e-01, MPFR_RNDU); if (mpfr_cmp_ui (x, 1)) { printf ("Error in tset_d: expected 1.0, got "); mpfr_print_binary (x); putchar('\n'); exit (1); } mpfr_init2 (z, 32); mpfr_set_d (z, 1.0, (mpfr_rnd_t) 0); if (mpfr_cmp_ui (z, 1)) { mpfr_print_binary (z); puts (""); printf ("Error: 1.0 != 1.0\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_init2 (y, 53); mpfr_set_d (x, d=-1.08007920352320089721e+150, (mpfr_rnd_t) 0); if (mpfr_get_d1 (x) != d) { mpfr_print_binary (x); puts (""); printf ("Error: get_d o set_d <> identity for d = %1.20e %1.20e\n", d, mpfr_get_d1 (x)); exit (1); } mpfr_set_d (x, 8.06294740693074521573e-310, (mpfr_rnd_t) 0); d = -6.72658901114033715233e-165; mpfr_set_d (x, d, (mpfr_rnd_t) 0); if (d != mpfr_get_d1 (x)) { mpfr_print_binary (x); puts (""); printf ("Error: get_d o set_d <> identity for d = %1.20e %1.20e\n", d, mpfr_get_d1 (x)); exit (1); } n = (argc==1) ? 500000 : atoi(argv[1]); for (k = 1; k <= n; k++) { do { d = DBL_RAND (); } #ifdef HAVE_DENORMS while (0); #else while (ABS(d) < DBL_MIN); #endif mpfr_set_d (x, d, (mpfr_rnd_t) 0); dd = mpfr_get_d1 (x); if (d != dd && !(Isnan(d) && Isnan(dd))) { printf ("Mismatch on : %1.18g != %1.18g\n", d, mpfr_get_d1 (x)); mpfr_print_binary (x); puts (""); exit (1); } } mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); tests_end_mpfr (); return 0; }

void BigFloat::SetPrecision( mpfr_prec_t prec ) { mpfr_set_prec( mpfrFloat_, prec ); numLimbs_ = (prec-1) / GMP_NUMB_BITS + 1; }

static int decimal (void) { mpfr_prec_t p = 128; mpfr_t x; mpfr_t z; mpfr_init (z); mpfr_init2 (x, p); /* specifier 'P' for precision */ check_vsprintf ("128", "%Pu", p); check_vsprintf ("00128", "%.5Pu", p); /* special numbers */ mpfr_set_inf (x, 1); check_sprintf (pinf_str, "%Re", x); check_sprintf (pinf_str, "%RUe", x); check_sprintf (pinf_uc_str, "%RE", x); check_sprintf (pinf_uc_str, "%RDE", x); check_sprintf (pinf_str, "%Rf", x); check_sprintf (pinf_str, "%RYf", x); check_sprintf (pinf_uc_str, "%RF", x); check_sprintf (pinf_uc_str, "%RZF", x); check_sprintf (pinf_str, "%Rg", x); check_sprintf (pinf_str, "%RNg", x); check_sprintf (pinf_uc_str, "%RG", x); check_sprintf (pinf_uc_str, "%RUG", x); check_sprintf (" inf", "%010Re", x); check_sprintf (" inf", "%010RDe", x); mpfr_set_inf (x, -1); check_sprintf (minf_str, "%Re", x); check_sprintf (minf_str, "%RYe", x); check_sprintf (minf_uc_str, "%RE", x); check_sprintf (minf_uc_str, "%RZE", x); check_sprintf (minf_str, "%Rf", x); check_sprintf (minf_str, "%RNf", x); check_sprintf (minf_uc_str, "%RF", x); check_sprintf (minf_uc_str, "%RUF", x); check_sprintf (minf_str, "%Rg", x); check_sprintf (minf_str, "%RDg", x); check_sprintf (minf_uc_str, "%RG", x); check_sprintf (minf_uc_str, "%RYG", x); check_sprintf (" -inf", "%010Re", x); check_sprintf (" -inf", "%010RZe", x); mpfr_set_nan (x); check_sprintf (nan_str, "%Re", x); check_sprintf (nan_str, "%RNe", x); check_sprintf (nan_uc_str, "%RE", x); check_sprintf (nan_uc_str, "%RUE", x); check_sprintf (nan_str, "%Rf", x); check_sprintf (nan_str, "%RDf", x); check_sprintf (nan_uc_str, "%RF", x); check_sprintf (nan_uc_str, "%RYF", x); check_sprintf (nan_str, "%Rg", x); check_sprintf (nan_str, "%RZg", x); check_sprintf (nan_uc_str, "%RG", x); check_sprintf (nan_uc_str, "%RNG", x); check_sprintf (" nan", "%010Re", x); /* positive numbers */ mpfr_set_str (x, "18993474.61279296875", 10, MPFR_RNDN); mpfr_set_ui (z, 0, MPFR_RNDD); /* simplest case right justified */ check_sprintf (" 1.899347461279296875e+07", "%30Re", x); check_sprintf (" 2e+07", "%30.0Re", x); check_sprintf (" 18993474.612793", "%30Rf", x); check_sprintf (" 18993474.6127930", "%30.7Rf", x); check_sprintf (" 1.89935e+07", "%30Rg", x); check_sprintf (" 2e+07", "%30.0Rg", x); check_sprintf (" 18993474.61279296875", "%30.19Rg", x); check_sprintf (" 0e+00", "%30.0Re", z); check_sprintf (" 0", "%30.0Rf", z); check_sprintf (" 0.0000", "%30.4Rf", z); check_sprintf (" 0", "%30.0Rg", z); check_sprintf (" 0", "%30.4Rg", z); /* sign or space, pad with leading zeros */ check_sprintf (" 000001.899347461279296875E+07", "% 030RE", x); check_sprintf (" 0000000000000000001.89935E+07", "% 030RG", x); check_sprintf (" 0000000000000000000000002E+07", "% 030.0RE", x); check_sprintf (" 0000000000000000000000000E+00", "% 030.0RE", z); check_sprintf (" 00000000000000000000000000000", "% 030.0RF", z); /* sign + or -, left justified */ check_sprintf ("+1.899347461279296875e+07 ", "%+-30Re", x); check_sprintf ("+2e+07 ", "%+-30.0Re", x); check_sprintf ("+0e+00 ", "%+-30.0Re", z); check_sprintf ("+0 ", "%+-30.0Rf", z); /* decimal point, left justified, precision and rounding parameter */ check_vsprintf ("1.9E+07 ", "%#-10.*R*E", 1, MPFR_RNDN, x); check_vsprintf ("2.E+07 ", "%#*.*R*E", -10, 0, MPFR_RNDN, x); check_vsprintf ("2.E+07 ", "%#-10.*R*G", 0, MPFR_RNDN, x); check_vsprintf ("0.E+00 ", "%#-10.*R*E", 0, MPFR_RNDN, z); check_vsprintf ("0. ", "%#-10.*R*F", 0, MPFR_RNDN, z); check_vsprintf ("0. ", "%#-10.*R*G", 0, MPFR_RNDN, z); /* sign or space */ check_sprintf (" 1.899e+07", "% .3RNe", x); check_sprintf (" 2e+07", "% .0RNe", x); /* sign + or -, decimal point, pad with leading zeros */ check_sprintf ("+0001.8E+07", "%0+#11.1RZE", x); check_sprintf ("+00001.E+07", "%0+#11.0RZE", x); check_sprintf ("+0000.0E+00", "%0+#11.1RZE", z); check_sprintf ("+00000000.0", "%0+#11.1RZF", z); /* pad with leading zero */ check_sprintf ("0000001.899347461279296875e+07", "%030RDe", x); check_sprintf ("00000000000000000000000001e+07", "%030.0RDe", x); /* sign or space, decimal point, left justified */ check_sprintf (" 1.8E+07 ", "%- #11.1RDE", x); check_sprintf (" 1.E+07 ", "%- #11.0RDE", x); /* negative numbers */ mpfr_mul_si (x, x, -1, MPFR_RNDD); mpfr_mul_si (z, z, -1, MPFR_RNDD); /* sign + or - */ check_sprintf (" -1.8e+07", "%+10.1RUe", x); check_sprintf (" -1e+07", "%+10.0RUe", x); check_sprintf (" -0e+00", "%+10.0RUe", z); check_sprintf (" -0", "%+10.0RUf", z); /* neighborhood of 1 */ mpfr_set_str (x, "0.99993896484375", 10, MPFR_RNDN); check_sprintf ("9.9993896484375E-01 ", "%-20RE", x); check_sprintf ("9.9993896484375E-01 ", "%-20.RE", x); check_sprintf ("1E+00 ", "%-20.0RE", x); check_sprintf ("1.0E+00 ", "%-20.1RE", x); check_sprintf ("1.00E+00 ", "%-20.2RE", x); check_sprintf ("9.999E-01 ", "%-20.3RE", x); check_sprintf ("9.9994E-01 ", "%-20.4RE", x); check_sprintf ("0.999939 ", "%-20RF", x); check_sprintf ("0.999939 ", "%-20.RF", x); check_sprintf ("1 ", "%-20.0RF", x); check_sprintf ("1.0 ", "%-20.1RF", x); check_sprintf ("1.00 ", "%-20.2RF", x); check_sprintf ("1.000 ", "%-20.3RF", x); check_sprintf ("0.9999 ", "%-20.4RF", x); check_sprintf ("0.999939 ", "%-#20RF", x); check_sprintf ("0.999939 ", "%-#20.RF", x); check_sprintf ("1. ", "%-#20.0RF", x); check_sprintf ("1.0 ", "%-#20.1RF", x); check_sprintf ("1.00 ", "%-#20.2RF", x); check_sprintf ("1.000 ", "%-#20.3RF", x); check_sprintf ("0.9999 ", "%-#20.4RF", x); check_sprintf ("1 ", "%-20.0RG", x); check_sprintf ("1 ", "%-20.1RG", x); check_sprintf ("1 ", "%-20.2RG", x); check_sprintf ("1 ", "%-20.3RG", x); check_sprintf ("0.9999 ", "%-20.4RG", x); check_sprintf ("0.999939 ", "%-#20RG", x); check_sprintf ("0.999939 ", "%-#20.RG", x); check_sprintf ("1. ", "%-#20.0RG", x); check_sprintf ("1. ", "%-#20.1RG", x); check_sprintf ("1.0 ", "%-#20.2RG", x); check_sprintf ("1.00 ", "%-#20.3RG", x); check_sprintf ("0.9999 ", "%-#20.4RG", x); /* multiple of 10 */ mpfr_set_str (x, "1e17", 10, MPFR_RNDN); check_sprintf ("1e+17", "%Re", x); check_sprintf ("1.000e+17", "%.3Re", x); check_sprintf ("100000000000000000", "%.0Rf", x); check_sprintf ("100000000000000000.0", "%.1Rf", x); check_sprintf ("100000000000000000.000000", "%'Rf", x); check_sprintf ("100000000000000000.0", "%'.1Rf", x); mpfr_ui_div (x, 1, x, MPFR_RNDN); /* x=1e-17 */ check_sprintf ("1e-17", "%Re", x); check_sprintf ("0.000000", "%Rf", x); check_sprintf ("1e-17", "%Rg", x); check_sprintf ("0.0", "%.1RDf", x); check_sprintf ("0.0", "%.1RZf", x); check_sprintf ("0.1", "%.1RUf", x); check_sprintf ("0.1", "%.1RYf", x); check_sprintf ("0", "%.0RDf", x); check_sprintf ("0", "%.0RZf", x); check_sprintf ("1", "%.0RUf", x); check_sprintf ("1", "%.0RYf", x); /* multiple of 10 with 'g' style */ mpfr_set_str (x, "10", 10, MPFR_RNDN); check_sprintf ("10", "%Rg", x); check_sprintf ("1e+01", "%.0Rg", x); check_sprintf ("1e+01", "%.1Rg", x); check_sprintf ("10", "%.2Rg", x); mpfr_ui_div (x, 1, x, MPFR_RNDN); check_sprintf ("0.1", "%Rg", x); check_sprintf ("0.1", "%.0Rg", x); check_sprintf ("0.1", "%.1Rg", x); mpfr_set_str (x, "1000", 10, MPFR_RNDN); check_sprintf ("1000", "%Rg", x); check_sprintf ("1e+03", "%.0Rg", x); check_sprintf ("1e+03", "%.3Rg", x); check_sprintf ("1000", "%.4Rg", x); mpfr_ui_div (x, 1, x, MPFR_RNDN); check_sprintf ("0.001", "%Rg", x); check_sprintf ("0.001", "%.0Rg", x); check_sprintf ("0.001", "%.1Rg", x); mpfr_set_str (x, "100000", 10, MPFR_RNDN); check_sprintf ("100000", "%Rg", x); check_sprintf ("1e+05", "%.0Rg", x); check_sprintf ("1e+05", "%.5Rg", x); check_sprintf ("100000", "%.6Rg", x); mpfr_ui_div (x, 1, x, MPFR_RNDN); check_sprintf ("1e-05", "%Rg", x); check_sprintf ("1e-05", "%.0Rg", x); check_sprintf ("1e-05", "%.1Rg", x); /* check rounding mode */ mpfr_set_str (x, "0.0076", 10, MPFR_RNDN); check_sprintf ("0.007", "%.3RDF", x); check_sprintf ("0.007", "%.3RZF", x); check_sprintf ("0.008", "%.3RF", x); check_sprintf ("0.008", "%.3RUF", x); check_sprintf ("0.008", "%.3RYF", x); check_vsprintf ("0.008", "%.3R*F", MPFR_RNDA, x); /* check limit between %f-style and %g-style */ mpfr_set_str (x, "0.0000999", 10, MPFR_RNDN); check_sprintf ("0.0001", "%.0Rg", x); check_sprintf ("9e-05", "%.0RDg", x); check_sprintf ("0.0001", "%.1Rg", x); check_sprintf ("0.0001", "%.2Rg", x); check_sprintf ("9.99e-05", "%.3Rg", x); /* trailing zeros */ mpfr_set_si_2exp (x, -1, -15, MPFR_RNDN); /* x=-2^-15 */ check_sprintf ("-3.0517578125e-05", "%.30Rg", x); check_sprintf ("-3.051757812500000000000000000000e-05", "%.30Re", x); check_sprintf ("-3.05175781250000000000000000000e-05", "%#.30Rg", x); check_sprintf ("-0.000030517578125000000000000000", "%.30Rf", x); /* bug 20081023 */ check_sprintf ("-3.0517578125e-05", "%.30Rg", x); mpfr_set_str (x, "1.9999", 10, MPFR_RNDN); check_sprintf ("1.999900 ", "%-#10.7RG", x); check_sprintf ("1.9999 ", "%-10.7RG", x); mpfr_set_ui (x, 1, MPFR_RNDN); check_sprintf ("1.00000000000000000000000000000", "%#.30Rg", x); check_sprintf ("1", "%.30Rg", x); mpfr_set_ui (x, 0, MPFR_RNDN); check_sprintf ("0.000000000000000000000000000000", "%#.30Rg", x); check_sprintf ("0", "%.30Rg", x); /* following tests with precision 53 bits */ mpfr_set_prec (x, 53); /* Exponent zero has a plus sign */ mpfr_set_str (x, "-9.95645044213728791504536275169812142849e-01", 10, MPFR_RNDN); check_sprintf ("-1.0e+00", "%- #0.1Re", x); /* Decimal point and no figure after it with '#' flag and 'G' style */ mpfr_set_str (x, "-9.90597761233942053494e-01", 10, MPFR_RNDN); check_sprintf ("-1.", "%- #0.1RG", x); /* precision zero */ mpfr_set_d (x, 9.5, MPFR_RNDN); check_sprintf ("9", "%.0RDf", x); check_sprintf ("10", "%.0RUf", x); mpfr_set_d (x, 19.5, MPFR_RNDN); check_sprintf ("19", "%.0RDf", x); check_sprintf ("20", "%.0RUf", x); mpfr_set_d (x, 99.5, MPFR_RNDN); check_sprintf ("99", "%.0RDf", x); check_sprintf ("100", "%.0RUf", x); mpfr_set_d (x, -9.5, MPFR_RNDN); check_sprintf ("-10", "%.0RDf", x); check_sprintf ("-10", "%.0RYf", x); check_sprintf ("-10", "%.0Rf", x); check_sprintf ("-1e+01", "%.0Re", x); check_sprintf ("-1e+01", "%.0Rg", x); mpfr_set_ui_2exp (x, 1, -1, MPFR_RNDN); check_sprintf ("0", "%.0Rf", x); check_sprintf ("5e-01", "%.0Re", x); check_sprintf ("0.5", "%.0Rg", x); mpfr_set_ui_2exp (x, 3, -1, MPFR_RNDN); check_sprintf ("2", "%.0Rf", x); mpfr_set_ui_2exp (x, 5, -1, MPFR_RNDN); check_sprintf ("2", "%.0Rf", x); mpfr_set_ui (x, 0x1f, MPFR_RNDN); check_sprintf ("0x1p+5", "%.0Ra", x); mpfr_set_ui (x, 3, MPFR_RNDN); check_sprintf ("1p+2", "%.0Rb", x); /* round to next ten power with %f but not with %g */ mpfr_set_str (x, "-6.64464380544039223686e-02", 10, MPFR_RNDN); check_sprintf ("-0.1", "%.1Rf", x); check_sprintf ("-0.0", "%.1RZf", x); check_sprintf ("-0.07", "%.1Rg", x); check_sprintf ("-0.06", "%.1RZg", x); /* round to next ten power and do not remove trailing zeros */ mpfr_set_str (x, "9.98429393291486722006e-02", 10, MPFR_RNDN); check_sprintf ("0.1", "%#.1Rg", x); check_sprintf ("0.10", "%#.2Rg", x); check_sprintf ("0.099", "%#.2RZg", x); /* Halfway cases */ mpfr_set_str (x, "1.5", 10, MPFR_RNDN); check_sprintf ("2e+00", "%.0Re", x); mpfr_set_str (x, "2.5", 10, MPFR_RNDN); check_sprintf ("2e+00", "%.0Re", x); mpfr_set_str (x, "9.5", 10, MPFR_RNDN); check_sprintf ("1e+01", "%.0Re", x); mpfr_set_str (x, "1.25", 10, MPFR_RNDN); check_sprintf ("1.2e+00", "%.1Re", x); mpfr_set_str (x, "1.75", 10, MPFR_RNDN); check_sprintf ("1.8e+00", "%.1Re", x); mpfr_set_str (x, "-0.5", 10, MPFR_RNDN); check_sprintf ("-0", "%.0Rf", x); mpfr_set_str (x, "1.25", 10, MPFR_RNDN); check_sprintf ("1.2", "%.1Rf", x); mpfr_set_str (x, "1.75", 10, MPFR_RNDN); check_sprintf ("1.8", "%.1Rf", x); mpfr_set_str (x, "1.5", 10, MPFR_RNDN); check_sprintf ("2", "%.1Rg", x); mpfr_set_str (x, "2.5", 10, MPFR_RNDN); check_sprintf ("2", "%.1Rg", x); mpfr_set_str (x, "9.25", 10, MPFR_RNDN); check_sprintf ("9.2", "%.2Rg", x); mpfr_set_str (x, "9.75", 10, MPFR_RNDN); check_sprintf ("9.8", "%.2Rg", x); /* assertion failure in r6320 */ mpfr_set_str (x, "-9.996", 10, MPFR_RNDN); check_sprintf ("-10.0", "%.1Rf", x); mpfr_clears (x, z, (mpfr_ptr) 0); return 0; }

/* Assumes that the exponent range has already been extended and if y is an integer, then the result is not exact in unbounded exponent range. */ int mpfr_pow_general (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode, int y_is_integer, mpfr_save_expo_t *expo) { mpfr_t t, u, k, absx; int neg_result = 0; int k_non_zero = 0; int check_exact_case = 0; int inexact; /* Declaration of the size variable */ mpfr_prec_t Nz = MPFR_PREC(z); /* target precision */ mpfr_prec_t Nt; /* working precision */ mpfr_exp_t err; /* error */ MPFR_ZIV_DECL (ziv_loop); MPFR_LOG_FUNC (("x[%Pu]=%.*Rg y[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, mpfr_get_prec (y), mpfr_log_prec, y, rnd_mode), ("z[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (z), mpfr_log_prec, z, inexact)); /* We put the absolute value of x in absx, pointing to the significand of x to avoid allocating memory for the significand of absx. */ MPFR_ALIAS(absx, x, /*sign=*/ 1, /*EXP=*/ MPFR_EXP(x)); /* We will compute the absolute value of the result. So, let's invert the rounding mode if the result is negative. */ if (MPFR_IS_NEG (x) && is_odd (y)) { neg_result = 1; rnd_mode = MPFR_INVERT_RND (rnd_mode); } /* compute the precision of intermediary variable */ /* the optimal number of bits : see algorithms.tex */ Nt = Nz + 5 + MPFR_INT_CEIL_LOG2 (Nz); /* initialize of intermediary variable */ mpfr_init2 (t, Nt); MPFR_ZIV_INIT (ziv_loop, Nt); for (;;) { MPFR_BLOCK_DECL (flags1); /* compute exp(y*ln|x|), using MPFR_RNDU to get an upper bound, so that we can detect underflows. */ mpfr_log (t, absx, MPFR_IS_NEG (y) ? MPFR_RNDD : MPFR_RNDU); /* ln|x| */ mpfr_mul (t, y, t, MPFR_RNDU); /* y*ln|x| */ if (k_non_zero) { MPFR_LOG_MSG (("subtract k * ln(2)\n", 0)); mpfr_const_log2 (u, MPFR_RNDD); mpfr_mul (u, u, k, MPFR_RNDD); /* Error on u = k * log(2): < k * 2^(-Nt) < 1. */ mpfr_sub (t, t, u, MPFR_RNDU); MPFR_LOG_MSG (("t = y * ln|x| - k * ln(2)\n", 0)); MPFR_LOG_VAR (t); } /* estimate of the error -- see pow function in algorithms.tex. The error on t is at most 1/2 + 3*2^(EXP(t)+1) ulps, which is <= 2^(EXP(t)+3) for EXP(t) >= -1, and <= 2 ulps for EXP(t) <= -2. Additional error if k_no_zero: treal = t * errk, with 1 - |k| * 2^(-Nt) <= exp(-|k| * 2^(-Nt)) <= errk <= 1, i.e., additional absolute error <= 2^(EXP(k)+EXP(t)-Nt). Total error <= 2^err1 + 2^err2 <= 2^(max(err1,err2)+1). */ err = MPFR_NOTZERO (t) && MPFR_GET_EXP (t) >= -1 ? MPFR_GET_EXP (t) + 3 : 1; if (k_non_zero) { if (MPFR_GET_EXP (k) > err) err = MPFR_GET_EXP (k); err++; } MPFR_BLOCK (flags1, mpfr_exp (t, t, MPFR_RNDN)); /* exp(y*ln|x|)*/ /* We need to test */ if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (t) || MPFR_UNDERFLOW (flags1))) { mpfr_prec_t Ntmin; MPFR_BLOCK_DECL (flags2); MPFR_ASSERTN (!k_non_zero); MPFR_ASSERTN (!MPFR_IS_NAN (t)); /* Real underflow? */ if (MPFR_IS_ZERO (t)) { /* Underflow. We computed rndn(exp(t)), where t >= y*ln|x|. Therefore rndn(|x|^y) = 0, and we have a real underflow on |x|^y. */ inexact = mpfr_underflow (z, rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode, MPFR_SIGN_POS); if (expo != NULL) MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW); break; } /* Real overflow? */ if (MPFR_IS_INF (t)) { /* Note: we can probably use a low precision for this test. */ mpfr_log (t, absx, MPFR_IS_NEG (y) ? MPFR_RNDU : MPFR_RNDD); mpfr_mul (t, y, t, MPFR_RNDD); /* y * ln|x| */ MPFR_BLOCK (flags2, mpfr_exp (t, t, MPFR_RNDD)); /* t = lower bound on exp(y * ln|x|) */ if (MPFR_OVERFLOW (flags2)) { /* We have computed a lower bound on |x|^y, and it overflowed. Therefore we have a real overflow on |x|^y. */ inexact = mpfr_overflow (z, rnd_mode, MPFR_SIGN_POS); if (expo != NULL) MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW); break; } } k_non_zero = 1; Ntmin = sizeof(mpfr_exp_t) * CHAR_BIT; if (Ntmin > Nt) { Nt = Ntmin; mpfr_set_prec (t, Nt); } mpfr_init2 (u, Nt); mpfr_init2 (k, Ntmin); mpfr_log2 (k, absx, MPFR_RNDN); mpfr_mul (k, y, k, MPFR_RNDN); mpfr_round (k, k); MPFR_LOG_VAR (k); /* |y| < 2^Ntmin, therefore |k| < 2^Nt. */ continue; } if (MPFR_LIKELY (MPFR_CAN_ROUND (t, Nt - err, Nz, rnd_mode))) { inexact = mpfr_set (z, t, rnd_mode); break; } /* check exact power, except when y is an integer (since the exact cases for y integer have already been filtered out) */ if (check_exact_case == 0 && ! y_is_integer) { if (mpfr_pow_is_exact (z, absx, y, rnd_mode, &inexact)) break; check_exact_case = 1; } /* reactualisation of the precision */ MPFR_ZIV_NEXT (ziv_loop, Nt); mpfr_set_prec (t, Nt); if (k_non_zero) mpfr_set_prec (u, Nt); } MPFR_ZIV_FREE (ziv_loop); if (k_non_zero) { int inex2; long lk; /* The rounded result in an unbounded exponent range is z * 2^k. As * MPFR chooses underflow after rounding, the mpfr_mul_2si below will * correctly detect underflows and overflows. However, in rounding to * nearest, if z * 2^k = 2^(emin - 2), then the double rounding may * affect the result. We need to cope with that before overwriting z. * This can occur only if k < 0 (this test is necessary to avoid a * potential integer overflow). * If inexact >= 0, then the real result is <= 2^(emin - 2), so that * o(2^(emin - 2)) = +0 is correct. If inexact < 0, then the real * result is > 2^(emin - 2) and we need to round to 2^(emin - 1). */ MPFR_ASSERTN (MPFR_EXP_MAX <= LONG_MAX); lk = mpfr_get_si (k, MPFR_RNDN); /* Due to early overflow detection, |k| should not be much larger than * MPFR_EMAX_MAX, and as MPFR_EMAX_MAX <= MPFR_EXP_MAX/2 <= LONG_MAX/2, * an overflow should not be possible in mpfr_get_si (and lk is exact). * And one even has the following assertion. TODO: complete proof. */ MPFR_ASSERTD (lk > LONG_MIN && lk < LONG_MAX); /* Note: even in case of overflow (lk inexact), the code is correct. * Indeed, for the 3 occurrences of lk: * - The test lk < 0 is correct as sign(lk) = sign(k). * - In the test MPFR_GET_EXP (z) == __gmpfr_emin - 1 - lk, * if lk is inexact, then lk = LONG_MIN <= MPFR_EXP_MIN * (the minimum value of the mpfr_exp_t type), and * __gmpfr_emin - 1 - lk >= MPFR_EMIN_MIN - 1 - 2 * MPFR_EMIN_MIN * >= - MPFR_EMIN_MIN - 1 = MPFR_EMAX_MAX - 1. However, from the * choice of k, z has been chosen to be around 1, so that the * result of the test is false, as if lk were exact. * - In the mpfr_mul_2si (z, z, lk, rnd_mode), if lk is inexact, * then |lk| >= LONG_MAX >= MPFR_EXP_MAX, and as z is around 1, * mpfr_mul_2si underflows or overflows in the same way as if * lk were exact. * TODO: give a bound on |t|, then on |EXP(z)|. */ if (rnd_mode == MPFR_RNDN && inexact < 0 && lk < 0 && MPFR_GET_EXP (z) == __gmpfr_emin - 1 - lk && mpfr_powerof2_raw (z)) { /* Rounding to nearest, real result > z * 2^k = 2^(emin - 2), * underflow case: as the minimum precision is > 1, we will * obtain the correct result and exceptions by replacing z by * nextabove(z). */ MPFR_STAT_STATIC_ASSERT (MPFR_PREC_MIN > 1); mpfr_nextabove (z); } MPFR_CLEAR_FLAGS (); inex2 = mpfr_mul_2si (z, z, lk, rnd_mode); if (inex2) /* underflow or overflow */ { inexact = inex2; if (expo != NULL) MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, __gmpfr_flags); } mpfr_clears (u, k, (mpfr_ptr) 0); } mpfr_clear (t); /* update the sign of the result if x was negative */ if (neg_result) { MPFR_SET_NEG(z); inexact = -inexact; } return inexact; }

static int hexadecimal (void) { mpfr_t x, z; mpfr_inits2 (64, x, z, (mpfr_ptr) 0); /* special */ mpfr_set_inf (x, 1); check_sprintf (pinf_str, "%Ra", x); check_sprintf (pinf_str, "%RUa", x); check_sprintf (pinf_str, "%RDa", x); check_sprintf (pinf_uc_str, "%RA", x); check_sprintf (pinf_uc_str, "%RYA", x); check_sprintf (pinf_uc_str, "%RZA", x); check_sprintf (pinf_uc_str, "%RNA", x); mpfr_set_inf (x, -1); check_sprintf (minf_str, "%Ra", x); check_sprintf (minf_str, "%RYa", x); check_sprintf (minf_str, "%RZa", x); check_sprintf (minf_str, "%RNa", x); check_sprintf (minf_uc_str, "%RA", x); check_sprintf (minf_uc_str, "%RUA", x); check_sprintf (minf_uc_str, "%RDA", x); mpfr_set_nan (x); check_sprintf (nan_str, "%Ra", x); check_sprintf (nan_uc_str, "%RA", x); /* regular numbers */ mpfr_set_str (x, "FEDCBA9.87654321", 16, MPFR_RNDN); mpfr_set_ui (z, 0, MPFR_RNDZ); /* simplest case right justified */ check_sprintf (" 0xf.edcba987654321p+24", "%25Ra", x); check_sprintf (" 0xf.edcba987654321p+24", "%25RUa", x); check_sprintf (" 0xf.edcba987654321p+24", "%25RDa", x); check_sprintf (" 0xf.edcba987654321p+24", "%25RYa", x); check_sprintf (" 0xf.edcba987654321p+24", "%25RZa", x); check_sprintf (" 0xf.edcba987654321p+24", "%25RNa", x); check_sprintf (" 0x1p+28", "%25.0Ra", x); check_sprintf (" 0x0p+0", "%25.0Ra", z); /* sign or space, pad with leading zeros */ check_sprintf (" 0X00F.EDCBA987654321P+24", "% 025RA", x); check_sprintf (" 0X000000000000000001P+28", "% 025.0RA", x); check_sprintf (" 0X0000000000000000000P+0", "% 025.0RA", z); /* sign + or -, left justified */ check_sprintf ("+0xf.edcba987654321p+24 ", "%+-25Ra", x); check_sprintf ("+0x1p+28 ", "%+-25.0Ra", x); check_sprintf ("+0x0p+0 ", "%+-25.0Ra", z); /* decimal point, left justified, precision and rounding parameter */ check_vsprintf ("0XF.FP+24 ", "%#-10.*R*A", 1, MPFR_RNDN, x); check_vsprintf ("0X1.P+28 ", "%#-10.*R*A", 0, MPFR_RNDN, x); check_vsprintf ("0X0.P+0 ", "%#-10.*R*A", 0, MPFR_RNDN, z); /* sign or space */ check_sprintf (" 0xf.eddp+24", "% .3RNa", x); check_sprintf (" 0x1p+28", "% .0RNa", x); /* sign + or -, decimal point, pad with leading zeros */ check_sprintf ("+0X0F.EP+24", "%0+#11.1RZA", x); check_sprintf ("+0X00F.P+24", "%0+#11.0RZA", x); check_sprintf ("+0X000.0P+0", "%0+#11.1RZA", z); /* pad with leading zero */ check_sprintf ("0x0000f.edcba987654321p+24", "%026RDa", x); check_sprintf ("0x0000000000000000000fp+24", "%026.0RDa", x); /* sign or space, decimal point, left justified */ check_sprintf (" 0XF.EP+24 " , "%- #11.1RDA", x); check_sprintf (" 0XF.P+24 " , "%- #11.0RDA", x); mpfr_mul_si (x, x, -1, MPFR_RNDD); mpfr_mul_si (z, z, -1, MPFR_RNDD); /* sign + or - */ check_sprintf ("-0xf.ep+24", "%+10.1RUa", x); check_sprintf (" -0xfp+24", "%+10.0RUa", x); check_sprintf (" -0x0p+0", "%+10.0RUa", z); /* rounding bit is zero */ mpfr_set_str (x, "0xF.7", 16, MPFR_RNDN); check_sprintf ("0XFP+0", "%.0RNA", x); /* tie case in round to nearest mode */ mpfr_set_str (x, "0x0.8800000000000000p+3", 16, MPFR_RNDN); check_sprintf ("0x9.p-1", "%#.0RNa", x); mpfr_set_str (x, "-0x0.9800000000000000p+3", 16, MPFR_RNDN); check_sprintf ("-0xap-1", "%.0RNa", x); /* trailing zeros in fractional part */ check_sprintf ("-0X4.C0000000000000000000P+0", "%.20RNA", x); /* rounding bit is one and the first non zero bit is far away */ mpfr_set_prec (x, 1024); mpfr_set_ui_2exp (x, 29, -1, MPFR_RNDN); mpfr_nextabove (x); check_sprintf ("0XFP+0", "%.0RNA", x); /* with more than one limb */ mpfr_set_prec (x, 300); mpfr_set_str (x, "0xf.ffffffffffffffffffffffffffffffffffffffffffffffffffff" "fffffffffffffffff", 16, MPFR_RNDN); check_sprintf ("0x1p+4 [300]", "%.0RNa [300]", x); check_sprintf ("0xfp+0 [300]", "%.0RZa [300]", x); check_sprintf ("0x1p+4 [300]", "%.0RYa [300]", x); check_sprintf ("0xfp+0 [300]", "%.0RDa [300]", x); check_sprintf ("0x1p+4 [300]", "%.0RUa [300]", x); check_sprintf ("0x1.0000000000000000000000000000000000000000p+4", "%.40RNa", x); check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffffffp+0", "%.40RZa", x); check_sprintf ("0x1.0000000000000000000000000000000000000000p+4", "%.40RYa", x); check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffffffp+0", "%.40RDa", x); check_sprintf ("0x1.0000000000000000000000000000000000000000p+4", "%.40RUa", x); mpfr_set_str (x, "0xf.7fffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffff", 16, MPFR_RNDN); check_sprintf ("0XFP+0", "%.0RNA", x); check_sprintf ("0XFP+0", "%.0RZA", x); check_sprintf ("0X1P+4", "%.0RYA", x); check_sprintf ("0XFP+0", "%.0RDA", x); check_sprintf ("0X1P+4", "%.0RUA", x); check_sprintf ("0XF.8P+0", "%.1RNA", x); check_sprintf ("0XF.7P+0", "%.1RZA", x); check_sprintf ("0XF.8P+0", "%.1RYA", x); check_sprintf ("0XF.7P+0", "%.1RDA", x); check_sprintf ("0XF.8P+0", "%.1RUA", x); /* do not round up to the next power of the base */ mpfr_set_str (x, "0xf.fffffffffffffffffffffffffffffffffffffeffffffffffffff" "ffffffffffffffffff", 16, MPFR_RNDN); check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0", "%.40RNa", x); check_sprintf ("0xf.fffffffffffffffffffffffffffffffffffffeffp+0", "%.40RZa", x); check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0", "%.40RYa", x); check_sprintf ("0xf.fffffffffffffffffffffffffffffffffffffeffp+0", "%.40RDa", x); check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0", "%.40RUa", x); mpfr_clears (x, z, (mpfr_ptr) 0); return 0; }

int main (void) { mpfr_t xx, yy; int c; tests_start_mpfr (); mpfr_init2 (xx, 2); mpfr_init2 (yy, 2); mpfr_clear_erangeflag (); MPFR_SET_NAN (xx); MPFR_SET_NAN (yy); if (mpfr_cmpabs (xx, yy) != 0) ERROR ("mpfr_cmpabs (NAN,NAN) returns non-zero\n"); if (!mpfr_erangeflag_p ()) ERROR ("mpfr_cmpabs (NAN,NAN) doesn't set erange flag\n"); mpfr_set_str_binary (xx, "0.10E0"); mpfr_set_str_binary (yy, "-0.10E0"); if (mpfr_cmpabs (xx, yy) != 0) ERROR ("mpfr_cmpabs (xx, yy) returns non-zero for prec=2\n"); mpfr_set_prec (xx, 65); mpfr_set_prec (yy, 65); mpfr_set_str_binary (xx, "-0.10011010101000110101010000000011001001001110001011101011111011101E623"); mpfr_set_str_binary (yy, "0.10011010101000110101010000000011001001001110001011101011111011100E623"); if (mpfr_cmpabs (xx, yy) <= 0) ERROR ("Error (1) in mpfr_cmpabs\n"); mpfr_set_str_binary (xx, "-0.10100010001110110111000010001000010011111101000100011101000011100"); mpfr_set_str_binary (yy, "-0.10100010001110110111000010001000010011111101000100011101000011011"); if (mpfr_cmpabs (xx, yy) <= 0) ERROR ("Error (2) in mpfr_cmpabs\n"); mpfr_set_prec (xx, 160); mpfr_set_prec (yy, 160); mpfr_set_str_binary (xx, "0.1E1"); mpfr_set_str_binary (yy, "-0.1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000110001110100"); if (mpfr_cmpabs (xx, yy) <= 0) ERROR ("Error (3) in mpfr_cmpabs\n"); mpfr_set_prec(xx, 53); mpfr_set_prec(yy, 200); mpfr_set_ui (xx, 1, (mpfr_rnd_t) 0); mpfr_set_ui (yy, 1, (mpfr_rnd_t) 0); if (mpfr_cmpabs(xx, yy) != 0) ERROR ("Error in mpfr_cmpabs: 1.0 != 1.0\n"); mpfr_set_prec (yy, 31); mpfr_set_str (xx, "-1.0000000002", 10, (mpfr_rnd_t) 0); mpfr_set_ui (yy, 1, (mpfr_rnd_t) 0); if (!(mpfr_cmpabs(xx,yy)>0)) ERROR ("Error in mpfr_cmpabs: not 1.0000000002 > 1.0\n"); mpfr_set_prec(yy, 53); mpfr_set_ui(xx, 0, MPFR_RNDN); mpfr_set_str (yy, "-0.1", 10, MPFR_RNDN); if (mpfr_cmpabs(xx, yy) >= 0) ERROR ("Error in mpfr_cmpabs(0.0, 0.1)\n"); mpfr_set_inf (xx, -1); mpfr_set_str (yy, "23489745.0329", 10, MPFR_RNDN); if (mpfr_cmpabs(xx, yy) <= 0) ERROR ("Error in mpfr_cmp(-Inf, 23489745.0329)\n"); mpfr_set_inf (xx, 1); mpfr_set_inf (yy, -1); if (mpfr_cmpabs(xx, yy) != 0) ERROR ("Error in mpfr_cmpabs(Inf, -Inf)\n"); mpfr_set_inf (yy, -1); mpfr_set_str (xx, "2346.09234", 10, MPFR_RNDN); if (mpfr_cmpabs (xx, yy) >= 0) ERROR ("Error in mpfr_cmpabs(-Inf, 2346.09234)\n"); mpfr_set_prec (xx, 2); mpfr_set_prec (yy, 128); mpfr_set_str_binary (xx, "0.1E10"); mpfr_set_str_binary (yy, "0.100000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000001E10"); if (mpfr_cmpabs (xx, yy) >= 0) ERROR ("Error in mpfr_cmpabs(10.235, 2346.09234)\n"); mpfr_swap (xx, yy); if (mpfr_cmpabs(xx, yy) <= 0) ERROR ("Error in mpfr_cmpabs(2346.09234, 10.235)\n"); mpfr_swap (xx, yy); /* Check for NAN */ mpfr_set_nan (xx); mpfr_clear_erangeflag (); c = (mpfr_cmp) (xx, yy); if (c != 0 || !mpfr_erangeflag_p () ) { printf ("NAN error (1)\n"); exit (1); } mpfr_clear_erangeflag (); c = (mpfr_cmp) (yy, xx); if (c != 0 || !mpfr_erangeflag_p () ) { printf ("NAN error (2)\n"); exit (1); } mpfr_clear_erangeflag (); c = (mpfr_cmp) (xx, xx); if (c != 0 || !mpfr_erangeflag_p () ) { printf ("NAN error (3)\n"); exit (1); } mpfr_clear (xx); mpfr_clear (yy); tests_end_mpfr (); return 0; }

/* 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. 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, mp_rnd_t r) { mpfr_t s, c, P, Q, t, iz, err_t, err_s, err_u; mp_prec_t w; long k; int inex, stop, diverge = 0; mp_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, GMP_RNDN); if (MPFR_IS_NEG(z)) mpfr_neg (s, s, GMP_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, GMP_RNDN); mpfr_sub (c, s, c, GMP_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, GMP_RNDN); /* err <= 1 */ mpfr_div_2ui (iz, iz, 3, GMP_RNDN); /* compute P and Q */ mpfr_set_ui (P, 1, GMP_RNDN); mpfr_set_ui (Q, 0, GMP_RNDN); mpfr_set_ui (t, 1, GMP_RNDN); /* current term */ mpfr_set_ui (err_t, 0, GMP_RNDN); /* error on t */ mpfr_set_ui (err_s, 0, GMP_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, GMP_RNDN); /* err <= err_k + 1 */ mpfr_mul_si (t, t, 2 * (n - k) + 1, GMP_RNDN); /* err <= err_k + 2 */ mpfr_div_ui (t, t, k, GMP_RNDN); /* err <= err_k + 3 */ mpfr_mul (t, t, iz, GMP_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) ? GMP_RNDU : GMP_RNDD); mpfr_abs (err_t, err_t, GMP_RNDN); /* exact */ /* the absolute error on t is bounded by err_t * 2^(-w) */ mpfr_abs (err_u, t, GMP_RNDU); mpfr_mul_2ui (err_u, err_u, w, GMP_RNDU); /* t * 2^w */ mpfr_add (err_u, err_u, err_t, GMP_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, GMP_RNDU); if (MPFR_IS_POS(t)) mpfr_add (err_s, err_s, t, GMP_RNDU); else mpfr_sub (err_s, err_s, t, GMP_RNDU); mpfr_mul_2ui (err_s, err_s, w, GMP_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, GMP_RNDN); else mpfr_sub (Q, Q, t, GMP_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, GMP_RNDN); else mpfr_sub (P, P, t, GMP_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, GMP_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, GMP_RNDN); /* Q * (sin - cos) */ mpfr_mul (s, s, P, GMP_RNDN); /* P * (sin + cos) */ #else mpfr_mul (c, c, P, GMP_RNDN); /* P * (sin - cos) */ mpfr_mul (s, s, Q, GMP_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, GMP_RNDN); #else mpfr_add (s, s, c, GMP_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, GMP_RNDN); /* P * (sin - cos) */ mpfr_mul (s, s, Q, GMP_RNDN); /* Q * (sin + cos) */ #else mpfr_mul (c, c, Q, GMP_RNDN); /* Q * (sin - cos) */ mpfr_mul (s, s, P, GMP_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, GMP_RNDN); #else mpfr_sub (s, c, s, GMP_RNDN); #endif } if ((n & 2) != 0) mpfr_neg (s, s, GMP_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, GMP_RNDN); /* Pi, err <= 1 */ mpfr_mul (c, c, z, GMP_RNDN); /* err <= 2 */ mpfr_si_div (c, MPFR_IS_POS(z) ? 1 : -1, c, GMP_RNDN); /* err <= 3 */ mpfr_sqrt (c, c, GMP_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) ? GMP_RNDU : GMP_RNDD); mpfr_abs (err_t, err_t, GMP_RNDU); mpfr_mul_ui (err_t, err_t, 3, GMP_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, GMP_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) ? mpfr_set (res, c, r) : mpfr_neg (res, c, r); mpfr_clear (c); return inex; }

int main (void) { mpfr_t x; int r; mpfr_prec_t p; unsigned long k; tests_start_mpfr (); special (); mpfr_init (x); for (p = 2; p < 100; p++) { mpfr_set_prec (x, p); for (r = 0; r < MPFR_RND_MAX; r++) { mpfr_set_ui (x, 1, MPFR_RNDN); k = 2 + randlimb () % 4; /* 2 <= k <= 5 */ mpfr_root (x, x, k, (mpfr_rnd_t) r); if (mpfr_cmp_ui (x, 1)) { printf ("Error in mpfr_root(%lu) for x=1, rnd=%s\ngot ", k, mpfr_print_rnd_mode ((mpfr_rnd_t) r)); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); printf ("\n"); exit (1); } mpfr_set_si (x, -1, MPFR_RNDN); if (k % 2) { mpfr_root (x, x, k, (mpfr_rnd_t) r); if (mpfr_cmp_si (x, -1)) { printf ("Error in mpfr_root(%lu) for x=-1, rnd=%s\ngot ", k, mpfr_print_rnd_mode ((mpfr_rnd_t) r)); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); printf ("\n"); exit (1); } } if (p >= 5) { int i; for (i = -12; i <= 12; i++) { mpfr_set_ui (x, 27, MPFR_RNDN); mpfr_mul_2si (x, x, 3*i, MPFR_RNDN); mpfr_root (x, x, 3, MPFR_RNDN); if (mpfr_cmp_si_2exp (x, 3, i)) { printf ("Error in mpfr_root(3) for " "x = 27.0 * 2^(%d), rnd=%s\ngot ", 3*i, mpfr_print_rnd_mode ((mpfr_rnd_t) r)); mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); printf ("\ninstead of 3 * 2^(%d)\n", i); exit (1); } } } } } mpfr_clear (x); test_generic_ui (2, 200, 30); tests_end_mpfr (); return 0; }

int mpc_acos (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd) { int inex_re, inex_im, inex; mpfr_prec_t p_re, p_im, p; mpc_t z1; mpfr_t pi_over_2; mpfr_exp_t e1, e2; mpfr_rnd_t rnd_im; mpc_rnd_t rnd1; inex_re = 0; inex_im = 0; /* special values */ if (mpfr_nan_p (mpc_realref (op)) || mpfr_nan_p (mpc_imagref (op))) { if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op))) { mpfr_set_inf (mpc_imagref (rop), mpfr_signbit (mpc_imagref (op)) ? +1 : -1); mpfr_set_nan (mpc_realref (rop)); } else if (mpfr_zero_p (mpc_realref (op))) { inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd)); mpfr_set_nan (mpc_imagref (rop)); } else { mpfr_set_nan (mpc_realref (rop)); mpfr_set_nan (mpc_imagref (rop)); } return MPC_INEX (inex_re, 0); } if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op))) { if (mpfr_inf_p (mpc_realref (op))) { if (mpfr_inf_p (mpc_imagref (op))) { if (mpfr_sgn (mpc_realref (op)) > 0) { inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd)); mpfr_div_2ui (mpc_realref (rop), mpc_realref (rop), 1, GMP_RNDN); } else { /* the real part of the result is 3*pi/4 a = o(pi) error(a) < 1 ulp(a) b = o(3*a) error(b) < 2 ulp(b) c = b/4 exact thus 1 bit is lost */ mpfr_t x; mpfr_prec_t prec; int ok; mpfr_init (x); prec = mpfr_get_prec (mpc_realref (rop)); p = prec; do { p += mpc_ceil_log2 (p); mpfr_set_prec (x, p); mpfr_const_pi (x, GMP_RNDD); mpfr_mul_ui (x, x, 3, GMP_RNDD); ok = mpfr_can_round (x, p - 1, GMP_RNDD, MPC_RND_RE (rnd), prec+(MPC_RND_RE (rnd) == GMP_RNDN)); } while (ok == 0); inex_re = mpfr_div_2ui (mpc_realref (rop), x, 2, MPC_RND_RE (rnd)); mpfr_clear (x); } } else { if (mpfr_sgn (mpc_realref (op)) > 0) mpfr_set_ui (mpc_realref (rop), 0, GMP_RNDN); else inex_re = mpfr_const_pi (mpc_realref (rop), MPC_RND_RE (rnd)); } } else inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd)); mpfr_set_inf (mpc_imagref (rop), mpfr_signbit (mpc_imagref (op)) ? +1 : -1); return MPC_INEX (inex_re, 0); } /* pure real argument */ if (mpfr_zero_p (mpc_imagref (op))) { int s_im; s_im = mpfr_signbit (mpc_imagref (op)); if (mpfr_cmp_ui (mpc_realref (op), 1) > 0) { if (s_im) inex_im = mpfr_acosh (mpc_imagref (rop), mpc_realref (op), MPC_RND_IM (rnd)); else inex_im = -mpfr_acosh (mpc_imagref (rop), mpc_realref (op), INV_RND (MPC_RND_IM (rnd))); mpfr_set_ui (mpc_realref (rop), 0, GMP_RNDN); } else if (mpfr_cmp_si (mpc_realref (op), -1) < 0) { mpfr_t minus_op_re; minus_op_re[0] = mpc_realref (op)[0]; MPFR_CHANGE_SIGN (minus_op_re); if (s_im) inex_im = mpfr_acosh (mpc_imagref (rop), minus_op_re, MPC_RND_IM (rnd)); else inex_im = -mpfr_acosh (mpc_imagref (rop), minus_op_re, INV_RND (MPC_RND_IM (rnd))); inex_re = mpfr_const_pi (mpc_realref (rop), MPC_RND_RE (rnd)); } else { inex_re = mpfr_acos (mpc_realref (rop), mpc_realref (op), MPC_RND_RE (rnd)); mpfr_set_ui (mpc_imagref (rop), 0, MPC_RND_IM (rnd)); } if (!s_im) mpc_conj (rop, rop, MPC_RNDNN); return MPC_INEX (inex_re, inex_im); } /* pure imaginary argument */ if (mpfr_zero_p (mpc_realref (op))) { inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd)); inex_im = -mpfr_asinh (mpc_imagref (rop), mpc_imagref (op), INV_RND (MPC_RND_IM (rnd))); mpc_conj (rop,rop, MPC_RNDNN); return MPC_INEX (inex_re, inex_im); } /* regular complex argument: acos(z) = Pi/2 - asin(z) */ p_re = mpfr_get_prec (mpc_realref(rop)); p_im = mpfr_get_prec (mpc_imagref(rop)); p = p_re; mpc_init3 (z1, p, p_im); /* we round directly the imaginary part to p_im, with rounding mode opposite to rnd_im */ rnd_im = MPC_RND_IM(rnd); /* the imaginary part of asin(z) has the same sign as Im(z), thus if Im(z) > 0 and rnd_im = RNDZ, we want to round the Im(asin(z)) to -Inf so that -Im(asin(z)) is rounded to zero */ if (rnd_im == GMP_RNDZ) rnd_im = mpfr_sgn (mpc_imagref(op)) > 0 ? GMP_RNDD : GMP_RNDU; else rnd_im = rnd_im == GMP_RNDU ? GMP_RNDD : rnd_im == GMP_RNDD ? GMP_RNDU : rnd_im; /* both RNDZ and RNDA map to themselves for -asin(z) */ rnd1 = MPC_RND (GMP_RNDN, rnd_im); mpfr_init2 (pi_over_2, p); for (;;) { p += mpc_ceil_log2 (p) + 3; mpfr_set_prec (mpc_realref(z1), p); mpfr_set_prec (pi_over_2, p); set_pi_over_2 (pi_over_2, +1, GMP_RNDN); e1 = 1; /* Exp(pi_over_2) */ inex = mpc_asin (z1, op, rnd1); /* asin(z) */ MPC_ASSERT (mpfr_sgn (mpc_imagref(z1)) * mpfr_sgn (mpc_imagref(op)) > 0); inex_im = MPC_INEX_IM(inex); /* inex_im is in {-1, 0, 1} */ e2 = mpfr_get_exp (mpc_realref(z1)); mpfr_sub (mpc_realref(z1), pi_over_2, mpc_realref(z1), GMP_RNDN); if (!mpfr_zero_p (mpc_realref(z1))) { /* the error on x=Re(z1) is bounded by 1/2 ulp(x) + 2^(e1-p-1) + 2^(e2-p-1) */ e1 = e1 >= e2 ? e1 + 1 : e2 + 1; /* the error on x is bounded by 1/2 ulp(x) + 2^(e1-p-1) */ e1 -= mpfr_get_exp (mpc_realref(z1)); /* the error on x is bounded by 1/2 ulp(x) [1 + 2^e1] */ e1 = e1 <= 0 ? 0 : e1; /* the error on x is bounded by 2^e1 * ulp(x) */ mpfr_neg (mpc_imagref(z1), mpc_imagref(z1), GMP_RNDN); /* exact */ inex_im = -inex_im; if (mpfr_can_round (mpc_realref(z1), p - e1, GMP_RNDN, GMP_RNDZ, p_re + (MPC_RND_RE(rnd) == GMP_RNDN))) break; } } inex = mpc_set (rop, z1, rnd); inex_re = MPC_INEX_RE(inex); mpc_clear (z1); mpfr_clear (pi_over_2); return MPC_INEX(inex_re, inex_im); }

/* Usage: tzeta - generic tests tzeta s prec rnd_mode - compute zeta(s) with precision 'prec' and rounding mode 'mode' */ int main (int argc, char *argv[]) { mpfr_t s, y, z; mpfr_prec_t prec; mpfr_rnd_t rnd_mode; int inex; tests_start_mpfr (); if (argc != 1 && argc != 4) { printf ("Usage: tzeta\n" " or tzeta s prec rnd_mode\n"); exit (1); } if (argc == 4) { prec = atoi(argv[2]); mpfr_init2 (s, prec); mpfr_init2 (z, prec); mpfr_set_str (s, argv[1], 10, MPFR_RNDN); rnd_mode = (mpfr_rnd_t) atoi(argv[3]); mpfr_zeta (z, s, rnd_mode); mpfr_out_str (stdout, 10, 0, z, MPFR_RNDN); printf ("\n"); mpfr_clear (s); mpfr_clear (z); return 0; } test1(); mpfr_init2 (s, MPFR_PREC_MIN); mpfr_init2 (y, MPFR_PREC_MIN); mpfr_init2 (z, MPFR_PREC_MIN); /* the following seems to loop */ mpfr_set_prec (s, 6); mpfr_set_prec (z, 6); mpfr_set_str_binary (s, "1.10010e4"); mpfr_zeta (z, s, MPFR_RNDZ); mpfr_set_prec (s, 53); mpfr_set_prec (y, 53); mpfr_set_prec (z, 53); mpfr_set_ui (s, 1, MPFR_RNDN); mpfr_zeta (z, s, MPFR_RNDN); if (!mpfr_inf_p (z) || MPFR_SIGN (z) < 0) { printf ("Error in mpfr_zeta for s = 1 (should be +inf)\n"); exit (1); } mpfr_set_str_binary (s, "0.1100011101110111111111111010000110010111001011001011"); mpfr_set_str_binary (y, "-0.11111101111011001001001111111000101010000100000100100E2"); mpfr_zeta (z, s, MPFR_RNDN); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (1,RNDN)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDZ); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (1,RNDZ)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDU); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (1,RNDU)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDD); mpfr_nexttoinf (y); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (1,RNDD)\n"); exit (1); } mpfr_set_str_binary (s, "0.10001011010011100110010001100100001011000010011001011"); mpfr_set_str_binary (y, "-0.11010011010010101101110111011010011101111101111010110E1"); mpfr_zeta (z, s, MPFR_RNDN); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (2,RNDN)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDZ); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (2,RNDZ)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDU); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (2,RNDU)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDD); mpfr_nexttoinf (y); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (2,RNDD)\n"); exit (1); } mpfr_set_str_binary (s, "0.1100111110100001111110111000110101111001011101000101"); mpfr_set_str_binary (y, "-0.10010111010110000111011111001101100001111011000001010E3"); mpfr_zeta (z, s, MPFR_RNDN); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (3,RNDN)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDD); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (3,RNDD)\n"); exit (1); } mpfr_nexttozero (y); mpfr_zeta (z, s, MPFR_RNDZ); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (3,RNDZ)\n"); exit (1); } mpfr_zeta (z, s, MPFR_RNDU); if (mpfr_cmp (z, y) != 0) { printf ("Error in mpfr_zeta (3,RNDU)\n"); exit (1); } mpfr_set_str (s, "-400000001", 10, MPFR_RNDZ); mpfr_zeta (z, s, MPFR_RNDN); if (!(mpfr_inf_p (z) && MPFR_SIGN(z) < 0)) { printf ("Error in mpfr_zeta (-400000001)\n"); exit (1); } mpfr_set_str (s, "-400000003", 10, MPFR_RNDZ); mpfr_zeta (z, s, MPFR_RNDN); if (!(mpfr_inf_p (z) && MPFR_SIGN(z) > 0)) { printf ("Error in mpfr_zeta (-400000003)\n"); exit (1); } mpfr_set_prec (s, 34); mpfr_set_prec (z, 34); mpfr_set_str_binary (s, "-1.111111100001011110000010001010000e-35"); mpfr_zeta (z, s, MPFR_RNDD); mpfr_set_str_binary (s, "-1.111111111111111111111111111111111e-2"); if (mpfr_cmp (s, z)) { printf ("Error in mpfr_zeta, prec=34, MPFR_RNDD\n"); mpfr_dump (z); exit (1); } /* bug found by nightly tests on June 7, 2007 */ mpfr_set_prec (s, 23); mpfr_set_prec (z, 25); mpfr_set_str_binary (s, "-1.0110110110001000000000e-27"); mpfr_zeta (z, s, MPFR_RNDN); mpfr_set_prec (s, 25); mpfr_set_str_binary (s, "-1.111111111111111111111111e-2"); if (mpfr_cmp (s, z)) { printf ("Error in mpfr_zeta, prec=25, MPFR_RNDN\n"); printf ("expected "); mpfr_dump (s); printf ("got "); mpfr_dump (z); exit (1); } /* bug reported by Kevin Rauch on 26 Oct 2007 */ mpfr_set_prec (s, 128); mpfr_set_prec (z, 128); mpfr_set_str_binary (s, "-0.1000000000000000000000000000000000000000000000000000000000000001E64"); inex = mpfr_zeta (z, s, MPFR_RNDN); MPFR_ASSERTN (mpfr_inf_p (z) && MPFR_SIGN (z) < 0 && inex < 0); inex = mpfr_zeta (z, s, MPFR_RNDU); mpfr_set_inf (s, -1); mpfr_nextabove (s); MPFR_ASSERTN (mpfr_equal_p (z, s) && inex > 0); mpfr_clear (s); mpfr_clear (y); mpfr_clear (z); test_generic (2, 70, 5); test2 (); tests_end_mpfr (); return 0; }

static void check_small (void) { mpfr_t x; char *s; mp_exp_t e; mp_prec_t p; mpfr_init (x); mpfr_set_prec (x, 20); mpfr_set_ui (x, 2, GMP_RNDN); mpfr_nexttozero (x); s = mpfr_get_str (NULL, &e, 4, 2, x, GMP_RNDU); if (strcmp (s, "20") || (e != 1)) { printf ("Error in mpfr_get_str: 2- rounded up with 2 digits" " in base 4\n"); exit (1); } mpfr_free_str (s); /* check n_digits=0 */ mpfr_set_prec (x, 5); mpfr_set_ui (x, 17, GMP_RNDN); s = mpfr_get_str (NULL, &e, 3, 0, x, GMP_RNDN); mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 36, 0, x, GMP_RNDN); mpfr_free_str (s); mpfr_set_prec (x, 64); mpfr_set_si (x, -1, GMP_RNDN); mpfr_div_2exp (x, x, 63, GMP_RNDN); /* x = -2^(-63) */ mpfr_add_ui (x, x, 1, GMP_RNDN); /* x = 1 - 2^(-63) */ mpfr_mul_2exp (x, x, 32, GMP_RNDN); /* x = 2^32 - 2^(-31) */ s = mpfr_get_str (NULL, &e, 3, 21, x, GMP_RNDU); if (strcmp (s, "102002022201221111211") || (e != 21)) { printf ("Error in mpfr_get_str: 2^32-2^(-31) rounded up with" " 21 digits in base 3\n"); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 3, 20, x, GMP_RNDU); if (strcmp (s, "10200202220122111122") || (e != 21)) { printf ("Error in mpfr_get_str: 2^32-2^(-31) rounded up with" " 20 digits in base 3\n"); exit (1); } mpfr_free_str (s); /* check corner case ret!=0, j0!=0 in mpfr_get_str_aux */ mpfr_set_prec (x, 100); mpfr_set_str_binary (x, "0.1001011111010001101110010101010101111001010111111101101101100110100011110110000101110110001011110000E-9"); s = mpfr_get_str (NULL, &e, 3, 2, x, GMP_RNDU); if (strcmp (s, "22") || (e != -6)) { printf ("Error in mpfr_get_str: 100-bit number rounded up with" " 2 digits in base 3\n"); exit (1); } mpfr_free_str (s); /* check corner case exact=0 in mpfr_get_str_aux */ mpfr_set_prec (x, 100); mpfr_set_str_binary (x, "0.1001001111101101111000101000110111111010101100000110010001111111011001101011101100001100110000000000E8"); s = mpfr_get_str (NULL, &e, 10, 2, x, GMP_RNDZ); if (strcmp (s, "14") || (e != 3)) { printf ("Error in mpfr_get_str: 100-bit number rounded to zero with" " 2 digits in base 10\n"); exit (1); } mpfr_free_str (s); for (p=4; p<=200; p++) { mpfr_set_prec (x, p); mpfr_set_str (x, "6.5", 10, GMP_RNDN); s = mpfr_get_str (NULL, &e, 6, 2, x, GMP_RNDN); if (strcmp (s, "10") || (e != 2)) { printf ("Error in mpfr_get_str: 6.5 rounded to nearest with" " 2 digits in base 6\n"); exit (1); } mpfr_free_str (s); mpfr_nexttoinf (x); s = mpfr_get_str (NULL, &e, 6, 2, x, GMP_RNDN); if (strcmp (s, "11") || (e != 2)) { printf ("Error in mpfr_get_str: 6.5+ rounded to nearest with" " 2 digits in base 6\ngot %se%d instead of 11e2\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str (x, "6.5", 10, GMP_RNDN); mpfr_nexttozero (x); s = mpfr_get_str (NULL, &e, 6, 2, x, GMP_RNDN); if (strcmp (s, "10") || (e != 2)) { printf ("Error in mpfr_get_str: 6.5- rounded to nearest with" " 2 digits in base 6\n"); exit (1); } mpfr_free_str (s); } mpfr_set_prec (x, 3); mpfr_set_ui (x, 7, GMP_RNDN); s = mpfr_get_str (NULL, &e, 2, 2, x, GMP_RNDU); if (strcmp (s, "10") || (e != 4)) { printf ("Error in mpfr_get_str: 7 rounded up with 2 bits should" " give 0.10e3 instead of 0.%s*2^%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* problem found by Fabrice Rouillier */ mpfr_set_prec (x, 63); mpfr_set_str (x, "5e14", 10, GMP_RNDN); s = mpfr_get_str (NULL, &e, 10, 18, x, GMP_RNDU); mpfr_free_str (s); /* bug found by Johan Vervloet */ mpfr_set_prec (x, 6); mpfr_set_str (x, "688.0", 10, GMP_RNDN); s = mpfr_get_str (NULL, &e, 2, 4, x, GMP_RNDU); if (strcmp (s, "1011") || (e != 10)) { printf ("Error in mpfr_get_str: 688 printed up to 4 bits should" " give 1.011e9\ninstead of "); mpfr_out_str (stdout, 2, 4, x, GMP_RNDU); puts (""); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 38); mpfr_set_str_binary (x, "1.0001110111110100011010100010010100110e-6"); s = mpfr_get_str (NULL, &e, 8, 10, x, GMP_RNDU); if (strcmp (s, "1073721522") || (e != -1)) { printf ("Error in mpfr_get_str (3): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 53); mpfr_set_str_binary (x, "0.11010111011101100010000100010101110001000000010111001E454"); s = mpfr_get_str (NULL, &e, 19, 12, x, GMP_RNDU); if (strcmp (s, "b1cgfa4gha0h") || (e != 107)) { printf ("Error in mpfr_get_str (4): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 145); mpfr_set_str_binary (x, "-0.1000110011000001011000010101101010110110101100101110100011111100011110011001001001010000100001000011000011000000010111011001000111101001110100110e6"); s = mpfr_get_str (NULL, &e, 4, 53, x, GMP_RNDU); if (strcmp (s, "-20303001120111222312230232203330132121021100201003003") || (e != 3)) { printf ("Error in mpfr_get_str (5): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 45); mpfr_set_str_binary (x, "-0.00100111010110010001011001110111010001010010010"); s = mpfr_get_str (NULL, &e, 32, 9, x, GMP_RNDN); if (strcmp (s, "-4tchctq54") || (e != 0)) { printf ("Error in mpfr_get_str (6): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* worst case found by Vincent Lefe`vre */ mpfr_set_prec (x, 53); mpfr_set_str_binary (x, "10011110111100000000001011011110101100010000011011111E164"); s = mpfr_get_str (NULL, &e, 10, 17, x, GMP_RNDN); if (strcmp (s, "13076622631878654") || (e != 66)) { printf ("Error in mpfr_get_str (7): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10000001001001001100011101010011011011111000011000100E93"); s = mpfr_get_str (NULL, &e, 10, 2, x, GMP_RNDU); if (strcmp (s, "46") || e != 44) { printf ("Error in mpfr_get_str (8): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10010001111100000111001111010101001010000010111010101E55"); s = mpfr_get_str (NULL, &e, 10, 2, x, GMP_RNDN); if (strcmp (s, "19") || e != 33) { printf ("Error in mpfr_get_str (9): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11011001010010111110010101101100111110111000010110110E44"); s = mpfr_get_str (NULL, &e, 10, 3, x, GMP_RNDN); if (strcmp (s, "135") || e != 30) { printf ("Error in mpfr_get_str (10): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11101111101000001011100001111000011111101111011001100E72"); s = mpfr_get_str (NULL, &e, 10, 4, x, GMP_RNDN); if (strcmp (s, "3981") || e != 38) { printf ("Error in mpfr_get_str (11): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10011001001100100010111100001101110101001001111110000E46"); s = mpfr_get_str (NULL, &e, 10, 5, x, GMP_RNDN); if (strcmp (s, "37930") || e != 30) { printf ("Error in mpfr_get_str (12): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10001100110111001011011110011011011101100011010001011E-72"); s = mpfr_get_str (NULL, &e, 10, 6, x, GMP_RNDN); if (strcmp (s, "104950") || e != -5) { printf ("Error in mpfr_get_str (13): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10100100001011001000011001101101000110100110000010111E89"); s = mpfr_get_str (NULL, &e, 10, 7, x, GMP_RNDN); if (strcmp (s, "3575392") || e != 43) { printf ("Error in mpfr_get_str (14): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11000011011110110010100110001010000001010011001011001E-73"); s = mpfr_get_str (NULL, &e, 10, 8, x, GMP_RNDN); if (strcmp (s, "72822386") || e != -6) { printf ("Error in mpfr_get_str (15): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10101010001101000111001100001000100011100010010001010E78"); s = mpfr_get_str (NULL, &e, 10, 9, x, GMP_RNDN); if (strcmp (s, "180992873") || e != 40) { printf ("Error in mpfr_get_str (16): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10110111001000100000001101111001100101101110011011101E91"); s = mpfr_get_str (NULL, &e, 10, 10, x, GMP_RNDN); if (strcmp (s, "1595312255") || e != 44) { printf ("Error in mpfr_get_str (17): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10011101010111101111000100111011101011110100110110101E93"); s = mpfr_get_str (NULL, &e, 10, 11, x, GMP_RNDN); if (strcmp (s, "54835744350") || e != 44) { printf ("Error in mpfr_get_str (18): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10011101010111101111000100111011101011110100110110101E92"); s = mpfr_get_str (NULL, &e, 10, 12, x, GMP_RNDN); if (strcmp (s, "274178721752") || e != 44) { printf ("Error in mpfr_get_str (19): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10011101010111101111000100111011101011110100110110101E91"); s = mpfr_get_str (NULL, &e, 10, 13, x, GMP_RNDN); if (strcmp (s, "1370893608762") || e != 44) { printf ("Error in mpfr_get_str (20): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10010011010110011100010010100101100011101000011111111E92"); s = mpfr_get_str (NULL, &e, 10, 14, x, GMP_RNDN); if (strcmp (s, "25672105101864") || e != 44) { printf ("Error in mpfr_get_str (21): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "100110111110110001000101110100100101101000011111001E87"); s = mpfr_get_str (NULL, &e, 10, 15, x, GMP_RNDN); if (strcmp (s, "212231308858721") || e != 42) { printf ("Error in mpfr_get_str (22): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10111010110000111000101100101111001011011100101001111E-128"); s = mpfr_get_str (NULL, &e, 10, 15, x, GMP_RNDN); if (strcmp (s, "193109287087290") || e != -22) { printf ("Error in mpfr_get_str (22b): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10001101101011010001111110000111010111010000110101010E80"); s = mpfr_get_str (NULL, &e, 10, 16, x, GMP_RNDN); if (strcmp (s, "6026241735727920") || e != 40) { printf ("Error in mpfr_get_str (23): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "100010001011101001110101000110011001001000110001001E-81"); s = mpfr_get_str (NULL, &e, 10, 17, x, GMP_RNDN); if (strcmp (s, "49741483709103481") || e != -9) { printf ("Error in mpfr_get_str (24): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11000100001001001110111010011001111001001010110101111E-101"); s = mpfr_get_str (NULL, &e, 10, 7, x, GMP_RNDN); if (strcmp (s, "2722049") || e != -14) { printf ("Error in mpfr_get_str (25): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11111001010011100101000001111111110001001001110110001E-135"); s = mpfr_get_str (NULL, &e, 10, 8, x, GMP_RNDN); if (strcmp (s, "20138772") || e != -24) { printf ("Error in mpfr_get_str (26): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11111001010011100101000001111111110001001001110110001E-136"); s = mpfr_get_str (NULL, &e, 10, 9, x, GMP_RNDN); if (strcmp (s, "100693858") || e != -24) { printf ("Error in mpfr_get_str (27): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10001000001110010110001011111011111011011010000110001E-110"); s = mpfr_get_str (NULL, &e, 10, 14, x, GMP_RNDN); if (strcmp (s, "36923634350619") || e != -17) { printf ("Error in mpfr_get_str (28): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11001100010111000111100010000110011101110001000101111E-87"); s = mpfr_get_str (NULL, &e, 10, 16, x, GMP_RNDN); if (strcmp (s, "4646636036100804") || e != -10) { printf ("Error in mpfr_get_str (29): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "10011111001111110100001001010111111011010101111111000E-99"); s = mpfr_get_str (NULL, &e, 10, 17, x, GMP_RNDN); if (strcmp (s, "88399901882446712") || e != -14) { printf ("Error in mpfr_get_str (30): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 8116315218207718*2^(-293) ~ 0.5100000000000000000015*10^(-72) */ mpfr_set_str_binary (x, "11100110101011011111011100101011101110110001111100110E-293"); s = mpfr_get_str (NULL, &e, 10, 2, x, GMP_RNDU); if (strcmp (s, "52") || e != -72) { printf ("Error in mpfr_get_str (31u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 2, x, GMP_RNDD); if (strcmp (s, "51") || e != -72) { printf ("Error in mpfr_get_str (31d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 6712731423444934*2^536 ~ .151000000000000000000067*10^178 */ mpfr_set_str_binary (x, "10111110110010011000110010011111101111000111111000110E536"); s = mpfr_get_str (NULL, &e, 10, 3, x, GMP_RNDU); if (strcmp (s, "152") || e != 178) { printf ("Error in mpfr_get_str (32u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 3, x, GMP_RNDD); if (strcmp (s, "151") || e != 178) { printf ("Error in mpfr_get_str (32d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 3356365711722467*2^540 ~ .120800000000000000000054*10^179 */ mpfr_set_str_binary (x, "1011111011001001100011001001111110111100011111100011E540"); s = mpfr_get_str (NULL, &e, 10, 4, x, GMP_RNDU); if (strcmp (s, "1209") || e != 179) { printf ("Error in mpfr_get_str (33u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 4, x, GMP_RNDD); if (strcmp (s, "1208") || e != 179) { printf ("Error in mpfr_get_str (33d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 6475049196144587*2^100 ~ .8208099999999999999999988*10^46 */ mpfr_set_str_binary (x, "10111000000010000010111011111001111010100011111001011E100"); s = mpfr_get_str (NULL, &e, 10, 5, x, GMP_RNDU); if (strcmp (s, "82081") || e != 46) { printf ("Error in mpfr_get_str (34u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 5, x, GMP_RNDD); if (strcmp (s, "82080") || e != 46) { printf ("Error in mpfr_get_str (34d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 6722280709661868*2^364 ~ .25260100000000000000000012*10^126 */ mpfr_set_str_binary (x, "10111111000011110000011110001110001111010010010101100E364"); s = mpfr_get_str (NULL, &e, 10, 6, x, GMP_RNDU); if (strcmp (s, "252602") || e != 126) { printf ("Error in mpfr_get_str (35u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 6, x, GMP_RNDD); if (strcmp (s, "252601") || e != 126) { printf ("Error in mpfr_get_str (35d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 5381065484265332*2^(-455) ~ .578389299999999999999999982*10^(-121) */ mpfr_set_str_binary (x, "10011000111100000110011110000101100111110011101110100E-455"); s = mpfr_get_str (NULL, &e, 10, 7, x, GMP_RNDU); if (strcmp (s, "5783893") || e != -121) { printf ("Error in mpfr_get_str (36u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 7, x, GMP_RNDD); if (strcmp (s, "5783892") || e != -121) { printf ("Error in mpfr_get_str (36d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 8369123604277281*2^(-852) ~ .27869147000000000000000000056*10^(-240) */ mpfr_set_str_binary (x, "11101101110111010110001101111100000111010100000100001E-852"); s = mpfr_get_str (NULL, &e, 10, 8, x, GMP_RNDU); if (strcmp (s, "27869148") || e != -240) { printf ("Error in mpfr_get_str (37u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 8, x, GMP_RNDD); if (strcmp (s, "27869147") || e != -240) { printf ("Error in mpfr_get_str (37d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 7976538478610756*2^377 ~ .245540326999999999999999999982*10^130 */ mpfr_set_str_binary (x, "11100010101101001111010010110100011100000100101000100E377"); s = mpfr_get_str (NULL, &e, 10, 9, x, GMP_RNDU); if (strcmp (s, "245540327") || e != 130) { printf ("Error in mpfr_get_str (38u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 9, x, GMP_RNDD); if (strcmp (s, "245540326") || e != 130) { printf ("Error in mpfr_get_str (38d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 8942832835564782*2^(-382) ~ .9078555839000000000000000000038*10^(-99) */ mpfr_set_str_binary (x, "11111110001010111010110000110011100110001010011101110E-382"); s = mpfr_get_str (NULL, &e, 10, 10, x, GMP_RNDU); if (strcmp (s, "9078555840") || e != -99) { printf ("Error in mpfr_get_str (39u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 10, x, GMP_RNDD); if (strcmp (s, "9078555839") || e != -99) { printf ("Error in mpfr_get_str (39d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 4471416417782391*2^(-380) ~ .18157111678000000000000000000077*10^(-98) */ mpfr_set_str_binary (x, "1111111000101011101011000011001110011000101001110111E-380"); s = mpfr_get_str (NULL, &e, 10, 11, x, GMP_RNDU); if (strcmp (s, "18157111679") || e != -98) { printf ("Error in mpfr_get_str (40u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 11, x, GMP_RNDD); if (strcmp (s, "18157111678") || e != -98) { printf ("Error in mpfr_get_str (40d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 7225450889282194*2^711 ~ .778380362292999999999999999999971*10^230 */ mpfr_set_str_binary (x, "11001101010111000001001100001100110010000001010010010E711"); s = mpfr_get_str (NULL, &e, 10, 12, x, GMP_RNDU); if (strcmp (s, "778380362293") || e != 230) { printf ("Error in mpfr_get_str (41u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 12, x, GMP_RNDD); if (strcmp (s, "778380362292") || e != 230) { printf ("Error in mpfr_get_str (41d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 3612725444641097*2^713 ~ .1556760724585999999999999999999942*10^231 */ mpfr_set_str_binary (x, "1100110101011100000100110000110011001000000101001001E713"); s = mpfr_get_str (NULL, &e, 10, 13, x, GMP_RNDU); if (strcmp (s, "1556760724586") || e != 231) { printf ("Error in mpfr_get_str (42u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 13, x, GMP_RNDD); if (strcmp (s, "1556760724585") || e != 231) { printf ("Error in mpfr_get_str (42d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 6965949469487146*2^(-248) ~ .15400733123779000000000000000000016*10^(-58) */ mpfr_set_str_binary (x, "11000101111110111111001111111101001101111000000101010E-248"); s = mpfr_get_str (NULL, &e, 10, 14, x, GMP_RNDU); if (strcmp (s, "15400733123780") || e != -58) { printf ("Error in mpfr_get_str (43u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 14, x, GMP_RNDD); if (strcmp (s, "15400733123779") || e != -58) { printf ("Error in mpfr_get_str (43d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 3482974734743573*2^(-244) ~ .12320586499023200000000000000000013*10^(-57) */ mpfr_set_str_binary (x, "1100010111111011111100111111110100110111100000010101E-244"); s = mpfr_get_str (NULL, &e, 10, 15, x, GMP_RNDU); if (strcmp (s, "123205864990233") || e != -57) { printf ("Error in mpfr_get_str (44u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 15, x, GMP_RNDD); if (strcmp (s, "123205864990232") || e != -57) { printf ("Error in mpfr_get_str (44d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 7542952370752766*2^(-919) ~ .170206189963739699999999999999999974*10^(-260) */ mpfr_set_str_binary (x, "11010110011000100011001110100100111011100110011111110E-919"); s = mpfr_get_str (NULL, &e, 10, 16, x, GMP_RNDU); if (strcmp (s, "1702061899637397") || e != -260) { printf ("Error in mpfr_get_str (45u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 16, x, GMP_RNDD); if (strcmp (s, "1702061899637396") || e != -260) { printf ("Error in mpfr_get_str (45d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); /* 5592117679628511*2^165 ~ .26153245263757307000000000000000000074*10^66 */ mpfr_set_str_binary (x, "10011110111100000000001011011110101100010000011011111E165"); s = mpfr_get_str (NULL, &e, 10, 17, x, GMP_RNDU); if (strcmp (s, "26153245263757308") || e != 66) { printf ("Error in mpfr_get_str (46u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 17, x, GMP_RNDD); if (strcmp (s, "26153245263757307") || e != 66) { printf ("Error in mpfr_get_str (46d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11010010110111100001011010000110010000100001011011101E1223"); s = mpfr_get_str (NULL, &e, 10, 17, x, GMP_RNDN); if (strcmp (s, "10716284017294180") || e != 385) { printf ("Error in mpfr_get_str (47n): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 18, x, GMP_RNDU); if (strcmp (s, "107162840172941805") || e != 385) { printf ("Error in mpfr_get_str (47u): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 18, x, GMP_RNDD); if (strcmp (s, "107162840172941804") || e != 385) { printf ("Error in mpfr_get_str (47d): s=%s e=%d\n", s, (int) e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "11111101111011000001010100001101101000010010001111E122620"); s = mpfr_get_str (NULL, &e, 10, 17, x, GMP_RNDN); if (strcmp (s, "22183435284042374") || e != 36928) { printf ("Error in mpfr_get_str (48n): s=%s e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 18, x, GMP_RNDU); if (strcmp (s, "221834352840423736") || e != 36928) { printf ("Error in mpfr_get_str (48u): s=%s e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 18, x, GMP_RNDD); if (strcmp (s, "221834352840423735") || e != 36928) { printf ("Error in mpfr_get_str (48d): s=%s e=%ld\n", s, (long) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 45); mpfr_set_str_binary (x, "1E45"); s = mpfr_get_str (NULL, &e, 32, 9, x, GMP_RNDN); mpfr_free_str (s); mpfr_set_prec (x, 7); mpfr_set_str_binary (x, "0.1010101E10"); s = mpfr_get_str (NULL, &e, 10, 2, x, GMP_RNDU); mpfr_free_str (s); /* checks rounding of negative numbers */ mpfr_set_prec (x, 7); mpfr_set_str (x, "-11.5", 10, GMP_RNDN); s = mpfr_get_str (NULL, &e, 10, 2, x, GMP_RNDD); if (strcmp (s, "-12")) { printf ("Error in mpfr_get_str for x=-11.5 and rnd=GMP_RNDD\n" "got %s instead of -12\n", s); exit (1); } mpfr_free_str (s); s = mpfr_get_str (NULL, &e, 10, 2, x, GMP_RNDU); if (strcmp (s, "-11")) { printf ("Error in mpfr_get_str for x=-11.5 and rnd=GMP_RNDU\n"); exit (1); } mpfr_free_str (s); /* bug found by Jean-Pierre Merlet, produced error in mpfr_get_str */ mpfr_set_prec (x, 128); mpfr_set_str_binary (x, "0.10111001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011010E3"); s = mpfr_get_str (NULL, &e, 10, 0, x, GMP_RNDU); mpfr_free_str (s); mpfr_set_prec (x, 381); mpfr_set_str_binary (x, "0.111111111111111111111111111111111111111111111111111111111111111111101110110000100110011101101101001010111000101111000100100011110101010110101110100000010100001000110100000100011111001000010010000010001010111001011110000001110010111101100001111000101101100000010110000101100100000101010110010110001010100111001111100011100101100000100100111001100010010011110011011010110000001000010"); s = mpfr_get_str (NULL, &e, 10, 0, x, GMP_RNDD); if (e != 0) { printf ("Error in mpfr_get_str for x=0.999999..., exponent is %d" " instead of 0\n", (int) e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 5); mpfr_set_str_binary (x, "1101.1"); /* 13.5, or (16)_7 + 1/2 */ s = mpfr_get_str (NULL, &e, 7, 2, x, GMP_RNDN); /* we are in the tie case: both surrounding numbers are (16)_7 and (20)_7: since (16)_7 = 13 is odd and (20)_7 = 14 is even, we should have s = "20" and e = 2 */ if (e != 2 || strcmp (s, "20")) { printf ("Error in mpfr_get_str for x=13.5, base 7\n"); printf ("Expected s=20, e=2, got s=%s, e=%ld\n", s, e); exit (1); } mpfr_free_str (s); /* try the same example, with input just below or above 13.5 */ mpfr_set_prec (x, 1000); mpfr_set_str_binary (x, "1101.1"); mpfr_nextabove (x); s = mpfr_get_str (NULL, &e, 7, 2, x, GMP_RNDN); if (e != 2 || strcmp (s, "20")) { printf ("Error in mpfr_get_str for x=13.5+tiny, base 7\n"); printf ("Expected s=20, e=2, got s=%s, e=%ld\n", s, e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "1101.1"); mpfr_nextbelow (x); s = mpfr_get_str (NULL, &e, 7, 2, x, GMP_RNDN); if (e != 2 || strcmp (s, "16")) { printf ("Error in mpfr_get_str for x=13.5-tiny, base 7\n"); printf ("Expected s=16, e=2, got s=%s, e=%ld\n", s, e); exit (1); } mpfr_free_str (s); mpfr_set_prec (x, 7); mpfr_set_str_binary (x, "110000.1"); /* 48.5, or (66)_7 + 1/2 */ s = mpfr_get_str (NULL, &e, 7, 2, x, GMP_RNDN); /* we are in the tie case: both surrounding numbers are (66)_7 and (100)_7: since (66)_7 = 48 is even and (100)_7 is odd, we should hase s = "66" and e = 2 */ if (e != 2 || strcmp (s, "66")) { printf ("Error in mpfr_get_str for x=48.5, base 7\n"); printf ("Expected s=66, e=2, got s=%s, e=%ld\n", s, e); exit (1); } mpfr_free_str (s); /* try the same example, with input just below or above 48.5 */ mpfr_set_prec (x, 1000); mpfr_set_str_binary (x, "110000.1"); mpfr_nextabove (x); s = mpfr_get_str (NULL, &e, 7, 2, x, GMP_RNDN); if (e != 3 || strcmp (s, "10")) { printf ("Error in mpfr_get_str for x=48.5+tiny, base 7\n"); printf ("Expected s=10, e=3, got s=%s, e=%ld\n", s, e); exit (1); } mpfr_free_str (s); mpfr_set_str_binary (x, "110000.1"); mpfr_nextbelow (x); s = mpfr_get_str (NULL, &e, 7, 2, x, GMP_RNDN); if (e != 2 || strcmp (s, "66")) { printf ("Error in mpfr_get_str for x=48.5-tiny, base 7\n"); printf ("Expected s=66, e=2, got s=%s, e=%ld\n", s, e); exit (1); } mpfr_free_str (s); mpfr_clear (x); }

int main (int argc, char *argv[]) { mpfr_t x, c, s, c2, s2; tests_start_mpfr (); check_regression (); check_nans (); /* worst case from PhD thesis of Vincent Lefe`vre: x=8980155785351021/2^54 */ check53 ("4.984987858808754279e-1", "4.781075595393330379e-1", MPFR_RNDN); check53 ("4.984987858808754279e-1", "4.781075595393329824e-1", MPFR_RNDD); check53 ("4.984987858808754279e-1", "4.781075595393329824e-1", MPFR_RNDZ); check53 ("4.984987858808754279e-1", "4.781075595393330379e-1", MPFR_RNDU); check53 ("1.00031274099908640274", "8.416399183372403892e-1", MPFR_RNDN); check53 ("1.00229256850978698523", "8.427074524447979442e-1", MPFR_RNDZ); check53 ("1.00288304857059840103", "8.430252033025980029e-1", MPFR_RNDZ); check53 ("1.00591265847407274059", "8.446508805292128885e-1", MPFR_RNDN); /* Other worst cases showing a bug introduced on 2005-01-29 in rev 3248 */ check53b ("1.0111001111010111010111111000010011010001110001111011e-21", "1.0111001111010111010111111000010011010001101001110001e-21", MPFR_RNDU); check53b ("1.1011101111111010000001010111000010000111100100101101", "1.1111100100101100001111100000110011110011010001010101e-1", MPFR_RNDU); mpfr_init2 (x, 2); mpfr_set_str (x, "0.5", 10, MPFR_RNDN); test_sin (x, x, MPFR_RNDD); if (mpfr_cmp_ui_2exp (x, 3, -3)) /* x != 0.375 = 3/8 */ { printf ("mpfr_sin(0.5, MPFR_RNDD) failed with precision=2\n"); exit (1); } /* bug found by Kevin Ryde */ mpfr_const_pi (x, MPFR_RNDN); mpfr_mul_ui (x, x, 3L, MPFR_RNDN); mpfr_div_ui (x, x, 2L, MPFR_RNDN); test_sin (x, x, MPFR_RNDN); if (mpfr_cmp_ui (x, 0) >= 0) { printf ("Error: wrong sign for sin(3*Pi/2)\n"); exit (1); } /* Can fail on an assert */ mpfr_set_prec (x, 53); mpfr_set_str (x, "77291789194529019661184401408", 10, MPFR_RNDN); mpfr_init2 (c, 4); mpfr_init2 (s, 42); mpfr_init2 (c2, 4); mpfr_init2 (s2, 42); test_sin (s, x, MPFR_RNDN); mpfr_cos (c, x, MPFR_RNDN); mpfr_sin_cos (s2, c2, x, MPFR_RNDN); if (mpfr_cmp (c2, c)) { printf("cos differs for x=77291789194529019661184401408"); exit (1); } if (mpfr_cmp (s2, s)) { printf("sin differs for x=77291789194529019661184401408"); exit (1); } mpfr_set_str_binary (x, "1.1001001000011111101101010100010001000010110100010011"); test_sin (x, x, MPFR_RNDZ); if (mpfr_cmp_str (x, "1.1111111111111111111111111111111111111111111111111111e-1", 2, MPFR_RNDN)) { printf ("Error for x= 1.1001001000011111101101010100010001000010110100010011\nGot "); mpfr_dump (x); exit (1); } mpfr_set_prec (s, 9); mpfr_set_prec (x, 190); mpfr_const_pi (x, MPFR_RNDN); mpfr_sin (s, x, MPFR_RNDZ); if (mpfr_cmp_str (s, "0.100000101e-196", 2, MPFR_RNDN)) { printf ("Error for x ~= pi\n"); mpfr_dump (s); exit (1); } mpfr_clear (s2); mpfr_clear (c2); mpfr_clear (s); mpfr_clear (c); mpfr_clear (x); test_generic (2, 100, 15); test_generic (MPFR_SINCOS_THRESHOLD-1, MPFR_SINCOS_THRESHOLD+1, 2); test_sign (); check_tiny (); data_check ("data/sin", mpfr_sin, "mpfr_sin"); bad_cases (mpfr_sin, mpfr_asin, "mpfr_sin", 256, -40, 0, 4, 128, 800, 50); tests_end_mpfr (); return 0; }

static void special (void) { mpfr_t x, y; mpq_t z; int res = 0; mpfr_init (x); mpfr_init (y); mpq_init (z); /* cancellation in mpfr_add_q */ mpfr_set_prec (x, 60); mpfr_set_prec (y, 20); mpz_set_str (mpq_numref (z), "-187207494", 10); mpz_set_str (mpq_denref (z), "5721", 10); mpfr_set_str_binary (x, "11111111101001011011100101100011011110010011100010000100001E-44"); mpfr_add_q (y, x, z, MPFR_RNDN); CHECK_FOR ("cancelation in add_q", mpfr_cmp_ui_2exp (y, 256783, -64) == 0); mpfr_set_prec (x, 19); mpfr_set_str_binary (x, "0.1011110101110011100E0"); mpz_set_str (mpq_numref (z), "187207494", 10); mpz_set_str (mpq_denref (z), "5721", 10); mpfr_set_prec (y, 29); mpfr_add_q (y, x, z, MPFR_RNDD); mpfr_set_prec (x, 29); mpfr_set_str_binary (x, "11111111101001110011010001001E-14"); CHECK_FOR ("cancelation in add_q", mpfr_cmp (x,y) == 0); /* Inf */ mpfr_set_inf (x, 1); mpz_set_str (mpq_numref (z), "395877315", 10); mpz_set_str (mpq_denref (z), "3508975966", 10); mpfr_set_prec (y, 118); mpfr_add_q (y, x, z, MPFR_RNDU); CHECK_FOR ("inf", mpfr_inf_p (y) && mpfr_sgn (y) > 0); mpfr_sub_q (y, x, z, MPFR_RNDU); CHECK_FOR ("inf", mpfr_inf_p (y) && mpfr_sgn (y) > 0); /* Nan */ MPFR_SET_NAN (x); mpfr_add_q (y, x, z, MPFR_RNDU); CHECK_FOR ("nan", mpfr_nan_p (y)); mpfr_sub_q (y, x, z, MPFR_RNDU); CHECK_FOR ("nan", mpfr_nan_p (y)); /* Exact value */ mpfr_set_prec (x, 60); mpfr_set_prec (y, 60); mpfr_set_str1 (x, "0.5"); mpz_set_str (mpq_numref (z), "3", 10); mpz_set_str (mpq_denref (z), "2", 10); res = mpfr_add_q (y, x, z, MPFR_RNDU); CHECK_FOR ("0.5+3/2", mpfr_cmp_ui(y, 2)==0 && res==0); res = mpfr_sub_q (y, x, z, MPFR_RNDU); CHECK_FOR ("0.5-3/2", mpfr_cmp_si(y, -1)==0 && res==0); /* Inf Rationnal */ mpq_set_ui (z, 1, 0); mpfr_set_str1 (x, "0.5"); res = mpfr_add_q (y, x, z, MPFR_RNDN); CHECK_FOR ("0.5+1/0", mpfr_inf_p (y) && MPFR_SIGN (y) > 0 && res == 0); res = mpfr_sub_q (y, x, z, MPFR_RNDN); CHECK_FOR ("0.5-1/0", mpfr_inf_p (y) && MPFR_SIGN (y) < 0 && res == 0); mpq_set_si (z, -1, 0); res = mpfr_add_q (y, x, z, MPFR_RNDN); CHECK_FOR ("0.5+ -1/0", mpfr_inf_p (y) && MPFR_SIGN (y) < 0 && res == 0); res = mpfr_sub_q (y, x, z, MPFR_RNDN); CHECK_FOR ("0.5- -1/0", mpfr_inf_p (y) && MPFR_SIGN (y) > 0 && res == 0); res = mpfr_div_q (y, x, z, MPFR_RNDN); CHECK_FOR ("0.5 / (-1/0)", mpfr_zero_p (y) && MPFR_SIGN (y) < 0 && res == 0); /* 0 */ mpq_set_ui (z, 0, 1); mpfr_set_ui (x, 42, MPFR_RNDN); res = mpfr_add_q (y, x, z, MPFR_RNDN); CHECK_FOR ("42+0/1", mpfr_cmp_ui (y, 42) == 0 && res == 0); res = mpfr_sub_q (y, x, z, MPFR_RNDN); CHECK_FOR ("42-0/1", mpfr_cmp_ui (y, 42) == 0 && res == 0); res = mpfr_mul_q (y, x, z, MPFR_RNDN); CHECK_FOR ("42*0/1", mpfr_zero_p (y) && MPFR_SIGN (y) > 0 && res == 0); res = mpfr_div_q (y, x, z, MPFR_RNDN); CHECK_FOR ("42/(0/1)", mpfr_inf_p (y) && MPFR_SIGN (y) > 0 && res == 0); mpq_clear (z); mpfr_clear (x); mpfr_clear (y); }