/* Extremely close to the branch point at -1/e, use the series expansion directly. */ int acb_lambertw_try_near_branch_point(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, int flags, slong prec) { if (fmpz_is_zero(k) || (fmpz_is_one(k) && arb_is_negative(acb_imagref(z))) || (fmpz_equal_si(k, -1) && arb_is_nonnegative(acb_imagref(z)))) { if (acb_contains_zero(ez1) || (arf_cmpabs_2exp_si(arb_midref(acb_realref(ez1)), -prec / 4.5 - 6) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(ez1)), -prec / 4.5 - 6) < 0)) { acb_t t; acb_init(t); acb_mul_2exp_si(t, ez1, 1); acb_sqrt(t, t, prec); if (!fmpz_is_zero(k)) acb_neg(t, t); acb_lambertw_branchpoint_series(res, t, 1, prec); acb_clear(t); return 1; } } return 0; }
/* f(z) = erf(z/sqrt(0.0002)*0.5 +1.5)*exp(-z), example provided by Silviu-Ioan Filip */ int f_erf_bent(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); acb_set_ui(t, 1250); acb_sqrt(t, t, prec); acb_mul(t, t, z, prec); acb_set_d(res, 1.5); acb_add(res, res, t, prec); acb_hypgeom_erf(res, res, prec); acb_neg(t, z); acb_exp(t, t, prec); acb_mul(res, res, t, prec); acb_clear(t); return 0; }
int main() { slong iter; flint_rand_t state; flint_printf("csgn...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++) { acb_t x, y; arb_t a; slong prec; acb_init(x); acb_init(y); arb_init(a); acb_randtest_special(x, state, 1 + n_randint(state, 200), 2 + n_randint(state, 100)); arb_randtest_special(a, state, 1 + n_randint(state, 200), 2 + n_randint(state, 100)); prec = 2 + n_randint(state, 200); acb_csgn(a, x); if (acb_is_zero(x)) { acb_zero(y); } else { acb_mul(y, x, x, prec); acb_sqrt(y, y, prec); acb_div(y, y, x, prec); } if (!arb_contains(acb_realref(y), a)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_printd(x, 15); flint_printf("\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("y = "); acb_printd(y, 15); flint_printf("\n\n"); abort(); } acb_clear(x); acb_clear(y); arb_clear(a); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void _acb_poly_sqrt_series(acb_ptr g, acb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); while (hlen > 0 && acb_is_zero(h + hlen - 1)) hlen--; if (hlen <= 1) { acb_sqrt(g, h, prec); _acb_vec_zero(g + 1, len - 1); } else if (len == 2) { acb_sqrt(g, h, prec); acb_div(g + 1, h + 1, h, prec); acb_mul(g + 1, g + 1, g, prec); acb_mul_2exp_si(g + 1, g + 1, -1); } else if (_acb_vec_is_zero(h + 1, hlen - 2)) { acb_t t; acb_init(t); arf_set_si_2exp_si(arb_midref(acb_realref(t)), 1, -1); _acb_poly_binomial_pow_acb_series(g, h, hlen, t, len, prec); acb_clear(t); } else { acb_ptr t; t = _acb_vec_init(len); _acb_poly_rsqrt_series(t, h, hlen, len, prec); _acb_poly_mullow(g, t, len, h, hlen, len, prec); _acb_vec_clear(t, len); } }
void acb_acosh(acb_t res, const acb_t z, slong prec) { if (acb_is_one(z)) { acb_zero(res); } else { acb_t t, u; acb_init(t); acb_init(u); acb_add_ui(t, z, 1, prec); acb_sub_ui(u, z, 1, prec); acb_sqrt(t, t, prec); acb_sqrt(u, u, prec); acb_mul(t, t, u, prec); acb_add(t, t, z, prec); if (!arb_is_zero(acb_imagref(z))) { acb_log(res, t, prec); } else { /* pure imaginary on (-1,1) */ arb_abs(acb_realref(u), acb_realref(z)); arb_one(acb_imagref(u)); acb_log(res, t, prec); if (arb_lt(acb_realref(u), acb_imagref(u))) arb_zero(acb_realref(res)); } acb_clear(t); acb_clear(u); } }
void acb_modular_elliptic_k(acb_t k, const acb_t m, slong prec) { acb_t t; acb_init(t); acb_sub_ui(t, m, 1, prec); acb_neg(t, t); acb_sqrt(t, t, prec); acb_agm1(k, t, prec); acb_const_pi(t, prec); acb_div(k, t, k, prec); acb_mul_2exp_si(k, k, -1); acb_clear(t); }
void acb_hypgeom_erf_asymp(acb_t res, const acb_t z, slong prec, slong prec2) { acb_t a, t, u; acb_init(a); acb_init(t); acb_init(u); 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); acb_const_pi(t, prec2); acb_sqrt(t, t, prec2); acb_mul(t, t, z, prec2); acb_div(u, u, t, prec2); /* branch cut term: -1 or 1 */ if (arb_contains_zero(acb_realref(z))) { arb_zero(acb_imagref(t)); arf_zero(arb_midref(acb_realref(t))); mag_one(arb_radref(acb_realref(t))); } else { acb_set_si(t, arf_sgn(arb_midref(acb_realref(z)))); } 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))) arb_zero(acb_realref(t)); acb_set(res, t); acb_clear(a); acb_clear(t); acb_clear(u); }
/* assumes no aliasing */ slong acb_lambertw_initial(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, slong prec) { /* Handle z very close to 0 on the principal branch. */ if (fmpz_is_zero(k) && (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -20) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -20) <= 0)) { acb_set(res, z); acb_submul(res, res, res, prec); return 40; /* could be tightened... */ } /* For moderate input not close to the branch point, compute a double approximation as the initial value. */ if (fmpz_is_zero(k) && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 400) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 400) < 0 && (arf_cmp_d(arb_midref(acb_realref(z)), -0.37) < 0 || arf_cmp_d(arb_midref(acb_realref(z)), -0.36) > 0 || arf_cmpabs_d(arb_midref(acb_imagref(z)), 0.01) > 0)) { acb_lambertw_principal_d(res, z); return 48; } /* Check if we are close to the branch point at -1/e. */ if ((fmpz_is_zero(k) || (fmpz_is_one(k) && arb_is_negative(acb_imagref(z))) || (fmpz_equal_si(k, -1) && arb_is_nonnegative(acb_imagref(z)))) && ((arf_cmpabs_2exp_si(arb_midref(acb_realref(ez1)), -2) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(ez1)), -2) <= 0))) { acb_t t; acb_init(t); acb_mul_2exp_si(t, ez1, 1); mag_zero(arb_radref(acb_realref(t))); mag_zero(arb_radref(acb_imagref(t))); acb_mul_ui(t, t, 3, prec); acb_sqrt(t, t, prec); if (!fmpz_is_zero(k)) acb_neg(t, t); acb_lambertw_branchpoint_series(res, t, 0, prec); acb_clear(t); return 1; /* todo: estimate */ } acb_lambertw_initial_asymp(res, z, k, prec); return 1; /* todo: estimate */ }
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); }
void integrals_edge_factors_gc(acb_ptr res, const acb_t cab, const acb_t ba2, sec_t c, slong prec) { slong i; acb_t cj, ci; acb_init(cj); acb_init(ci); /* polynomial shift */ acb_vec_polynomial_shift(res, cab, c.g, prec); /* constants cj, j = 1 */ /* c_1 = (1-zeta^-1) ba2^(-d/2) (-I)^i * = 2 / ba2^(d/2) */ acb_pow_ui(cj, ba2, c.d / 2, prec); if (c.d % 2) { acb_t t; acb_init(t); acb_sqrt(t, ba2, prec); acb_mul(cj, cj, t, prec); acb_clear(t); } acb_inv(cj, cj, prec); acb_mul_2exp_si(cj, cj, 1); _acb_vec_scalar_mul(res, res, c.g, cj, prec); /* constant ci = -I * ba2*/ acb_one(ci); for (i = 1; i < c.g; i++) { acb_mul(ci, ci, ba2, prec); acb_div_onei(ci, ci); acb_mul(res + i, res + i, ci, prec); } acb_clear(ci); acb_clear(cj); }
int main() { long iter; flint_rand_t state; printf("eta...."); fflush(stdout); flint_randinit(state); /* Test functional equation */ for (iter = 0; iter < 10000; iter++) { acb_t tau1, tau2, z1, z2, z3, t; fmpq_t arg; long e0, prec0, prec1, prec2; psl2z_t g; psl2z_init(g); fmpq_init(arg); acb_init(tau1); acb_init(tau2); acb_init(z1); acb_init(z2); acb_init(z3); acb_init(t); e0 = 1 + n_randint(state, 200); prec0 = 2 + n_randint(state, 2000); prec1 = 2 + n_randint(state, 2000); prec2 = 2 + n_randint(state, 2000); acb_randtest(tau1, state, prec0, e0); acb_randtest(tau2, state, prec0, e0); acb_randtest(z1, state, prec0, e0); acb_randtest(z2, state, prec0, e0); psl2z_randtest(g, state, 1 + n_randint(state, 200)); acb_modular_transform(tau2, g, tau1, prec0); acb_modular_eta(z1, tau1, prec1); acb_modular_eta(z2, tau2, prec2); /* apply transformation */ fmpq_set_si(arg, acb_modular_epsilon_arg(g), 12); arb_sin_cos_pi_fmpq(acb_imagref(t), acb_realref(t), arg, prec1); acb_mul(z3, z1, t, prec1); acb_mul_fmpz(t, tau1, &g->c, prec1); acb_add_fmpz(t, t, &g->d, prec1); acb_sqrt(t, t, prec1); acb_mul(z3, z3, t, prec1); if (!acb_overlaps(z3, z2)) { printf("FAIL (overlap)\n"); printf("tau1 = "); acb_printd(tau1, 15); printf("\n\n"); printf("tau2 = "); acb_printd(tau2, 15); printf("\n\n"); printf("g = "); psl2z_print(g); printf("\n\n"); printf("z1 = "); acb_printd(z1, 15); printf("\n\n"); printf("z2 = "); acb_printd(z2, 15); printf("\n\n"); printf("z3 = "); acb_printd(z3, 15); printf("\n\n"); abort(); } acb_modular_eta(tau1, tau1, prec2); if (!acb_overlaps(z1, tau1)) { printf("FAIL (aliasing)\n"); printf("tau1 = "); acb_print(tau1); printf("\n\n"); printf("tau2 = "); acb_print(tau2); printf("\n\n"); printf("z1 = "); acb_print(z1); printf("\n\n"); printf("z2 = "); acb_print(z2); printf("\n\n"); abort(); } acb_clear(tau1); acb_clear(tau2); acb_clear(z1); acb_clear(z2); acb_clear(z3); acb_clear(t); psl2z_clear(g); fmpq_clear(arg); } /* Test special values */ for (iter = 0; iter < 100; iter++) { acb_t tau, z; arb_t t, u; long prec; acb_init(tau); acb_init(z); arb_init(t); arb_init(u); prec = 2 + n_randint(state, 2000); acb_randtest(z, state, prec, 10); acb_onei(tau); acb_modular_eta(z, tau, prec); arb_one(t); arb_mul_2exp_si(t, t, -2); arb_gamma(t, t, prec); arb_const_pi(u, prec); arb_root(u, u, 4, prec); arb_pow_ui(u, u, 3, prec); arb_div(t, t, u, prec); arb_mul_2exp_si(t, t, -1); if (!arb_overlaps(acb_realref(z), t) || !arb_contains_zero(acb_imagref(z))) { printf("FAIL (value 1)\n"); printf("tau = "); acb_print(tau); printf("\n\n"); printf("z = "); acb_print(z); printf("\n\n"); abort(); } acb_clear(tau); acb_clear(z); arb_clear(t); arb_clear(u); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
int main() { slong iter; flint_rand_t state; flint_printf("fresnel...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++) { acb_t z, z2, s, c, u, v; slong prec1, prec2; int normalized; prec1 = 2 + n_randint(state, 500); prec2 = 2 + n_randint(state, 500); acb_init(z); acb_init(z2); acb_init(s); acb_init(c); acb_init(u); acb_init(v); acb_randtest_special(z, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(s, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); acb_randtest_special(c, state, 1 + n_randint(state, 500), 1 + n_randint(state, 100)); normalized = n_randint(state, 2); /* test S(z) + i C(z) = sqrt(pi/2) (1+i)/2 erf((1+i)/sqrt(2) z) */ /* u = rhs */ acb_onei(u); acb_sqrt(u, u, prec1); acb_mul(u, u, z, prec1); acb_hypgeom_erf(u, u, prec1); acb_mul_onei(v, u); acb_add(u, u, v, prec1); acb_mul_2exp_si(u, u, -1); acb_const_pi(v, prec1); acb_mul_2exp_si(v, v, -1); acb_sqrt(v, v, prec1); acb_mul(u, u, v, prec1); if (normalized) { acb_const_pi(v, prec2); acb_mul_2exp_si(v, v, -1); acb_sqrt(v, v, prec2); acb_div(z2, z, v, prec2); } else { acb_set(z2, z); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_fresnel(s, c, z2, normalized, prec2); break; case 1: acb_hypgeom_fresnel(s, NULL, z2, normalized, prec2); acb_hypgeom_fresnel(NULL, c, z2, normalized, prec2); break; case 2: acb_set(s, z2); acb_hypgeom_fresnel(s, c, s, normalized, prec2); break; case 3: acb_set(c, z2); acb_hypgeom_fresnel(s, c, c, normalized, prec2); break; default: acb_hypgeom_fresnel(s, c, z2, normalized, prec2); } if (normalized) { acb_mul(s, s, v, prec2); acb_mul(c, c, v, prec2); } acb_mul_onei(v, c); acb_add(v, v, s, prec2); if (!acb_overlaps(u, v)) { flint_printf("FAIL: overlap\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_printf("u = "); acb_printd(u, 30); flint_printf("\n\n"); flint_printf("v = "); acb_printd(v, 30); flint_printf("\n\n"); abort(); } acb_clear(z); acb_clear(z2); acb_clear(s); acb_clear(c); acb_clear(u); acb_clear(v); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void acb_modular_elliptic_k_cpx(acb_ptr w, const acb_t m, slong len, slong prec) { acb_t t, u, msub1m, m2sub1; slong k, n; if (len < 1) return; if (len == 1) { acb_modular_elliptic_k(w, m, prec); return; } if (acb_is_zero(m)) { acb_const_pi(w, prec); acb_mul_2exp_si(w, w, -1); for (k = 1; k < len; k++) { acb_mul_ui(w + k, w + k - 1, (2 * k - 1) * (2 * k - 1), prec); acb_div_ui(w + k, w + k, 4 * k * k, prec); } return; } acb_init(t); acb_init(u); acb_init(msub1m); acb_init(m2sub1); acb_sub_ui(msub1m, m, 1, prec); acb_neg(t, msub1m); acb_sqrt(t, t, prec); acb_mul(msub1m, msub1m, m, prec); acb_mul_2exp_si(m2sub1, m, 1); acb_sub_ui(m2sub1, m2sub1, 1, prec); acb_agm1_cpx(w, t, 2, prec); /* pi M'(t) / (4 t M(t)^2) */ acb_mul(u, w, w, prec); acb_mul(t, t, u, prec); acb_div(w + 1, w + 1, t, prec); acb_const_pi(u, prec); acb_mul(w + 1, w + 1, u, prec); acb_mul_2exp_si(w + 1, w + 1, -2); /* pi / (2 M(t)) */ acb_const_pi(u, prec); acb_div(w, u, w, prec); acb_mul_2exp_si(w, w, -1); acb_inv(t, msub1m, prec); for (k = 2; k < len; k++) { n = k - 2; acb_mul_ui(w + k, w + n, (2 * n + 1) * (2 * n + 1), prec); acb_mul(u, w + n + 1, m2sub1, prec); acb_addmul_ui(w + k, u, (n + 1) * (n + 1) * 4, prec); acb_mul(w + k, w + k, t, prec); acb_div_ui(w + k, w + k, 4 * (n + 1) * (n + 2), prec); acb_neg(w + k, w + k); } acb_clear(t); acb_clear(u); acb_clear(msub1m); acb_clear(m2sub1); }
void _acb_hypgeom_legendre_q_double(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); if (acb_is_int(m)) { acb_sub_ui(t, z, 1, prec); acb_mul_2exp_si(u, m, -1); acb_pow(v, t, u, prec); acb_neg(t, t); acb_neg(u, u); acb_pow(t, t, u, prec); acb_mul(t, t, v, prec); acb_hypgeom_legendre_q(u, n, m, z, 0, prec); acb_mul(t, t, u, prec); acb_mul_2exp_si(u, m, -1); if (!acb_is_int(u)) acb_neg(t, t); acb_sub_ui(u, z, 1, prec); acb_sqrt(u, u, prec); acb_sub_ui(v, z, 1, prec); acb_neg(v, v); acb_rsqrt(v, v, prec); acb_mul(u, u, v, prec); acb_hypgeom_legendre_p(v, n, m, z, 1, prec); acb_mul(u, u, v, prec); acb_const_pi(v, prec); acb_mul(u, u, v, prec); acb_mul_2exp_si(u, u, -1); acb_sub(res, t, u, prec); } else { acb_sub(t, n, m, prec); acb_add_ui(t, t, 1, prec); acb_mul_2exp_si(u, m, 1); acb_rising(t, t, u, prec); acb_neg(u, m); acb_hypgeom_legendre_p(u, n, u, z, 1, prec); acb_mul(t, t, u, prec); acb_hypgeom_legendre_p(u, n, m, z, 1, prec); acb_sub(t, u, t, prec); acb_exp_pi_i(u, m, prec); acb_mul(t, t, u, prec); acb_sin_pi(u, m, prec); acb_div(t, t, u, prec); acb_const_pi(u, prec); acb_mul(t, t, u, prec); acb_mul_2exp_si(t, t, -1); acb_set(res, t); } acb_clear(t); acb_clear(u); acb_clear(v); }