void acb_dirichlet_zeta_rs(acb_t res, const acb_t s, slong K, slong prec) { if (acb_is_exact(s)) { acb_dirichlet_zeta_rs_mid(res, s, K, prec); } else { acb_t t; mag_t rad, err, err2; slong acc; acc = acb_rel_accuracy_bits(s); acc = FLINT_MAX(acc, 0); acc = FLINT_MIN(acc, prec); prec = FLINT_MIN(prec, acc + 20); acb_init(t); mag_init(rad); mag_init(err); mag_init(err2); /* rad = rad(s) */ mag_hypot(rad, arb_radref(acb_realref(s)), arb_radref(acb_imagref(s))); /* bound |zeta'(s)| */ acb_dirichlet_zeta_deriv_bound(err, err2, s); /* error <= |zeta'(s)| * rad(s) */ mag_mul(err, err, rad); /* evaluate at midpoint */ acb_get_mid(t, s); acb_dirichlet_zeta_rs_mid(res, t, K, prec); acb_add_error_mag(res, err); acb_clear(t); mag_clear(rad); mag_clear(err); mag_clear(err2); } }
void acb_lambertw_cleared_cut(acb_t res, const acb_t z, const fmpz_t k, int flags, slong prec) { acb_t ez1; acb_init(ez1); /* compute e*z + 1 */ arb_const_e(acb_realref(ez1), prec); acb_mul(ez1, ez1, z, prec); acb_add_ui(ez1, ez1, 1, prec); if (acb_is_exact(z)) { acb_lambertw_main(res, z, ez1, k, flags, prec); } else { acb_t zz; mag_t err, rad; mag_init(err); mag_init(rad); acb_init(zz); acb_lambertw_bound_deriv(err, z, ez1, k); mag_hypot(rad, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); mag_mul(err, err, rad); acb_set(zz, z); mag_zero(arb_radref(acb_realref(zz))); mag_zero(arb_radref(acb_imagref(zz))); /* todo: recompute ez1? */ acb_lambertw_main(res, zz, ez1, k, flags, prec); acb_add_error_mag(res, err); mag_clear(err); mag_clear(rad); acb_clear(zz); } acb_clear(ez1); }
void acb_hypgeom_airy(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong prec) { arf_srcptr re, im; double x, y, t, zmag, z15, term_est, airy_est, abstol; slong n, wp; if (!acb_is_finite(z)) { if (ai != NULL) acb_indeterminate(ai); if (aip != NULL) acb_indeterminate(aip); if (bi != NULL) acb_indeterminate(bi); if (bip != NULL) acb_indeterminate(bip); return; } re = arb_midref(acb_realref(z)); im = arb_midref(acb_imagref(z)); wp = prec * 1.03 + 15; /* tiny input -- use direct method and pick n without underflowing */ if (arf_cmpabs_2exp_si(re, -64) < 0 && arf_cmpabs_2exp_si(im, -64) < 0) { if (arf_cmpabs_2exp_si(re, -wp) < 0 && arf_cmpabs_2exp_si(im, -wp) < 0) { n = 1; /* very tiny input */ } else { if (arf_cmpabs(re, im) > 0) zmag = fmpz_get_d(ARF_EXPREF(re)); else zmag = fmpz_get_d(ARF_EXPREF(im)); zmag = (zmag + 1) * (1.0 / LOG2); n = wp / (-zmag) + 1; } acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp); } /* huge input -- use asymptotics and pick n without overflowing */ else if ((arf_cmpabs_2exp_si(re, 64) > 0 || arf_cmpabs_2exp_si(im, 64) > 0)) { if (arf_cmpabs_2exp_si(re, prec) > 0 || arf_cmpabs_2exp_si(im, prec) > 0) { n = 1; /* very huge input */ } else { x = fmpz_get_d(ARF_EXPREF(re)); y = fmpz_get_d(ARF_EXPREF(im)); zmag = (FLINT_MAX(x, y) - 2) * (1.0 / LOG2); n = asymp_pick_terms(wp, zmag); n = FLINT_MAX(n, 1); } acb_hypgeom_airy_asymp(ai, aip, bi, bip, z, n, wp); } else /* moderate input */ { x = arf_get_d(re, ARF_RND_DOWN); y = arf_get_d(im, ARF_RND_DOWN); zmag = sqrt(x * x + y * y); z15 = zmag * sqrt(zmag); if (zmag >= 4.0 && (n = asymp_pick_terms(wp, log(zmag))) != -1) { acb_hypgeom_airy_asymp(ai, aip, bi, bip, z, n, wp); } else if (zmag <= 1.5) { t = 3 * (wp * LOG2) / (2 * z15 * EXP1); t = (wp * LOG2) / (2 * d_lambertw(t)); n = FLINT_MAX(t + 1, 2); acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp); } else { /* estimate largest term: log2(exp(2(z^3/9)^(1/2))) */ term_est = 0.96179669392597560491 * z15; /* estimate the smaller of Ai and Bi */ airy_est = estimate_airy(x, y, (ai != NULL || aip != NULL)); /* estimate absolute tolerance and necessary working precision */ abstol = airy_est - wp; wp = wp + term_est - airy_est; wp = FLINT_MAX(wp, 10); t = 3 * (-abstol * LOG2) / (2 * z15 * EXP1); t = (-abstol * LOG2) / (2 * d_lambertw(t)); n = FLINT_MAX(t + 1, 2); if (acb_is_exact(z)) acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp); else acb_hypgeom_airy_direct_prop(ai, aip, bi, bip, z, n, wp); } } if (ai != NULL) acb_set_round(ai, ai, prec); if (aip != NULL) acb_set_round(aip, aip, prec); if (bi != NULL) acb_set_round(bi, bi, prec); if (bip != NULL) acb_set_round(bip, bip, prec); }
void acb_hypgeom_erf_asymp(acb_t res, const acb_t z, int complementary, slong prec, slong prec2) { acb_t a, t, u; acb_init(a); acb_init(t); acb_init(u); if (!acb_is_exact(z) && (arf_cmpabs_ui(arb_midref(acb_realref(z)), prec) < 0) && (arf_cmpabs_ui(arb_midref(acb_imagref(z)), prec) < 0)) { acb_t zmid; mag_t re_err, im_err; acb_init(zmid); mag_init(re_err); mag_init(im_err); acb_hypgeom_erf_propagated_error(re_err, im_err, z); arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z))); acb_hypgeom_erf_asymp(res, zmid, complementary, prec, prec2); arb_add_error_mag(acb_realref(res), re_err); arb_add_error_mag(acb_imagref(res), im_err); acb_clear(zmid); mag_clear(re_err); mag_clear(im_err); return; } acb_one(a); acb_mul_2exp_si(a, a, -1); acb_mul(t, z, z, prec2); acb_hypgeom_u_asymp(u, a, a, t, -1, prec2); acb_neg(t, t); acb_exp(t, t, prec2); acb_mul(u, u, t, prec2); arb_const_sqrt_pi(acb_realref(t), prec2); arb_zero(acb_imagref(t)); acb_mul(t, t, z, prec2); acb_div(u, u, t, prec2); /* branch cut term: -1 or 1 */ acb_csgn(acb_realref(t), z); arb_zero(acb_imagref(t)); if (complementary) { /* erfc(z) = 1 - erf(z) = u - (sgn - 1) */ acb_sub_ui(t, t, 1, prec); acb_sub(t, u, t, prec); } else { /* erf(z) = sgn - u */ acb_sub(t, t, u, prec); } if (arb_is_zero(acb_imagref(z))) { arb_zero(acb_imagref(t)); } else if (arb_is_zero(acb_realref(z))) { if (complementary) arb_one(acb_realref(t)); else arb_zero(acb_realref(t)); } acb_set(res, t); acb_clear(a); acb_clear(t); acb_clear(u); }
void acb_hypgeom_2f1(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int flags, slong prec) { int algorithm, regularized; regularized = flags & ACB_HYPGEOM_2F1_REGULARIZED; if (!acb_is_finite(a) || !acb_is_finite(b) || !acb_is_finite(c) || !acb_is_finite(z)) { acb_indeterminate(res); return; } if (acb_is_zero(z)) { if (regularized) acb_rgamma(res, c, prec); else acb_one(res); return; } if (regularized && acb_is_int(c) && arb_is_nonpositive(acb_realref(c))) { if ((acb_is_int(a) && arb_is_nonpositive(acb_realref(a)) && arf_cmp(arb_midref(acb_realref(a)), arb_midref(acb_realref(c))) >= 0) || (acb_is_int(b) && arb_is_nonpositive(acb_realref(b)) && arf_cmp(arb_midref(acb_realref(b)), arb_midref(acb_realref(c))) >= 0)) { acb_zero(res); return; } } if (regularized && acb_eq(a, c)) { _acb_hypgeom_2f1r_reduced(res, b, c, z, prec); return; } if (regularized && acb_eq(b, c)) { _acb_hypgeom_2f1r_reduced(res, a, c, z, prec); return; } /* polynomial */ if (acb_is_int(a) && arf_sgn(arb_midref(acb_realref(a))) <= 0 && arf_cmpabs_ui(arb_midref(acb_realref(a)), prec) < 0) { acb_hypgeom_2f1_direct(res, a, b, c, z, regularized, prec); return; } /* polynomial */ if (acb_is_int(b) && arf_sgn(arb_midref(acb_realref(b))) <= 0 && arf_cmpabs_ui(arb_midref(acb_realref(b)), prec) < 0) { acb_hypgeom_2f1_direct(res, a, b, c, z, regularized, prec); return; } /* Try to reduce to a polynomial case using the Pfaff transformation */ /* TODO: look at flags for integer c-b, c-a here, even when c is nonexact */ if (acb_is_exact(c)) { acb_t t; acb_init(t); acb_sub(t, c, b, prec); if (acb_is_int(t) && arb_is_nonpositive(acb_realref(t))) { acb_hypgeom_2f1_transform(res, a, b, c, z, flags, 1, prec); acb_clear(t); return; } acb_sub(t, c, a, prec); if (acb_is_int(t) && arb_is_nonpositive(acb_realref(t))) { int f1, f2; /* When swapping a, b, also swap the flags. */ f1 = flags & ACB_HYPGEOM_2F1_AC; f2 = flags & ACB_HYPGEOM_2F1_BC; flags &= ~ACB_HYPGEOM_2F1_AC; flags &= ~ACB_HYPGEOM_2F1_BC; if (f1) flags |= ACB_HYPGEOM_2F1_BC; if (f2) flags |= ACB_HYPGEOM_2F1_AC; acb_hypgeom_2f1_transform(res, b, a, c, z, flags, 1, prec); acb_clear(t); return; } acb_clear(t); } /* special value at z = 1 */ if (acb_is_one(z)) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); acb_sub(t, c, a, prec); acb_sub(u, c, b, prec); acb_sub(v, t, b, prec); if (arb_is_positive(acb_realref(v))) { acb_rgamma(t, t, prec); acb_rgamma(u, u, prec); acb_mul(t, t, u, prec); acb_gamma(v, v, prec); acb_mul(t, t, v, prec); if (!regularized) { acb_gamma(v, c, prec); acb_mul(t, t, v, prec); } acb_set(res, t); } else { acb_indeterminate(res); } acb_clear(t); acb_clear(u); acb_clear(v); return; } algorithm = acb_hypgeom_2f1_choose(z); if (algorithm == 0) { acb_hypgeom_2f1_direct(res, a, b, c, z, regularized, prec); } else if (algorithm >= 1 && algorithm <= 5) { acb_hypgeom_2f1_transform(res, a, b, c, z, flags, algorithm, prec); } else { acb_hypgeom_2f1_corner(res, a, b, c, z, regularized, prec); } }
static void acb_log_sin_pi_half(acb_t res, const acb_t z, slong prec, int upper) { acb_t t, u, zmid; arf_t n; arb_t pi; acb_init(t); acb_init(u); acb_init(zmid); arf_init(n); arb_init(pi); arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z))); arf_floor(n, arb_midref(acb_realref(zmid))); arb_sub_arf(acb_realref(zmid), acb_realref(zmid), n, prec); arb_const_pi(pi, prec); if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(zmid)), 2) < 1) { acb_sin_pi(t, zmid, prec); acb_log(t, t, prec); } else /* i*pi*(z-0.5) + log((1-exp(-2i*pi*z))/2) */ { acb_mul_2exp_si(t, zmid, 1); acb_neg(t, t); if (upper) acb_conj(t, t); acb_exp_pi_i(t, t, prec); acb_sub_ui(t, t, 1, prec); acb_neg(t, t); acb_mul_2exp_si(t, t, -1); acb_log(t, t, prec); acb_one(u); acb_mul_2exp_si(u, u, -1); acb_sub(u, zmid, u, prec); if (upper) acb_conj(u, u); acb_mul_onei(u, u); acb_addmul_arb(t, u, pi, prec); if (upper) acb_conj(t, t); } if (upper) arb_submul_arf(acb_imagref(t), pi, n, prec); else arb_addmul_arf(acb_imagref(t), pi, n, prec); /* propagated error bound from the derivative pi cot(pi z) */ if (!acb_is_exact(z)) { mag_t zm, um; mag_init(zm); mag_init(um); acb_cot_pi(u, z, prec); acb_mul_arb(u, u, pi, prec); mag_hypot(zm, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); acb_get_mag(um, u); mag_mul(um, um, zm); acb_add_error_mag(t, um); mag_clear(zm); mag_clear(um); } acb_set(res, t); acb_clear(t); acb_clear(u); acb_clear(zmid); arf_clear(n); arb_clear(pi); }