/* $Id: pb-cr-canround.c 47490 2011-11-10 17:07:08Z vinc17/ypig $ */ #include #include #include #include int main (int argc, char *argv[]) { mpfr_t x, y; int n, xprec, yprec, rnd, reqinex; if (argc != 5 && argc != 6) { fprintf (stderr, "Usage: pb-cr-canround " " [ ]\n"); exit (EXIT_FAILURE); } reqinex = argc == 5; xprec = atoi (argv[2]); if (xprec < MPFR_PREC_MIN || xprec > MPFR_PREC_MAX) { fprintf (stderr, "pb-cr-canround: incorrect input precision %d\n", xprec); exit (EXIT_FAILURE); } mpfr_init2 (x, xprec); if (mpfr_set_str (x, argv[1], 0, MPFR_RNDN) || mpfr_cmp_ui (x, 0) < 0) { fprintf (stderr, "pb-cr-canround: bad value x (%s)\n", argv[1]); exit (EXIT_FAILURE); } n = atoi (argv[3]); if (n < 2) { fprintf (stderr, "pb-cr-canround: n must be >= 2\n"); exit (EXIT_FAILURE); } yprec = atoi (argv[4]); if (yprec < MPFR_PREC_MIN || yprec > MPFR_PREC_MAX) { fprintf (stderr, "pb-cr-canround: incorrect output precision %d\n", yprec); exit (EXIT_FAILURE); } for (rnd = 0; rnd < 4; rnd++) { int inex; mp_prec_t tprec = yprec; mpfr_init2 (y, tprec); do { tprec += 8; mpfr_set_prec (y, tprec); printf ("Intermediate precision %ld...\n", (long) tprec); mpfr_clear_inexflag (); mpfr_root (y, x, n, MPFR_RNDN); mpfr_ui_div (y, 1, y, MPFR_RNDN); } while (mpfr_inexflag_p () && ! mpfr_can_round (y, tprec - 2, MPFR_RNDN, reqinex ? MPFR_RNDZ : rnd, yprec + (reqinex && rnd == MPFR_RNDN))); inex = mpfr_prec_round (y, yprec, rnd); printf ("%s: ", mpfr_print_rnd_mode (rnd)); mpfr_out_str (stdout, 2, 0, y, rnd); printf (reqinex ? " (inex = %d)\n" : "\n", inex < 0 ? -1 : inex > 0); mpfr_clear (y); } mpfr_clear (x); return 0; } /* Let t = root(x,n), y1 = o(t), u = 1/t, y2 = o(1/y1). y1 = t(1 + Eps), where Eps = [-eps,eps] and eps = 2^(-p). 1/y1 = y2(1 + Eps), thus u = 1/t = y2(1 + Eps)^2. |y2 - u| <= y2 (2 eps + eps^2) <= 2^(E(y2) + 2 - p). $ ./pb-cr-canround 12 32 17 31 - Intermediate precision 39... Intermediate precision 47... MPFR_RNDN: 1.101110100101111110000011100011e-1 Intermediate precision 39... MPFR_RNDZ: 1.101110100101111110000011100010e-1 Intermediate precision 39... MPFR_RNDU: 1.101110100101111110000011100011e-1 Intermediate precision 39... MPFR_RNDD: 1.101110100101111110000011100010e-1 $ ./pb-cr-canround 12 32 17 31 Intermediate precision 39... Intermediate precision 47... MPFR_RNDN: 1.101110100101111110000011100011e-1 (inex = 1) Intermediate precision 39... MPFR_RNDZ: 1.101110100101111110000011100010e-1 (inex = -1) Intermediate precision 39... MPFR_RNDU: 1.101110100101111110000011100011e-1 (inex = 1) Intermediate precision 39... MPFR_RNDD: 1.101110100101111110000011100010e-1 (inex = -1) $ ./pb-cr-canround 12 32 17 32 - Intermediate precision 40... MPFR_RNDN: 1.1011101001011111100000111000101e-1 Intermediate precision 40... Intermediate precision 48... MPFR_RNDZ: 1.1011101001011111100000111000101e-1 Intermediate precision 40... Intermediate precision 48... MPFR_RNDU: 1.1011101001011111100000111000110e-1 Intermediate precision 40... Intermediate precision 48... MPFR_RNDD: 1.1011101001011111100000111000101e-1 $ ./pb-cr-canround 12 32 17 32 Intermediate precision 40... Intermediate precision 48... MPFR_RNDN: 1.1011101001011111100000111000101e-1 (inex = -1) Intermediate precision 40... Intermediate precision 48... MPFR_RNDZ: 1.1011101001011111100000111000101e-1 (inex = -1) Intermediate precision 40... Intermediate precision 48... MPFR_RNDU: 1.1011101001011111100000111000110e-1 (inex = 1) Intermediate precision 40... Intermediate precision 48... MPFR_RNDD: 1.1011101001011111100000111000101e-1 (inex = -1) */