/* $Id: pb-e-dir.c 47490 2011-11-10 17:07:08Z vinc17/ypig $ */ #include #include #include #include #include static const mp_rnd_t rnd[3] = { MPFR_RNDD, MPFR_RNDN, MPFR_RNDU }; static void calc_e (mpfr_t e, int prec, int r) { mpfr_t t, u; int i = 1; #ifdef PREC int newprec; #endif mpfr_inits2 (prec, t, u, (void *) 0); mpfr_set_ui (e, 2, rnd[r]); mpfr_set_ui (t, 1, rnd[r]); while (2 - mpfr_get_exp (t) < prec) { mpfr_div_ui (t, t, ++i, rnd[r]); #ifdef PREC /* make -W pb-e-dir.c pb-e-dir CPPFLAGS=-DPREC */ newprec = prec + mpfr_get_exp (t); if (newprec < MPFR_PREC_MIN) break; mpfr_prec_round (t, prec + mpfr_get_exp (t), rnd[r]); #endif mpfr_add (e, e, t, rnd[r]); } mpfr_clears (t, u, (void *) 0); } int main (int argc, char *argv[]) { mpfr_t e1, e2, u, einf, esup, length; int prec, inex; clock_t c; double t; if (argc != 2) { fprintf (stderr, "Usage: pb-e-dir \n"); exit (EXIT_FAILURE); } prec = atoi (argv[1]); if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) { fprintf (stderr, "pb-e-dir: incorrect precision %d\n", prec); exit (EXIT_FAILURE); } mpfr_inits2 (prec, e1, einf, esup, (void *) 0); mpfr_init2 (e2, prec + 8); mpfr_init2 (u, 2); c = clock (); calc_e (e1, prec, 1); t = (double) (clock () - c) / CLOCKS_PER_SEC; printf ("Time: %.2f s\n", t); mpfr_set_ui (u, 1, MPFR_RNDN); mpfr_exp (e2, u, MPFR_RNDN); mpfr_set_ui_2exp (u, 1, mpfr_get_exp (e2) - (mp_exp_t) mpfr_get_prec (e2) - 1, MPFR_RNDN); /* 1/2 ulp(e2), error bound for e2 */ inex = mpfr_sub (e2, e2, e1, MPFR_RNDZ); /* should be exact as e1 ~= e2 */ mpfr_abs (e2, e2, MPFR_RNDN); if (inex) { fprintf (stderr, "pb-e-dir: warning: e1 -e2 is inexact\n"); mpfr_nextabove (e2); /* upper bound on initial |e1 - e2| */ } mpfr_add (e2, e2, u, MPFR_RNDU); /* upper bound on the error |e1 - e| */ printf ("Error <= "); mpfr_out_str (stdout, 10, 6, e2, MPFR_RNDU); putchar ('\n'); calc_e (einf, prec, 0); calc_e (esup, prec, 2); mpfr_init2 (length, 32); inex = mpfr_sub (length, esup, einf, MPFR_RNDU); if (inex) fprintf (stderr, "pb-e-dir: warning: esup -einf is inexact\n"); printf ("Interval length <= "); mpfr_out_str (stdout, 10, 6, length, MPFR_RNDU); putchar ('\n'); mpfr_clears (e1, e2, u, einf, esup, length, (void *) 0); return 0; }