static void check_large (void) { mpfr_t a, b, agm; int inex; mpfr_init2 (a, 82); mpfr_init2 (b, 82); mpfr_init2 (agm, 82); mpfr_set_ui (a, 1, MPFR_RNDN); mpfr_set_str_binary (b, "0.1111101100001000000001011000110111101000001011111000100001000101010100011111110010E-39"); mpfr_agm (agm, a, b, MPFR_RNDN); mpfr_set_str_binary (a, "0.1110001000111101101010101010101101001010001001001011100101111011110101111001111100E-4"); if (mpfr_cmp (agm, a)) { printf ("mpfr_agm failed for precision 82\n"); exit (1); } /* problem found by Damien Fischer <*****@*****.**> 4 Aug 2003: produced a divide-by-zero exception */ mpfr_set_prec (a, 268); mpfr_set_prec (b, 268); mpfr_set_prec (agm, 268); mpfr_set_str (a, "703.93543315330225238487276503953366664991725089988315253092140138947103394917006", 10, MPFR_RNDN); mpfr_set_str (b, "703.93543315330225238487279020523738740563816490895994499256063816906728642622316", 10, MPFR_RNDN); mpfr_agm (agm, a, b, MPFR_RNDN); mpfr_set_prec (a, 18); mpfr_set_prec (b, 70); mpfr_set_prec (agm, 67); mpfr_set_str_binary (a, "0.111001111100101000e8"); mpfr_set_str_binary (b, "0.1101110111100100010100110000010111011011011100110100111001010100100001e10"); inex = mpfr_agm (agm, a, b, MPFR_RNDN); mpfr_set_str_binary (b, "0.1111110010011101101100010101011011010010010000001010100011000110011e9"); if (mpfr_cmp (agm, b)) { printf ("Error in mpfr_agm (1)\n"); exit (1); } if (inex >= 0) { printf ("Wrong flag for mpfr_agm (1)\n"); exit (1); } /* test worst case: 9 consecutive ones after the last bit */ mpfr_set_prec (a, 2); mpfr_set_prec (b, 2); mpfr_set_ui (a, 1, MPFR_RNDN); mpfr_set_ui (b, 2, MPFR_RNDN); mpfr_set_prec (agm, 904); mpfr_agm (agm, a, b, MPFR_RNDZ); mpfr_clear (a); mpfr_clear (b); mpfr_clear (agm); }
static void check4 (const char *as, const char *bs, mpfr_rnd_t rnd_mode, const char *res) { mpfr_t ta, tb, tres; mpfr_inits2 (53, ta, tb, tres, (mpfr_ptr) 0); mpfr_set_str1 (ta, as); mpfr_set_str1 (tb, bs); mpfr_agm(tres, ta, tb, rnd_mode); if (mpfr_cmp_str1 (tres, res)) { printf ("mpfr_agm failed for a=%s, b=%s, rnd_mode=%d\n",as,bs,rnd_mode); printf ("expected result is %s, got ",res); mpfr_out_str(stdout, 10, 0, tres, MPFR_RNDN); putchar('\n'); exit (1); } mpfr_clears (ta, tb, tres, (mpfr_ptr) 0); }
static void check4 (const char *as, const char *bs, mpfr_rnd_t rnd_mode, const char *res, int inex) { mpfr_t ta, tb, tc, tres; mpfr_exp_t emin, emax; int i; emin = mpfr_get_emin (); emax = mpfr_get_emax (); mpfr_inits2 (53, ta, tb, tc, tres, (mpfr_ptr) 0); for (i = 0; i <= 2; i++) { unsigned int expflags, newflags; int inex2; mpfr_set_str1 (ta, as); mpfr_set_str1 (tb, bs); mpfr_set_str1 (tc, res); if (i > 0) { mpfr_exp_t ea, eb, ec, e0; set_emin (MPFR_EMIN_MIN); set_emax (MPFR_EMAX_MAX); ea = mpfr_get_exp (ta); eb = mpfr_get_exp (tb); ec = mpfr_get_exp (tc); e0 = i == 1 ? __gmpfr_emin : __gmpfr_emax; if ((i == 1 && ea < eb) || (i == 2 && ea > eb)) { mpfr_set_exp (ta, e0); mpfr_set_exp (tb, e0 + (eb - ea)); mpfr_set_exp (tc, e0 + (ec - ea)); } else { mpfr_set_exp (ta, e0 + (ea - eb)); mpfr_set_exp (tb, e0); mpfr_set_exp (tc, e0 + (ec - eb)); } } __gmpfr_flags = expflags = (randlimb () & 1) ? MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE : 0; inex2 = mpfr_agm (tres, ta, tb, rnd_mode); newflags = __gmpfr_flags; expflags |= MPFR_FLAGS_INEXACT; if (SIGN (inex2) != inex || newflags != expflags || ! mpfr_equal_p (tres, tc)) { printf ("mpfr_agm failed in rnd_mode=%s for\n", mpfr_print_rnd_mode (rnd_mode)); printf (" a = "); mpfr_out_str (stdout, 10, 0, ta, MPFR_RNDN); printf ("\n"); printf (" b = "); mpfr_out_str (stdout, 10, 0, tb, MPFR_RNDN); printf ("\n"); printf ("expected inex = %d, flags = %u,\n" " ", inex, expflags); mpfr_dump (tc); printf ("got inex = %d, flags = %u,\n" " ", inex2, newflags); mpfr_dump (tres); exit (1); } set_emin (emin); set_emax (emax); } mpfr_clears (ta, tb, tc, tres, (mpfr_ptr) 0); }
static void check_special (void) { mpfr_t x, y, m; mpfr_init2 (x, 123L); mpfr_init2 (y, 123L); mpfr_init2 (m, 123L); /* agm(1,nan) is NaN */ mpfr_set_ui (x, 1L, MPFR_RNDN); mpfr_set_nan (y); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); /* agm(1,+inf) == +inf */ mpfr_set_ui (x, 1L, MPFR_RNDN); mpfr_set_inf (y, 1); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_inf_p (m)); MPFR_ASSERTN (mpfr_sgn (m) > 0); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_inf_p (m)); MPFR_ASSERTN (mpfr_sgn (m) > 0); /* agm(+inf,+inf) == +inf */ mpfr_set_inf (x, 1); mpfr_set_inf (y, 1); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_inf_p (m)); MPFR_ASSERTN (mpfr_sgn (m) > 0); /* agm(-inf,+inf) is NaN */ mpfr_set_inf (x, -1); mpfr_set_inf (y, 1); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); /* agm(+0,+inf) is NaN */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_inf (y, 1); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); /* agm(-0,+inf) is NaN */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_set_inf (y, 1); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); /* agm(+0,-inf) is NaN */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_inf (y, -1); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); /* agm(-0,-inf) is NaN */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_set_inf (y, -1); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); /* agm(+0,1) == +0 */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (m) && MPFR_IS_POS(m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (m) && MPFR_IS_POS(m)); /* agm(-0,1) == +0 */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (m) && MPFR_IS_POS(m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (m) && MPFR_IS_POS(m)); /* agm(+0,-1) == +0 */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_si (y, -1, MPFR_RNDN); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (m) && MPFR_IS_POS(m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (m) && MPFR_IS_POS(m)); /* agm(-0,-1) == +0 */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_set_si (y, -1, MPFR_RNDN); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (m) && MPFR_IS_POS(m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (m) && MPFR_IS_POS(m)); /* agm(-0,+0) == +0 */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_set_ui (y, 0, MPFR_RNDN); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (m) && MPFR_IS_POS(m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (m) && MPFR_IS_POS(m)); /* agm(1,1) == 1 */ mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_ui (m ,1) == 0); /* agm(-1,-2) is NaN */ mpfr_set_si (x, -1, MPFR_RNDN); mpfr_set_si (y, -2, MPFR_RNDN); mpfr_agm (m, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); mpfr_agm (m, y, x, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (m)); mpfr_clear (x); mpfr_clear (y); mpfr_clear (m); }
int main() { slong iter; flint_rand_t state; flint_printf("agm...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++) { arb_t a, b, c; fmpq_t q, r; mpfr_t t, u; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); arb_init(c); fmpq_init(q); fmpq_init(r); mpfr_init2(t, prec + 100); mpfr_init2(u, prec + 100); arb_randtest(a, state, 1 + n_randint(state, 200), 3); arb_randtest(b, state, 1 + n_randint(state, 200), 3); arb_randtest(c, state, 1 + n_randint(state, 200), 3); arb_agm(c, a, b, prec); if (arb_equal(a, b)) { if (!arb_contains(c, a)) { flint_printf("FAIL: containment (identity)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); abort(); } } else { arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); arb_get_rand_fmpq(r, state, b, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); fmpq_get_mpfr(u, r, MPFR_RNDN); mpfr_agm(t, t, u, MPFR_RNDN); if (!arb_contains_mpfr(c, t)) { flint_printf("FAIL: containment\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); abort(); } } arb_clear(a); arb_clear(b); arb_clear(c); fmpq_clear(q); fmpq_clear(r); mpfr_clear(t); mpfr_clear(u); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
int mpfr_log (mpfr_ptr r, mpfr_srcptr a, mpfr_rnd_t rnd_mode) { int inexact; mpfr_prec_t p, q; mpfr_t tmp1, tmp2; MPFR_SAVE_EXPO_DECL (expo); MPFR_ZIV_DECL (loop); MPFR_GROUP_DECL(group); MPFR_LOG_FUNC (("a[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (a), mpfr_log_prec, a, rnd_mode), ("r[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (r), mpfr_log_prec, r, inexact)); /* Special cases */ if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a))) { /* If a is NaN, the result is NaN */ if (MPFR_IS_NAN (a)) { MPFR_SET_NAN (r); MPFR_RET_NAN; } /* check for infinity before zero */ else if (MPFR_IS_INF (a)) { if (MPFR_IS_NEG (a)) /* log(-Inf) = NaN */ { MPFR_SET_NAN (r); MPFR_RET_NAN; } else /* log(+Inf) = +Inf */ { MPFR_SET_INF (r); MPFR_SET_POS (r); MPFR_RET (0); } } else /* a is zero */ { MPFR_ASSERTD (MPFR_IS_ZERO (a)); MPFR_SET_INF (r); MPFR_SET_NEG (r); mpfr_set_divby0 (); MPFR_RET (0); /* log(0) is an exact -infinity */ } } /* If a is negative, the result is NaN */ else if (MPFR_UNLIKELY (MPFR_IS_NEG (a))) { MPFR_SET_NAN (r); MPFR_RET_NAN; } /* If a is 1, the result is 0 */ else if (MPFR_UNLIKELY (MPFR_GET_EXP (a) == 1 && mpfr_cmp_ui (a, 1) == 0)) { MPFR_SET_ZERO (r); MPFR_SET_POS (r); MPFR_RET (0); /* only "normal" case where the result is exact */ } q = MPFR_PREC (r); /* use initial precision about q+lg(q)+5 */ p = q + 5 + 2 * MPFR_INT_CEIL_LOG2 (q); /* % ~(mpfr_prec_t)GMP_NUMB_BITS ; m=q; while (m) { p++; m >>= 1; } */ /* if (MPFR_LIKELY(p % GMP_NUMB_BITS != 0)) p += GMP_NUMB_BITS - (p%GMP_NUMB_BITS); */ MPFR_SAVE_EXPO_MARK (expo); MPFR_GROUP_INIT_2 (group, p, tmp1, tmp2); MPFR_ZIV_INIT (loop, p); for (;;) { long m; mpfr_exp_t cancel; /* Calculus of m (depends on p) */ m = (p + 1) / 2 - MPFR_GET_EXP (a) + 1; mpfr_mul_2si (tmp2, a, m, MPFR_RNDN); /* s=a*2^m, err<=1 ulp */ mpfr_div (tmp1, __gmpfr_four, tmp2, MPFR_RNDN);/* 4/s, err<=2 ulps */ mpfr_agm (tmp2, __gmpfr_one, tmp1, MPFR_RNDN); /* AG(1,4/s),err<=3 ulps */ mpfr_mul_2ui (tmp2, tmp2, 1, MPFR_RNDN); /* 2*AG(1,4/s), err<=3 ulps */ mpfr_const_pi (tmp1, MPFR_RNDN); /* compute pi, err<=1ulp */ mpfr_div (tmp2, tmp1, tmp2, MPFR_RNDN); /* pi/2*AG(1,4/s), err<=5ulps */ mpfr_const_log2 (tmp1, MPFR_RNDN); /* compute log(2), err<=1ulp */ mpfr_mul_si (tmp1, tmp1, m, MPFR_RNDN); /* compute m*log(2),err<=2ulps */ mpfr_sub (tmp1, tmp2, tmp1, MPFR_RNDN); /* log(a), err<=7ulps+cancel */ if (MPFR_LIKELY (MPFR_IS_PURE_FP (tmp1) && MPFR_IS_PURE_FP (tmp2))) { cancel = MPFR_GET_EXP (tmp2) - MPFR_GET_EXP (tmp1); MPFR_LOG_MSG (("canceled bits=%ld\n", (long) cancel)); MPFR_LOG_VAR (tmp1); if (MPFR_UNLIKELY (cancel < 0)) cancel = 0; /* we have 7 ulps of error from the above roundings, 4 ulps from the 4/s^2 second order term, plus the canceled bits */ if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp1, p-cancel-4, q, rnd_mode))) break; /* VL: I think it is better to have an increment that it isn't too low; in particular, the increment must be positive even if cancel = 0 (can this occur?). */ p += cancel >= 8 ? cancel : 8; } else { /* TODO: find why this case can occur and what is best to do with it. */ p += 32; } MPFR_ZIV_NEXT (loop, p); MPFR_GROUP_REPREC_2 (group, p, tmp1, tmp2); } MPFR_ZIV_FREE (loop); inexact = mpfr_set (r, tmp1, rnd_mode); /* We clean */ MPFR_GROUP_CLEAR (group); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (r, inexact, rnd_mode); }