void arb_agm(arb_t z, const arb_t x, const arb_t y, long prec) { arb_t t, u, v, w; if (arb_contains_negative(x) || arb_contains_negative(y)) { arb_indeterminate(z); return; } if (arb_is_zero(x) || arb_is_zero(y)) { arb_zero(z); return; } arb_init(t); arb_init(u); arb_init(v); arb_init(w); arb_set(t, x); arb_set(u, y); while (!arb_overlaps(t, u) && !arb_contains_nonpositive(t) && !arb_contains_nonpositive(u)) { arb_add(v, t, u, prec); arb_mul_2exp_si(v, v, -1); arb_mul(w, t, u, prec); arb_sqrt(w, w, prec); arb_swap(v, t); arb_swap(w, u); } if (!arb_is_finite(t) || !arb_is_finite(u)) { arb_indeterminate(z); } else { arb_union(z, t, u, prec); } arb_clear(t); arb_clear(u); arb_clear(v); arb_clear(w); }
void acb_pow_arb(acb_t z, const acb_t x, const arb_t y, long prec) { const arf_struct * ymid = arb_midref(y); const mag_struct * yrad = arb_radref(y); if (arb_is_zero(y)) { acb_one(z); return; } if (mag_is_zero(yrad)) { /* small half-integer or integer */ if (arf_cmpabs_2exp_si(ymid, BINEXP_LIMIT) < 0 && arf_is_int_2exp_si(ymid, -1)) { fmpz_t e; fmpz_init(e); if (arf_is_int(ymid)) { arf_get_fmpz_fixed_si(e, ymid, 0); acb_pow_fmpz_binexp(z, x, e, prec); } else { /* hack: give something finite here (should fix sqrt/rsqrt etc) */ if (arb_contains_zero(acb_imagref(x)) && arb_contains_nonpositive(acb_realref(x))) { _acb_pow_arb_exp(z, x, y, prec); fmpz_clear(e); return; } arf_get_fmpz_fixed_si(e, ymid, -1); acb_sqrt(z, x, prec + fmpz_bits(e)); acb_pow_fmpz_binexp(z, z, e, prec); } fmpz_clear(e); return; } } _acb_pow_arb_exp(z, x, y, prec); }
int f_lambertw(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); prec = FLINT_MIN(prec, acb_rel_accuracy_bits(z) + 10); if (order != 0) { /* check for branch cut */ arb_const_e(acb_realref(t), prec); acb_inv(t, t, prec); acb_add(t, t, z, prec); if (arb_contains_zero(acb_imagref(t)) && arb_contains_nonpositive(acb_realref(t))) { acb_indeterminate(t); } } if (acb_is_finite(t)) { fmpz_t k; fmpz_init(k); acb_lambertw(res, z, k, 0, prec); fmpz_clear(k); } else { acb_indeterminate(res); } acb_clear(t); return 0; }
void arb_sqrtpos(arb_t z, const arb_t x, long prec) { if (!arb_is_finite(x)) { if (mag_is_zero(arb_radref(x)) && arf_is_pos_inf(arb_midref(x))) arb_pos_inf(z); else arb_zero_pm_inf(z); } else if (arb_contains_nonpositive(x)) { arf_t t; arf_init(t); arf_set_mag(t, arb_radref(x)); arf_add(t, arb_midref(x), t, MAG_BITS, ARF_RND_CEIL); if (arf_sgn(t) <= 0) { arb_zero(z); } else { arf_sqrt(t, t, MAG_BITS, ARF_RND_CEIL); arf_mul_2exp_si(t, t, -1); arf_set(arb_midref(z), t); arf_get_mag(arb_radref(z), t); } arf_clear(t); } else { arb_sqrt(z, x, prec); } arb_nonnegative_part(z, z, prec); }
int main() { slong iter; flint_rand_t state; flint_printf("log...."); fflush(stdout); flint_randinit(state); /* compare with mpfr */ for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 200); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); do { arb_randtest(a, state, 1 + n_randint(state, 200), 10); } while (arb_contains_nonpositive(a)); arb_randtest(b, state, 1 + n_randint(state, 200), 10); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); /* todo: estimate cancellation precisely */ if (mpfr_cmp_d(t, 1 - 1e-10) > 0 && mpfr_cmp_d(t, 1 + 1e-10) < 0) { mpfr_set_prec(t, prec + 1000); fmpq_get_mpfr(t, q, MPFR_RNDN); } mpfr_log(t, t, MPFR_RNDN); arb_log(b, a, prec); if (!arb_contains_mpfr(b, 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"); abort(); } arb_log(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* compare with mpfr (higher precision) */ for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++) { arb_t a, b; fmpq_t q; mpfr_t t; slong prec = 2 + n_randint(state, 6000); arb_init(a); arb_init(b); fmpq_init(q); mpfr_init2(t, prec + 100); do { arb_randtest(a, state, 1 + n_randint(state, 6000), 10); } while (arb_contains_nonpositive(a)); arb_randtest(b, state, 1 + n_randint(state, 6000), 10); arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200)); fmpq_get_mpfr(t, q, MPFR_RNDN); /* todo: estimate cancellation precisely */ if (mpfr_cmp_d(t, 1 - 1e-10) > 0 && mpfr_cmp_d(t, 1 + 1e-10) < 0) { mpfr_set_prec(t, prec + 10000); fmpq_get_mpfr(t, q, MPFR_RNDN); } mpfr_log(t, t, MPFR_RNDN); arb_log(b, a, prec); if (!arb_contains_mpfr(b, 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"); abort(); } arb_log(a, a, prec); if (!arb_equal(a, b)) { flint_printf("FAIL: aliasing\n\n"); abort(); } arb_clear(a); arb_clear(b); fmpq_clear(q); mpfr_clear(t); } /* test large numbers */ for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++) { arb_t a, b, ab, lab, la, lb, lalb; slong prec = 2 + n_randint(state, 6000); arb_init(a); arb_init(b); arb_init(ab); arb_init(lab); arb_init(la); arb_init(lb); arb_init(lalb); arb_randtest(a, state, 1 + n_randint(state, 400), 400); arb_randtest(b, state, 1 + n_randint(state, 400), 400); arb_log(la, a, prec); arb_log(lb, b, prec); arb_mul(ab, a, b, prec); arb_log(lab, ab, prec); arb_add(lalb, la, lb, prec); if (!arb_overlaps(lab, lalb)) { 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("la = "); arb_print(la); flint_printf("\n\n"); flint_printf("lb = "); arb_print(lb); flint_printf("\n\n"); flint_printf("ab = "); arb_print(ab); flint_printf("\n\n"); flint_printf("lab = "); arb_print(lab); flint_printf("\n\n"); flint_printf("lalb = "); arb_print(lalb); flint_printf("\n\n"); abort(); } arb_log(a, a, prec); if (!arb_overlaps(a, la)) { flint_printf("FAIL: aliasing\n\n"); abort(); } arb_clear(a); arb_clear(b); arb_clear(ab); arb_clear(lab); arb_clear(la); arb_clear(lb); arb_clear(lalb); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void _arb_poly_zeta_series(arb_ptr res, arb_srcptr h, long hlen, const arb_t a, int deflate, long len, long prec) { long i; acb_t cs, ca; acb_ptr z; arb_ptr t, u; if (arb_contains_nonpositive(a)) { _arb_vec_indeterminate(res, len); return; } hlen = FLINT_MIN(hlen, len); z = _acb_vec_init(len); t = _arb_vec_init(len); u = _arb_vec_init(len); acb_init(cs); acb_init(ca); /* use reflection formula */ if (arf_sgn(arb_midref(h)) < 0 && arb_is_one(a)) { /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */ arb_t pi; arb_ptr f, s1, s2, s3, s4; arb_init(pi); f = _arb_vec_init(2); s1 = _arb_vec_init(len); s2 = _arb_vec_init(len); s3 = _arb_vec_init(len); s4 = _arb_vec_init(len); arb_const_pi(pi, prec); /* s1 = (2*pi)**s */ arb_mul_2exp_si(pi, pi, 1); _arb_poly_pow_cpx(s1, pi, h, len, prec); arb_mul_2exp_si(pi, pi, -1); /* s2 = sin(pi*s/2) / pi */ arb_set(f, h); arb_one(f + 1); arb_mul_2exp_si(f, f, -1); arb_mul_2exp_si(f + 1, f + 1, -1); _arb_poly_sin_pi_series(s2, f, 2, len, prec); _arb_vec_scalar_div(s2, s2, len, pi, prec); /* s3 = gamma(1-s) */ arb_sub_ui(f, h, 1, prec); arb_neg(f, f); arb_set_si(f + 1, -1); _arb_poly_gamma_series(s3, f, 2, len, prec); /* s4 = zeta(1-s) */ arb_sub_ui(f, h, 1, prec); arb_neg(f, f); acb_set_arb(cs, f); acb_one(ca); _acb_poly_zeta_cpx_series(z, cs, ca, 0, len, prec); for (i = 0; i < len; i++) arb_set(s4 + i, acb_realref(z + i)); for (i = 1; i < len; i += 2) arb_neg(s4 + i, s4 + i); _arb_poly_mullow(u, s1, len, s2, len, len, prec); _arb_poly_mullow(s1, s3, len, s4, len, len, prec); _arb_poly_mullow(t, u, len, s1, len, len, prec); /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */ if (deflate) { arb_sub_ui(u, h, 1, prec); arb_neg(u, u); arb_inv(u, u, prec); for (i = 1; i < len; i++) arb_mul(u + i, u + i - 1, u, prec); _arb_vec_add(t, t, u, len, prec); } arb_clear(pi); _arb_vec_clear(f, 2); _arb_vec_clear(s1, len); _arb_vec_clear(s2, len); _arb_vec_clear(s3, len); _arb_vec_clear(s4, len); } else { acb_set_arb(cs, h); acb_set_arb(ca, a); _acb_poly_zeta_cpx_series(z, cs, ca, deflate, len, prec); for (i = 0; i < len; i++) arb_set(t + i, acb_realref(z + i)); } /* compose with nonconstant part */ arb_zero(u); _arb_vec_set(u + 1, h + 1, hlen - 1); _arb_poly_compose_series(res, t, len, u, hlen, len, prec); _acb_vec_clear(z, len); _arb_vec_clear(t, len); _arb_vec_clear(u, len); acb_init(cs); acb_init(ca); }