void acb_dot_simple(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) { slong i; if (len <= 0) { if (initial == NULL) acb_zero(res); else acb_set_round(res, initial, prec); return; } if (initial == NULL) { acb_mul(res, x, y, prec); } else { if (subtract) acb_neg(res, initial); else acb_set(res, initial); acb_addmul(res, x, y, prec); } for (i = 1; i < len; i++) acb_addmul(res, x + i * xstep, y + i * ystep, prec); if (subtract) acb_neg(res, res); }
void _acb_poly_evaluate_rectangular(acb_t y, acb_srcptr poly, slong len, const acb_t x, slong prec) { slong i, j, m, r; acb_ptr xs; acb_t s, t, c; if (len < 3) { if (len == 0) { acb_zero(y); } else if (len == 1) { acb_set_round(y, poly + 0, prec); } else if (len == 2) { acb_mul(y, x, poly + 1, prec); acb_add(y, y, poly + 0, prec); } return; } m = n_sqrt(len) + 1; r = (len + m - 1) / m; xs = _acb_vec_init(m + 1); acb_init(s); acb_init(t); acb_init(c); _acb_vec_set_powers(xs, x, m + 1, prec); acb_set(y, poly + (r - 1) * m); for (j = 1; (r - 1) * m + j < len; j++) acb_addmul(y, xs + j, poly + (r - 1) * m + j, prec); for (i = r - 2; i >= 0; i--) { acb_set(s, poly + i * m); for (j = 1; j < m; j++) acb_addmul(s, xs + j, poly + i * m + j, prec); acb_mul(y, y, xs + m, prec); acb_add(y, y, s, prec); } _acb_vec_clear(xs, m + 1); acb_clear(s); acb_clear(t); acb_clear(c); }
/* returns x0, c.x0 + x1, c^2.x0 + c.x1 + x2, ... */ void acb_vec_polynomial_shift(acb_ptr x, const acb_t c, slong len, slong prec) { slong k; for (k = 1; k < len; k++) acb_addmul(x + k, x + k - 1, c, prec); }
void _acb_poly_revert_series_lagrange_fast(acb_ptr Qinv, acb_srcptr Q, slong Qlen, slong n, slong prec) { slong i, j, k, m; acb_ptr R, S, T, tmp; acb_t t; if (n <= 2) { if (n >= 1) acb_zero(Qinv); if (n == 2) acb_inv(Qinv + 1, Q + 1, prec); return; } m = n_sqrt(n); acb_init(t); R = _acb_vec_init((n - 1) * m); S = _acb_vec_init(n - 1); T = _acb_vec_init(n - 1); acb_zero(Qinv); acb_inv(Qinv + 1, Q + 1, prec); _acb_poly_inv_series(Ri(1), Q + 1, FLINT_MIN(Qlen, n) - 1, n - 1, prec); for (i = 2; i <= m; i++) _acb_poly_mullow(Ri(i), Ri((i + 1) / 2), n - 1, Ri(i / 2), n - 1, n - 1, prec); for (i = 2; i < m; i++) acb_div_ui(Qinv + i, Ri(i) + i - 1, i, prec); _acb_vec_set(S, Ri(m), n - 1); for (i = m; i < n; i += m) { acb_div_ui(Qinv + i, S + i - 1, i, prec); for (j = 1; j < m && i + j < n; j++) { acb_mul(t, S + 0, Ri(j) + i + j - 1, prec); for (k = 1; k <= i + j - 1; k++) acb_addmul(t, S + k, Ri(j) + i + j - 1 - k, prec); acb_div_ui(Qinv + i + j, t, i + j, prec); } if (i + 1 < n) { _acb_poly_mullow(T, S, n - 1, Ri(m), n - 1, n - 1, prec); tmp = S; S = T; T = tmp; } } acb_clear(t); _acb_vec_clear(R, (n - 1) * m); _acb_vec_clear(S, n - 1); _acb_vec_clear(T, n - 1); }
void acb_polygamma(acb_t res, const acb_t s, const acb_t z, long prec) { if (acb_is_zero(s)) { acb_digamma(res, z, prec); } else if (acb_is_int(s) && arb_is_positive(acb_realref(s))) { acb_t t, u; acb_init(t); acb_init(u); acb_add_ui(t, s, 1, prec); acb_gamma(u, t, prec); acb_hurwitz_zeta(t, t, z, prec); if (arf_is_int_2exp_si(arb_midref(acb_realref(s)), 1)) acb_neg(t, t); acb_mul(res, t, u, prec); acb_clear(t); acb_clear(u); } else { acb_t t, u; acb_struct v[2]; acb_init(t); acb_init(u); acb_init(v); acb_init(v + 1); /* u = psi(-s) + gamma */ acb_neg(t, s); acb_digamma(u, t, prec); arb_const_euler(acb_realref(v), prec); arb_add(acb_realref(u), acb_realref(u), acb_realref(v), prec); acb_add_ui(t, s, 1, prec); _acb_poly_zeta_cpx_series(v, t, z, 0, 2, prec); acb_addmul(v + 1, v, u, prec); acb_neg(t, s); acb_rgamma(u, t, prec); acb_mul(res, v + 1, u, prec); acb_clear(v); acb_clear(v + 1); acb_clear(t); acb_clear(u); } }
static void _acb_mat_det_cofactor_3x3(acb_t t, const acb_mat_t A, slong prec) { acb_t a; acb_init(a); acb_mul (a, acb_mat_entry(A, 1, 0), acb_mat_entry(A, 2, 1), prec); acb_submul(a, acb_mat_entry(A, 1, 1), acb_mat_entry(A, 2, 0), prec); acb_mul (t, a, acb_mat_entry(A, 0, 2), prec); acb_mul (a, acb_mat_entry(A, 1, 2), acb_mat_entry(A, 2, 0), prec); acb_submul(a, acb_mat_entry(A, 1, 0), acb_mat_entry(A, 2, 2), prec); acb_addmul(t, a, acb_mat_entry(A, 0, 1), prec); acb_mul (a, acb_mat_entry(A, 1, 1), acb_mat_entry(A, 2, 2), prec); acb_submul(a, acb_mat_entry(A, 1, 2), acb_mat_entry(A, 2, 1), prec); acb_addmul(t, a, acb_mat_entry(A, 0, 0), prec); acb_clear(a); }
void acb_mat_mul(acb_mat_t C, const acb_mat_t A, const acb_mat_t B, slong prec) { slong ar, ac, br, bc, i, j, k; ar = acb_mat_nrows(A); ac = acb_mat_ncols(A); br = acb_mat_nrows(B); bc = acb_mat_ncols(B); if (ac != br || ar != acb_mat_nrows(C) || bc != acb_mat_ncols(C)) { flint_printf("acb_mat_mul: incompatible dimensions\n"); abort(); } if (br == 0) { acb_mat_zero(C); return; } if (A == C || B == C) { acb_mat_t T; acb_mat_init(T, ar, bc); acb_mat_mul(T, A, B, prec); acb_mat_swap(T, C); acb_mat_clear(T); return; } for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { acb_mul(acb_mat_entry(C, i, j), acb_mat_entry(A, i, 0), acb_mat_entry(B, 0, j), prec); for (k = 1; k < br; k++) { acb_addmul(acb_mat_entry(C, i, j), acb_mat_entry(A, i, k), acb_mat_entry(B, k, j), prec); } } } }
void _acb_poly_mullow_classical(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec) { len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (n == 1) { acb_mul(res, poly1, poly2, prec); } else if (poly1 == poly2 && len1 == len2) { slong i; _acb_vec_scalar_mul(res, poly1, FLINT_MIN(len1, n), poly1, prec); _acb_vec_scalar_mul(res + len1, poly1 + 1, n - len1, poly1 + len1 - 1, prec); for (i = 1; i < len1 - 1; i++) _acb_vec_scalar_addmul(res + i + 1, poly1 + 1, FLINT_MIN(i - 1, n - (i + 1)), poly1 + i, prec); for (i = 1; i < FLINT_MIN(2 * len1 - 2, n); i++) acb_mul_2exp_si(res + i, res + i, 1); for (i = 1; i < FLINT_MIN(len1 - 1, (n + 1) / 2); i++) acb_addmul(res + 2 * i, poly1 + i, poly1 + i, prec); } else { slong i; _acb_vec_scalar_mul(res, poly1, FLINT_MIN(len1, n), poly2, prec); if (n > len1) _acb_vec_scalar_mul(res + len1, poly2 + 1, n - len1, poly1 + len1 - 1, prec); for (i = 0; i < FLINT_MIN(len1, n) - 1; i++) _acb_vec_scalar_addmul(res + i + 1, poly2 + 1, FLINT_MIN(len2, n - i) - 1, poly1 + i, prec); } }
void _acb_poly_product_roots(acb_ptr poly, acb_srcptr xs, slong n, slong prec) { if (n == 0) { acb_one(poly); } else if (n == 1) { acb_neg(poly, xs); acb_one(poly + 1); } else if (n == 2) { acb_mul(poly, xs + 0, xs + 1, prec); acb_add(poly + 1, xs + 0, xs + 1, prec); acb_neg(poly + 1, poly + 1); acb_one(poly + 2); } else if (n == 3) { acb_mul(poly + 1, xs, xs + 1, prec); acb_mul(poly, poly + 1, xs + 2, prec); acb_neg(poly, poly); acb_add(poly + 2, xs, xs + 1, prec); acb_addmul(poly + 1, poly + 2, xs + 2, prec); acb_add(poly + 2, poly + 2, xs + 2, prec); acb_neg(poly + 2, poly + 2); acb_one(poly + 3); } else { const slong m = (n + 1) / 2; acb_ptr tmp; tmp = _acb_vec_init(n + 2); _acb_poly_product_roots(tmp, xs, m, prec); _acb_poly_product_roots(tmp + m + 1, xs + m, n - m, prec); _acb_poly_mul_monic(poly, tmp, m + 1, tmp + m + 1, n - m + 1, prec); _acb_vec_clear(tmp, n + 2); } }
void _acb_poly_taylor_shift_divconquer(acb_ptr poly, const acb_t c, slong len, slong prec) { acb_struct d[2]; if (len <= 1 || acb_is_zero(c)) return; if (len == 2) { acb_addmul(poly, poly + 1, c, prec); return; } d[0] = *c; acb_init(d + 1); acb_one(d + 1); /* no need to free */ _acb_poly_compose_divconquer(poly, poly, len, d, 2, prec); }
void acb_dirichlet_l(acb_t res, const acb_t s, const acb_dirichlet_group_t G, ulong m, slong prec) { acb_t chi, t, u, a; ulong k; acb_init(chi); acb_init(t); acb_init(u); acb_init(a); acb_zero(t); for (k = 1; k <= G->q; k++) { acb_dirichlet_chi(chi, G, m, k, prec); if (!acb_is_zero(chi)) { acb_set_ui(a, k); acb_div_ui(a, a, G->q, prec); acb_hurwitz_zeta(u, s, a, prec); acb_addmul(t, chi, u, prec); } } acb_set_ui(u, G->q); acb_neg(a, s); acb_pow(u, u, a, prec); acb_mul(res, t, u, prec); acb_clear(chi); acb_clear(t); acb_clear(u); acb_clear(a); }
void _acb_poly_taylor_shift_horner(acb_ptr poly, const acb_t c, slong n, slong prec) { slong i, j; if (acb_is_one(c)) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) acb_add(poly + j, poly + j, poly + j + 1, prec); } else if (acb_equal_si(c, -1)) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) acb_sub(poly + j, poly + j, poly + j + 1, prec); } else if (!acb_is_zero(c)) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) acb_addmul(poly + j, poly + j + 1, c, prec); } }
int main() { slong iter; flint_rand_t state; flint_printf("bessel_i...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 2000; iter++) { acb_t nu, z, jv, iv, t; slong prec; acb_init(nu); acb_init(z); acb_init(jv); acb_init(iv); acb_init(t); prec = 2 + n_randint(state, 500); acb_randtest_param(nu, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(iv, nu, z, prec); break; case 1: acb_hypgeom_bessel_i_0f1(iv, nu, z, prec); break; default: acb_hypgeom_bessel_i(iv, nu, z, prec); } acb_mul_onei(t, z); acb_hypgeom_bessel_j(jv, nu, t, prec); acb_pow(t, z, nu, prec); acb_mul(jv, jv, t, prec); acb_mul_onei(t, z); acb_pow(t, t, nu, prec); acb_div(jv, jv, t, prec); if (!acb_overlaps(iv, jv)) { flint_printf("FAIL: consistency with bessel_j\n\n"); flint_printf("nu = "); acb_printd(nu, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("iv = "); acb_printd(iv, 30); flint_printf("\n\n"); flint_printf("jv = "); acb_printd(jv, 30); flint_printf("\n\n"); abort(); } acb_clear(nu); acb_clear(z); acb_clear(jv); acb_clear(iv); acb_clear(t); } for (iter = 0; iter < 2000; iter++) { acb_t nu0, nu1, nu2, z, w0, w1, w2, t, u; slong prec0, prec1, prec2; acb_init(nu0); acb_init(nu1); acb_init(nu2); acb_init(z); acb_init(w0); acb_init(w1); acb_init(w2); acb_init(t); acb_init(u); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); acb_randtest_param(nu0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_sub_ui(nu1, nu0, 1, prec0); acb_sub_ui(nu2, nu0, 2, prec0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w0, nu0, z, prec0); break; case 1: acb_hypgeom_bessel_i_0f1(w0, nu0, z, prec0); break; default: acb_hypgeom_bessel_i(w0, nu0, z, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w1, nu0, z, prec1); break; case 1: acb_hypgeom_bessel_i_0f1(w1, nu0, z, prec1); break; default: acb_hypgeom_bessel_i(w1, nu0, z, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); abort(); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w1, nu1, z, prec1); break; case 1: acb_hypgeom_bessel_i_0f1(w1, nu1, z, prec1); break; default: acb_hypgeom_bessel_i(w1, nu1, z, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w2, nu2, z, prec2); break; case 1: acb_hypgeom_bessel_i_0f1(w2, nu2, z, prec2); break; default: acb_hypgeom_bessel_i(w2, nu2, z, prec2); } acb_mul(t, w1, nu1, prec0); acb_mul_2exp_si(t, t, 1); acb_submul(t, w2, z, prec0); acb_addmul(t, w0, z, prec0); if (!acb_contains_zero(t)) { flint_printf("FAIL: contiguous relation\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); abort(); } acb_neg(t, nu0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w2, t, z, prec2); break; case 1: acb_hypgeom_bessel_i_0f1(w2, t, z, prec2); break; default: acb_hypgeom_bessel_i(w2, t, z, prec2); } acb_mul(w1, w1, w2, prec2); acb_neg(t, nu1); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_i_asymp(w2, t, z, prec2); break; case 1: acb_hypgeom_bessel_i_0f1(w2, t, z, prec2); break; default: acb_hypgeom_bessel_i(w2, t, z, prec2); } acb_mul(w0, w0, w2, prec2); acb_sub(w0, w1, w0, prec2); acb_sin_pi(t, nu0, prec2); acb_const_pi(u, prec2); acb_mul(u, u, z, prec2); acb_div(t, t, u, prec2); acb_mul_2exp_si(t, t, 1); if (!acb_overlaps(w0, t)) { flint_printf("FAIL: wronskian\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); abort(); } acb_clear(nu0); acb_clear(nu1); acb_clear(nu2); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(w2); acb_clear(t); acb_clear(u); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
int main() { long iter; flint_rand_t state; printf("gamma_upper...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 2000; iter++) { acb_t a0, a1, b, z, w0, w1, t, u; long prec0, prec1; int modified; acb_init(a0); acb_init(a1); acb_init(b); acb_init(z); acb_init(w0); acb_init(w1); acb_init(t); acb_init(u); modified = n_randint(state, 2); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); acb_randtest_maybe_half_int(a0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_add_ui(a1, a0, 1, prec0); switch (n_randint(state, 4)) { case 0: acb_hypgeom_gamma_upper_asymp(w0, a0, z, modified, prec0); break; case 1: acb_hypgeom_gamma_upper_1f1a(w0, a0, z, modified, prec0); break; case 2: acb_hypgeom_gamma_upper_1f1b(w0, a0, z, modified, prec0); break; default: acb_hypgeom_gamma_upper(w0, a0, z, modified, prec0); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_gamma_upper_asymp(w1, a0, z, modified, prec1); break; case 1: acb_hypgeom_gamma_upper_1f1a(w1, a0, z, modified, prec1); break; case 2: acb_hypgeom_gamma_upper_1f1b(w1, a0, z, modified, prec1); break; default: acb_hypgeom_gamma_upper(w1, a0, z, modified, prec1); } if (!acb_overlaps(w0, w1)) { printf("FAIL: consistency\n\n"); printf("nu = "); acb_printd(a0, 30); printf("\n\n"); printf("z = "); acb_printd(z, 30); printf("\n\n"); printf("w0 = "); acb_printd(w0, 30); printf("\n\n"); printf("w1 = "); acb_printd(w1, 30); printf("\n\n"); abort(); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_gamma_upper_asymp(w1, a1, z, modified, prec1); break; case 1: acb_hypgeom_gamma_upper_1f1a(w1, a1, z, modified, prec1); break; case 2: acb_hypgeom_gamma_upper_1f1b(w1, a1, z, modified, prec1); break; default: acb_hypgeom_gamma_upper(w1, a1, z, modified, prec1); } /* a Gamma(a,z) + exp(-z) z^a = Gamma(a+1,z) */ if (modified) acb_one(t); else acb_pow(t, z, a0, prec0); acb_neg(u, z); acb_exp(u, u, prec0); acb_mul(t, t, u, prec0); if (modified) { acb_mul(b, w1, z, prec0); acb_addmul(t, a0, w0, prec0); acb_sub(t, t, b, prec0); } else { acb_addmul(t, a0, w0, prec0); acb_sub(t, t, w1, prec0); } if (!acb_contains_zero(t)) { printf("FAIL: contiguous relation\n\n"); printf("nu = "); acb_printd(a0, 30); printf("\n\n"); printf("z = "); acb_printd(z, 30); printf("\n\n"); printf("w0 = "); acb_printd(w0, 30); printf("\n\n"); printf("w1 = "); acb_printd(w1, 30); printf("\n\n"); printf("t = "); acb_printd(t, 30); printf("\n\n"); abort(); } acb_clear(a0); acb_clear(a1); acb_clear(b); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(t); acb_clear(u); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
/* todo: use log(1-z) when this is better? would also need to adjust strategy in the main function */ void acb_hypgeom_dilog_bernoulli(acb_t res, const acb_t z, slong prec) { acb_t s, w, w2; slong n, k; fmpz_t c, d; mag_t m, err; double lm; int real; acb_init(s); acb_init(w); acb_init(w2); fmpz_init(c); fmpz_init(d); mag_init(m); mag_init(err); real = 0; if (acb_is_real(z)) { arb_sub_ui(acb_realref(w), acb_realref(z), 1, 30); real = arb_is_nonpositive(acb_realref(w)); } acb_log(w, z, prec); acb_get_mag(m, w); /* for k >= 4, the terms are bounded by (|w| / (2 pi))^k */ mag_set_ui_2exp_si(err, 2670177, -24); /* upper bound for 1/(2pi) */ mag_mul(err, err, m); lm = mag_get_d_log2_approx(err); if (lm < -0.25) { n = prec / (-lm) + 1; n = FLINT_MAX(n, 4); mag_geom_series(err, err, n); BERNOULLI_ENSURE_CACHED(n) acb_mul(w2, w, w, prec); for (k = n - (n % 2 == 0); k >= 3; k -= 2) { fmpz_mul_ui(c, fmpq_denref(bernoulli_cache + k - 1), k - 1); fmpz_mul_ui(d, c, (k + 1) * (k + 2)); acb_mul(s, s, w2, prec); acb_mul_fmpz(s, s, c, prec); fmpz_mul_ui(c, fmpq_numref(bernoulli_cache + k - 1), (k + 1) * (k + 2)); acb_sub_fmpz(s, s, c, prec); acb_div_fmpz(s, s, d, prec); } acb_mul(s, s, w, prec); acb_mul_2exp_si(s, s, 1); acb_sub_ui(s, s, 3, prec); acb_mul(s, s, w2, prec); acb_mul_2exp_si(s, s, -1); acb_const_pi(w2, prec); acb_addmul(s, w2, w2, prec); acb_div_ui(s, s, 6, prec); acb_neg(w2, w); acb_log(w2, w2, prec); acb_submul(s, w2, w, prec); acb_add(res, s, w, prec); acb_add_error_mag(res, err); if (real) arb_zero(acb_imagref(res)); } else { acb_indeterminate(res); } acb_clear(s); acb_clear(w); acb_clear(w2); fmpz_clear(c); fmpz_clear(d); mag_clear(m); mag_clear(err); }
int main() { slong iter; flint_rand_t state; flint_printf("bessel_k...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 2000 * arb_test_multiplier(); iter++) { acb_t nu0, nu1, nu2, z, w0, w1, w2, t, u; slong prec0, prec1, prec2; acb_init(nu0); acb_init(nu1); acb_init(nu2); acb_init(z); acb_init(w0); acb_init(w1); acb_init(w2); acb_init(t); acb_init(u); prec0 = 2 + n_randint(state, 700); prec1 = 2 + n_randint(state, 700); prec2 = 2 + n_randint(state, 700); acb_randtest_param(nu0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); if (n_randint(state, 4) == 0) arb_zero(acb_imagref(z)); acb_sub_ui(nu1, nu0, 1, prec0); acb_sub_ui(nu2, nu0, 2, prec0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_k_asymp(w0, nu0, z, prec0); break; case 1: acb_hypgeom_bessel_k_0f1(w0, nu0, z, prec0); break; default: acb_hypgeom_bessel_k(w0, nu0, z, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_k_asymp(w1, nu0, z, prec1); break; case 1: acb_hypgeom_bessel_k_0f1(w1, nu0, z, prec1); break; default: acb_hypgeom_bessel_k(w1, nu0, z, prec1); } if (!acb_overlaps(w0, w1)) { flint_printf("FAIL: consistency\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); abort(); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_k_asymp(w1, nu1, z, prec1); break; case 1: acb_hypgeom_bessel_k_0f1(w1, nu1, z, prec1); break; default: acb_hypgeom_bessel_k(w1, nu1, z, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_k_asymp(w2, nu2, z, prec2); break; case 1: acb_hypgeom_bessel_k_0f1(w2, nu2, z, prec2); break; default: acb_hypgeom_bessel_k(w2, nu2, z, prec2); } acb_mul(t, w1, nu1, prec0); acb_mul_2exp_si(t, t, 1); acb_addmul(t, w2, z, prec0); acb_submul(t, w0, z, prec0); if (!acb_contains_zero(t)) { flint_printf("FAIL: contiguous relation\n\n"); flint_printf("nu = "); acb_printd(nu0, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); abort(); } acb_clear(nu0); acb_clear(nu1); acb_clear(nu2); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(w2); acb_clear(t); acb_clear(u); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void acb_hypgeom_bessel_i_asymp(acb_t res, const acb_t nu, const acb_t z, long prec) { acb_t A1, A2, C, U1, U2, s, t, u; int is_real, is_imag; acb_init(A1); acb_init(A2); acb_init(C); acb_init(U1); acb_init(U2); acb_init(s); acb_init(t); acb_init(u); is_imag = 0; is_real = acb_is_real(nu) && acb_is_real(z) && (acb_is_int(nu) || arb_is_positive(acb_realref(z))); if (!is_real && arb_is_zero(acb_realref(z)) && acb_is_int(nu)) { acb_mul_2exp_si(t, nu, -1); if (acb_is_int(t)) is_real = 1; else is_imag = 1; } acb_hypgeom_bessel_i_asymp_prefactors(A1, A2, C, nu, z, prec); /* todo: if Ap ~ 2^a and Am = 2^b and U1 ~ U2 ~ 1, change precision? */ if (!acb_is_finite(A1) || !acb_is_finite(A2) || !acb_is_finite(C)) { acb_indeterminate(res); } else { /* s = 1/2 + nu */ acb_one(s); acb_mul_2exp_si(s, s, -1); acb_add(s, s, nu, prec); /* t = 1 + 2 nu */ acb_mul_2exp_si(t, nu, 1); acb_add_ui(t, t, 1, prec); acb_mul_2exp_si(u, z, 1); acb_hypgeom_u_asymp(U1, s, t, u, -1, prec); acb_neg(u, u); acb_hypgeom_u_asymp(U2, s, t, u, -1, prec); acb_mul(res, A1, U1, prec); acb_addmul(res, A2, U2, prec); acb_mul(res, res, C, prec); if (is_real) arb_zero(acb_imagref(res)); if (is_imag) arb_zero(acb_realref(res)); } acb_clear(A1); acb_clear(A2); acb_clear(C); acb_clear(U1); acb_clear(U2); acb_clear(s); acb_clear(t); acb_clear(u); }
void acb_hypgeom_pfq_sum_fme(acb_t s, acb_t t, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong n, slong prec) { acb_poly_t A, B, C; acb_ptr ks, As, Bs, Cs; acb_t u, v; acb_ptr * tree; slong i, k, m, w; /* we compute to n-1 instead of n to avoid dividing by 0 in the denominator when computing a hypergeometric polynomial that terminates right before a pole */ if (n > 4) { m = n_sqrt(n - 1) / 4; /* tuning parameter */ w = (n - 1) / FLINT_MAX(m, 1); } else { m = w = 0; } if (m < 1 || w < 1 || p > 3 || q > 3) { acb_hypgeom_pfq_sum_forward(s, t, a, p, b, q, z, n, prec); return; } acb_poly_init(A); acb_poly_init(B); acb_poly_init(C); acb_init(u); acb_init(v); ks = _acb_vec_init(w); As = _acb_vec_init(w); Bs = _acb_vec_init(w); Cs = _acb_vec_init(w); bsplit(A, B, C, a, p, b, q, z, 0, m, prec); for (i = 0; i < w; i++) acb_set_ui(ks + i, i * m); tree = _acb_poly_tree_alloc(w); _acb_poly_tree_build(tree, ks, w, prec); _acb_poly_evaluate_vec_fast_precomp(As, A->coeffs, A->length, tree, w, prec); _acb_poly_evaluate_vec_fast_precomp(Bs, B->coeffs, B->length, tree, w, prec); _acb_poly_evaluate_vec_fast_precomp(Cs, C->coeffs, C->length, tree, w, prec); _acb_poly_tree_free(tree, w); /* todo: use binary splitting here for improved numerical stability */ for (i = 1; i < w; i++) { acb_mul(Cs, Cs, Bs + i, prec); acb_addmul(Cs, As, Cs + i, prec); acb_mul(As, As, As + i, prec); acb_mul(Bs, Bs, Bs + i, prec); } acb_div(s, Cs, Bs, prec); acb_div(t, As, Bs, prec); for (k = w * m; k < n && !acb_is_zero(t); k++) { acb_add(s, s, t, prec); if (p > 0) { acb_add_ui(u, a, k, prec); for (i = 1; i < p; i++) { acb_add_ui(v, a + i, k, prec); acb_mul(u, u, v, prec); } acb_mul(t, t, u, prec); } if (q > 0) { acb_add_ui(u, b, k, prec); for (i = 1; i < q; i++) { acb_add_ui(v, b + i, k, prec); acb_mul(u, u, v, prec); } acb_div(t, t, u, prec); } acb_mul(t, t, z, prec); } acb_clear(u); acb_clear(v); _acb_vec_clear(ks, w); _acb_vec_clear(As, w); _acb_vec_clear(Bs, w); _acb_vec_clear(Cs, w); acb_poly_clear(A); acb_poly_clear(B); acb_poly_clear(C); }
static void evaluate(acb_poly_t A, acb_srcptr a, slong p, const acb_t z, slong n, slong prec) { acb_poly_fit_length(A, p + 1); if (p == 1) { acb_add_ui(A->coeffs, a, n, prec); if (z != NULL) acb_mul(A->coeffs, A->coeffs, z, prec); } else if (p == 2) { acb_add(A->coeffs, a + 0, a + 1, prec); acb_add_ui(A->coeffs + 1, A->coeffs, 2 * n, prec); acb_add_ui(A->coeffs, A->coeffs, n, prec); acb_mul_ui(A->coeffs, A->coeffs, n, prec); acb_addmul(A->coeffs, a + 0, a + 1, prec); if (z != NULL) { acb_mul(A->coeffs, A->coeffs, z, prec); acb_mul(A->coeffs + 1, A->coeffs + 1, z, prec); } } else if (p == 3) { acb_t t, u; acb_init(t); acb_init(u); acb_add(t, a + 0, a + 1, prec); acb_add(t, t, a + 2, prec); acb_mul(u, a + 0, a + 1, prec); acb_mul(A->coeffs, u, a + 2, prec); acb_addmul(u, a + 0, a + 2, prec); acb_addmul(u, a + 1, a + 2, prec); /* (a0 + n)(a1 + n)(a2 + n) = a0 a1 a2 + (a0 a1 + a0 a2 + a1 a2) n + (a0 + a1 + a2) n^2 + n^3 (a0 a1 + a0 a2 + a1 a2) + 2 (a0 + a1 + a2) n + 3 n^2 (a0 + a1 + a2) + 3n 1 */ acb_addmul_ui(A->coeffs, u, n, prec); acb_addmul_ui(A->coeffs, t, n * n, prec); acb_add_ui(A->coeffs, A->coeffs, n * n * n, prec); acb_set(A->coeffs + 1, u); acb_addmul_ui(A->coeffs + 1, t, 2 * n, prec); acb_add_ui(A->coeffs + 1, A->coeffs + 1, 3 * n * n, prec); acb_add_ui(A->coeffs + 2, t, 3 * n, prec); if (z != NULL) { acb_mul(A->coeffs + 0, A->coeffs + 0, z, prec); acb_mul(A->coeffs + 1, A->coeffs + 1, z, prec); acb_mul(A->coeffs + 2, A->coeffs + 2, z, prec); } acb_clear(t); acb_clear(u); } else if (p != 0) { flint_abort(); } if (z != NULL) acb_set(A->coeffs + p, z); else acb_one(A->coeffs + p); _acb_poly_set_length(A, p + 1); _acb_poly_normalise(A); }
static void bsplit(acb_t A1, acb_t B1, acb_t C1, acb_srcptr a, slong p, acb_srcptr b, slong q, const acb_t z, slong aa, slong bb, slong prec, int invz) { if (bb - aa == 1) { slong i; if (p == 0) { if (invz) acb_one(A1); else acb_set(A1, z); } else { acb_add_ui(A1, a, aa, prec); for (i = 1; i < p; i++) { acb_add_ui(B1, a + i, aa, prec); acb_mul(A1, A1, B1, prec); } if (!invz) acb_mul(A1, A1, z, prec); } if (q == 0) { if (invz) acb_set(C1, z); else acb_one(C1); } else { acb_add_ui(C1, b, aa, prec); for (i = 1; i < q; i++) { acb_add_ui(B1, b + i, aa, prec); acb_mul(C1, C1, B1, prec); } if (invz) acb_mul(C1, C1, z, prec); } /* acb_set(B1, C1); but we skip this */ } else { slong m; acb_t A2, B2, C2; acb_init(A2); acb_init(B2); acb_init(C2); m = aa + (bb - aa) / 2; bsplit(A1, B1, C1, a, p, b, q, z, aa, m, prec, invz); bsplit(A2, B2, C2, a, p, b, q, z, m, bb, prec, invz); if (bb - m == 1) /* B2 = C2 */ { if (m - aa == 1) acb_add(B2, A1, C1, prec); else acb_add(B2, A1, B1, prec); acb_mul(B1, B2, C2, prec); } else { if (m - aa == 1) acb_mul(B1, C1, C2, prec); else acb_mul(B1, B1, C2, prec); acb_addmul(B1, A1, B2, prec); } acb_mul(A1, A1, A2, prec); acb_mul(C1, C1, C2, prec); acb_clear(A2); acb_clear(B2); acb_clear(C2); } }
void acb_modular_eisenstein(acb_ptr r, const acb_t tau, slong len, slong prec) { psl2z_t g; arf_t one_minus_eps; acb_t tau_prime, t1, t2, t3, t4, q; slong m, n; if (len < 1) return; psl2z_init(g); arf_init(one_minus_eps); acb_init(tau_prime); acb_init(t1); acb_init(t2); acb_init(t3); acb_init(t4); acb_init(q); arf_set_ui_2exp_si(one_minus_eps, 63, -6); acb_modular_fundamental_domain_approx(tau_prime, g, tau, one_minus_eps, prec); acb_exp_pi_i(q, tau_prime, prec); acb_modular_theta_const_sum(t2, t3, t4, q, prec); /* fourth powers of the theta functions (a, b, c) */ acb_mul(t2, t2, t2, prec); acb_mul(t2, t2, t2, prec); acb_mul(t2, t2, q, prec); acb_mul(t3, t3, t3, prec); acb_mul(t3, t3, t3, prec); acb_mul(t4, t4, t4, prec); acb_mul(t4, t4, t4, prec); /* c2 = pi^4 * (a^8 + b^8 + c^8) / 30 */ /* c3 = pi^6 * (b^12 + c^12 - 3a^8 * (b^4+c^4)) / 180 */ /* r = a^8 */ acb_mul(r, t2, t2, prec); if (len > 1) { /* r[1] = -3 a^8 * (b^4 + c^4) */ acb_add(r + 1, t3, t4, prec); acb_mul(r + 1, r + 1, r, prec); acb_mul_si(r + 1, r + 1, -3, prec); } /* b^8 */ acb_mul(t1, t3, t3, prec); acb_add(r, r, t1, prec); /* b^12 */ if (len > 1) acb_addmul(r + 1, t1, t3, prec); /* c^8 */ acb_mul(t1, t4, t4, prec); acb_add(r, r, t1, prec); /* c^12 */ if (len > 1) acb_addmul(r + 1, t1, t4, prec); acb_const_pi(t1, prec); acb_mul(t1, t1, t1, prec); acb_mul(t2, t1, t1, prec); acb_mul(r, r, t2, prec); acb_div_ui(r, r, 30, prec); if (len > 1) { acb_mul(t2, t2, t1, prec); acb_mul(r + 1, r + 1, t2, prec); acb_div_ui(r + 1, r + 1, 189, prec); } /* apply modular transformation */ if (!fmpz_is_zero(&g->c)) { acb_mul_fmpz(t1, tau, &g->c, prec); acb_add_fmpz(t1, t1, &g->d, prec); acb_inv(t1, t1, prec); acb_mul(t1, t1, t1, prec); acb_mul(t2, t1, t1, prec); acb_mul(r, r, t2, prec); if (len > 1) { acb_mul(t2, t1, t2, prec); acb_mul(r + 1, r + 1, t2, prec); } } /* compute more coefficients using recurrence */ for (n = 4; n < len + 2; n++) { acb_zero(r + n - 2); m = 2; for (m = 2; m * 2 < n; m++) acb_addmul(r + n - 2, r + m - 2, r + n - m - 2, prec); acb_mul_2exp_si(r + n - 2, r + n - 2, 1); if (n % 2 == 0) acb_addmul(r + n - 2, r + n / 2 - 2, r + n / 2 - 2, prec); acb_mul_ui(r + n - 2, r + n - 2, 3, prec); acb_div_ui(r + n - 2, r + n - 2, (2 * n + 1) * (n - 3), prec); } /* convert c's to G's */ for (n = 0; n < len; n++) acb_div_ui(r + n, r + n, 2 * n + 3, prec); psl2z_clear(g); arf_clear(one_minus_eps); acb_clear(tau_prime); acb_clear(t1); acb_clear(t2); acb_clear(t3); acb_clear(t4); acb_clear(q); }
void acb_rising2_ui_rs(acb_t u, acb_t v, const acb_t x, ulong n, ulong m, long prec) { if (n == 0) { acb_zero(v); acb_one(u); } else if (n == 1) { acb_set(u, x); acb_one(v); } else { long wp; ulong i, j, a, b; acb_ptr xs; acb_t S, T, U, V; fmpz *A, *B; wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); if (m == 0) { ulong m1, m2; m1 = 0.6 * pow(wp, 0.4); m2 = n_sqrt(n); m = FLINT_MIN(m1, m2); } m = FLINT_MAX(m, 1); xs = _acb_vec_init(m + 1); A = _fmpz_vec_init(2 * m + 1); B = A + (m + 1); acb_init(S); acb_init(T); acb_init(U); acb_init(V); _acb_vec_set_powers(xs, x, m + 1, wp); for (i = 0; i < n; i += m) { a = i; b = FLINT_MIN(n, a + m); if (a == 0 || b != a + m) { _gamma_rf_bsplit(A, a, b); } else { fmpz tt = m; _fmpz_poly_taylor_shift(A, &tt, m + 1); } _fmpz_poly_derivative(B, A, b - a + 1); acb_set_fmpz(S, A); for (j = 1; j <= b - a; j++) acb_addmul_fmpz(S, xs + j, A + j, wp); acb_set_fmpz(T, B); for (j = 1; j < b - a; j++) acb_addmul_fmpz(T, xs + j, B + j, wp); if (i == 0) { acb_set(U, S); acb_set(V, T); } else { acb_mul(V, V, S, wp); acb_addmul(V, U, T, wp); acb_mul(U, U, S, wp); } } acb_set(u, U); acb_set(v, V); _acb_vec_clear(xs, m + 1); _fmpz_vec_clear(A, 2 * m + 1); acb_clear(S); acb_clear(T); acb_clear(U); acb_clear(V); } }
int main() { long iter; flint_rand_t state; printf("u...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 2000; iter++) { acb_t a0, a1, a2, b, z, w0, w1, w2, t, u; long prec0, prec1, prec2; acb_init(a0); acb_init(a1); acb_init(a2); acb_init(b); acb_init(z); acb_init(w0); acb_init(w1); acb_init(w2); acb_init(t); acb_init(u); prec0 = 2 + n_randint(state, 700); prec1 = 2 + n_randint(state, 700); prec2 = 2 + n_randint(state, 700); acb_randtest_maybe_half_int(a0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest_maybe_half_int(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(w2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_add_ui(a1, a0, 1, prec0); acb_add_ui(a2, a0, 2, prec0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_u_asymp_proper(w0, a0, b, z, prec0); break; case 1: acb_hypgeom_u_1f1(w0, a0, b, z, prec0); break; default: acb_hypgeom_u(w0, a0, b, z, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_u_asymp_proper(w1, a0, b, z, prec1); break; case 1: acb_hypgeom_u_1f1(w1, a0, b, z, prec1); break; default: acb_hypgeom_u(w1, a0, b, z, prec1); } if (!acb_overlaps(w0, w1)) { printf("FAIL: consistency\n\n"); printf("a = "); acb_printd(a0, 30); printf("\n\n"); printf("b = "); acb_printd(b, 30); printf("\n\n"); printf("z = "); acb_printd(z, 30); printf("\n\n"); printf("w0 = "); acb_printd(w0, 30); printf("\n\n"); printf("w1 = "); acb_printd(w1, 30); printf("\n\n"); abort(); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_u_asymp_proper(w1, a1, b, z, prec1); break; case 1: acb_hypgeom_u_1f1(w1, a1, b, z, prec1); break; default: acb_hypgeom_u(w1, a1, b, z, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_u_asymp_proper(w2, a2, b, z, prec2); break; case 1: acb_hypgeom_u_1f1(w2, a2, b, z, prec2); break; default: acb_hypgeom_u(w2, a2, b, z, prec2); } acb_set(t, w0); acb_mul_2exp_si(u, a0, 1); acb_sub(u, u, b, prec0); acb_add(u, u, z, prec0); acb_add_ui(u, u, 2, prec0); acb_submul(t, w1, u, prec0); acb_sub(u, a2, b, prec0); acb_mul(u, u, a1, prec0); acb_addmul(t, w2, u, prec0); if (!acb_contains_zero(t)) { printf("FAIL: contiguous relation\n\n"); printf("a = "); acb_printd(a0, 30); printf("\n\n"); printf("b = "); acb_printd(b, 30); printf("\n\n"); printf("z = "); acb_printd(z, 30); printf("\n\n"); printf("w0 = "); acb_printd(w0, 30); printf("\n\n"); printf("w1 = "); acb_printd(w1, 30); printf("\n\n"); printf("w2 = "); acb_printd(w2, 30); printf("\n\n"); printf("t = "); acb_printd(t, 30); printf("\n\n"); abort(); } acb_clear(a0); acb_clear(a1); acb_clear(a2); acb_clear(b); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(w2); acb_clear(t); acb_clear(u); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
int main() { slong iter; flint_rand_t state; flint_printf("u_asymp...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++) { acb_t a, b, a2, b2, z, U1, U2, t, u, M1, M2, am; acb_struct bm[2]; ulong n1, n2; slong prec0, prec1, prec2; acb_init(a); acb_init(b); acb_init(a2); acb_init(b2); acb_init(z); acb_init(U1); acb_init(U2); acb_init(t); acb_init(u); acb_init(M1); acb_init(M2); acb_init(am); acb_init(bm); acb_init(bm + 1); if (n_randint(state, 4) == 0) { n1 = n_randint(state, 200); n2 = n_randint(state, 200); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); } else { n1 = n_randint(state, 40); n2 = n_randint(state, 40); prec0 = 2 + n_randint(state, 300); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); } acb_randtest_param(a, state, prec0, 1 + n_randint(state, 20)); if (n_randint(state, 4) == 0) acb_add_ui(b, a, n_randint(state, 10), prec0); else acb_randtest_param(b, state, prec0, 1 + n_randint(state, 20)); acb_randtest(z, state, prec0, 1 + n_randint(state, 20)); /* Test Kummer's transformation */ acb_sub(a2, a, b, prec0); acb_add_ui(a2, a2, 1, prec0); acb_sub_ui(b2, b, 2, prec0); acb_neg(b2, b2); acb_hypgeom_u_asymp(U1, a, b, z, n1, prec1); acb_hypgeom_u_asymp(U2, a2, b2, z, n2, prec2); if (!acb_overlaps(U1, U2)) { flint_printf("FAIL (Kummer transformation)\n"); flint_printf("iter = %wd\n", iter); flint_printf("a = "); acb_printd(a, 50); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 50); flint_printf("\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n"); flint_printf("n1 = %wd, n2 = %wd, prec1 = %wd, prec2 = %wd\n", n1, n2, prec1, prec2); flint_printf("U1 = "); acb_printd(U1, 100); flint_printf("\n"); flint_printf("U2 = "); acb_printd(U2, 100); flint_printf("\n"); abort(); } /* Check contiguous relation (b-a-1)U(a,b-1,z) + z U(a,b+1,z) + (1-b-z) U(a,b,z) = 0 */ acb_one(t); acb_sub(t, t, b, prec0); acb_sub(t, t, z, prec0); acb_mul(u, U1, t, prec1); acb_add_ui(b2, b, 1, prec0); acb_hypgeom_u_asymp(U2, a, b2, z, n2, prec2); acb_addmul(u, U2, z, prec1); acb_sub_ui(b2, b, 1, prec0); acb_hypgeom_u_asymp(U2, a, b2, z, n2, prec2); acb_sub(t, b, a, prec0); acb_sub_ui(t, t, 1, prec0); acb_mul(t, t, U2, prec0); acb_add(t, t, u, prec0); if (!acb_contains_zero(t)) { flint_printf("FAIL (contiguous relation)\n"); flint_printf("iter = %wd\n", iter); flint_printf("a = "); acb_printd(a, 50); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 50); flint_printf("\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n"); flint_printf("n1 = %wd, n2 = %wd, prec1 = %wd, prec2 = %wd\n", n1, n2, prec1, prec2); flint_printf("U1 = "); acb_printd(U1, 100); flint_printf("\n"); flint_printf("t = "); acb_printd(t, 100); flint_printf("\n"); abort(); } /* Test U(a,b,z) = gamma(1-b)/gamma(a-b+1) M(a,b,z) + gamma(b-1)/gamma(a) z^(1-b) M(a-b+1,2-b,z) */ acb_set(am, a); acb_set(bm, b); acb_one(bm + 1); acb_hypgeom_pfq_direct(M1, am, 1, bm, 2, z, n2, prec2); acb_sub(am, a, b, prec2); acb_add_ui(am, am, 1, prec2); acb_sub_ui(bm, b, 2, prec2); acb_neg(bm, bm); acb_one(bm + 1); acb_hypgeom_pfq_direct(M2, am, 1, bm, 2, z, n2, prec2); acb_sub(am, a, b, prec2); acb_add_ui(am, am, 1, prec2); acb_rgamma(am, am, prec2); acb_mul(M1, M1, am, prec2); acb_sub_ui(am, b, 1, prec2); acb_neg(am, am); acb_gamma(am, am, prec2); acb_mul(M1, M1, am, prec2); acb_rgamma(am, a, prec2); acb_mul(M2, M2, am, prec2); acb_sub_ui(am, b, 1, prec2); acb_gamma(am, am, prec2); acb_mul(M2, M2, am, prec2); acb_sub_ui(am, b, 1, prec2); acb_neg(am, am); acb_pow(am, z, am, prec2); acb_mul(M2, M2, am, prec2); acb_add(U2, M1, M2, prec2); acb_pow(am, z, a, prec2); acb_mul(U2, U2, am, prec2); if (!acb_overlaps(U1, U2)) { flint_printf("FAIL (U in terms of M)\n"); flint_printf("iter = %wd\n", iter); flint_printf("a = "); acb_printd(a, 50); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 50); flint_printf("\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n"); flint_printf("n1 = %wd, n2 = %wd, prec1 = %wd, prec2 = %wd\n", n1, n2, prec1, prec2); flint_printf("U1 = "); acb_printd(U1, 100); flint_printf("\n"); flint_printf("U2 = "); acb_printd(U2, 100); flint_printf("\n"); abort(); } /* Test special value: b = a+1 */ acb_add_ui(b, a, 1, prec0); acb_hypgeom_u_asymp(U1, a, b, z, n1, prec1); acb_one(U2); if (!acb_overlaps(U1, U2)) { flint_printf("FAIL (special value)\n"); flint_printf("iter = %wd\n", iter); flint_printf("a = "); acb_printd(a, 50); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 50); flint_printf("\n"); flint_printf("z = "); acb_printd(z, 50); flint_printf("\n"); flint_printf("n1 = %wd, n2 = %wd, prec1 = %wd, prec2 = %wd\n", n1, n2, prec1, prec2); flint_printf("U1 = "); acb_printd(U1, 100); flint_printf("\n"); flint_printf("U2 = "); acb_printd(U2, 100); flint_printf("\n"); abort(); } acb_clear(a); acb_clear(b); acb_clear(a2); acb_clear(b2); acb_clear(z); acb_clear(U1); acb_clear(U2); acb_clear(t); acb_clear(u); acb_clear(M1); acb_clear(M2); acb_clear(am); acb_clear(bm); acb_clear(bm + 1); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void acb_modular_theta_const_sum_basecase(acb_t theta2, acb_t theta3, acb_t theta4, const acb_t q, slong N, slong prec) { slong * tab; slong k, term_prec; double log2q_approx, log2term_approx; mag_t qmag; acb_ptr qpow; acb_t s1, s2, s3, t1, t2; if (N < 2) { acb_set_ui(theta2, 2 * (N > 0)); acb_set_ui(theta3, N > 0); acb_set(theta4, theta3); return; } if (N < 25) { acb_t q1, q2, q4, q8, q16; acb_init(q1); acb_init(q2); acb_init(q4); acb_init(q8); acb_init(q16); acb_set_round(q1, q, prec); if (N > 2) acb_mul(q2, q1, q1, prec); if (N > 4) acb_mul(q4, q2, q2, prec); if (N > 9) acb_mul(q8, q4, q4, prec); if (N > 16) acb_mul(q16, q8, q8, prec); /* theta2 = 2 + 2q^2 + 2q^4 [2q^2 + 2q^8 + 2q^16] */ if (N > 6) { if (N > 12) { acb_add(theta2, q2, q8, prec); if (N > 20) acb_add(theta2, theta2, q16, prec); acb_mul(theta2, theta2, q4, prec); } else { acb_mul(theta2, q2, q4, prec); } acb_add(theta2, theta2, q2, prec); acb_add_ui(theta2, theta2, 1, prec); } else if (N > 2) acb_add_ui(theta2, q2, 1, prec); else acb_one(theta2); acb_mul_2exp_si(theta2, theta2, 1); /* theta3 = [1 + 2q^4 + 2q^16] + [2q + 2q^9] */ /* theta4 = [1 + 2q^4 + 2q^16] - [2q + 2q^9] */ if (N > 4) { if (N > 16) acb_add(q4, q4, q16, prec); acb_mul_2exp_si(q4, q4, 1); acb_add_ui(q4, q4, 1, prec); if (N > 9) acb_addmul(q1, q1, q8, prec); acb_mul_2exp_si(q1, q1, 1); acb_add(theta3, q4, q1, prec); acb_sub(theta4, q4, q1, prec); } else { acb_mul_2exp_si(q1, q1, 1); acb_add_ui(theta3, q1, 1, prec); acb_sub_ui(theta4, q1, 1, prec); acb_neg(theta4, theta4); } acb_clear(q1); acb_clear(q2); acb_clear(q4); acb_clear(q8); acb_clear(q16); return; } mag_init(qmag); acb_init(s1); acb_init(s2); acb_init(s3); acb_init(t1); acb_init(t2); tab = flint_calloc(N, sizeof(slong)); qpow = _acb_vec_init(N); for (k = 0; k*(k+1) < N; k++) tab[k*(k+1)] = -1; for (k = 0; 4*k*k < N; k++) tab[4*k*k] = -1; for (k = 0; 4*k*(k+1) + 1 < N; k++) tab[4*k*(k+1)] = -1; if (N > 0) tab[0] = 0; if (N > 1) tab[1] = 1; acb_modular_fill_addseq(tab, N); acb_get_mag(qmag, q); log2q_approx = mag_get_log2_d_approx(qmag); for (k = 0; k < N; k++) { if (k == 0) { acb_one(qpow + k); } else if (k == 1) { acb_set_round(qpow + k, q, prec); } else if (tab[k] != 0) { log2term_approx = k * log2q_approx; term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec); acb_mul_approx(qpow + k, t1, t2, qpow + tab[k], qpow + k - tab[k], term_prec, prec); } } for (k = 0; k*(k+1) < N; k++) acb_add(s1, s1, qpow + k*(k+1), prec); for (k = 1; 4*k*k < N; k++) acb_add(s2, s2, qpow + 4*k*k, prec); for (k = 0; 4*k*(k+1) + 1 < N; k++) acb_add(s3, s3, qpow + 4*k*(k+1), prec); /* theta2 = 2 + 2q^2 + 2q^6 + 2q^12 + 2q^20 + 2q^30 + ... theta3 = 1 + 2 (q^4 + q^16 + ...) + 2q (1 + q^8 + q^24 + ...) theta4 = 1 + 2 (q^4 + q^16 + ...) - 2q (1 + q^8 + q^24 + ...) */ acb_mul(s3, s3, q, prec); acb_mul_2exp_si(s3, s3, 1); acb_mul_2exp_si(s2, s2, 1); acb_add(theta3, s2, s3, prec); acb_sub(theta4, s2, s3, prec); acb_add_ui(theta3, theta3, 1, prec); acb_add_ui(theta4, theta4, 1, prec); acb_mul_2exp_si(theta2, s1, 1); _acb_vec_clear(qpow, N); flint_free(tab); acb_clear(s1); acb_clear(s2); acb_clear(s3); acb_clear(t1); acb_clear(t2); mag_clear(qmag); }
/* F(x) = c0 + c1 x + c2 x^2 + c3 x^3 + [...] F'(x) = c1 + 2 c2 x + 3 c3 x^2 + 4 c4 x^3 + [...] */ static void evaluate_sum(acb_t res, acb_t res1, const acb_t a, const acb_t b, const acb_t c, const acb_t y, const acb_t x, const acb_t f0, const acb_t f1, long num, long prec) { acb_t s, s2, w, d, e, xpow, ck, cknext; long k; acb_init(s); acb_init(s2); acb_init(w); acb_init(d); acb_init(e); acb_init(xpow); acb_init(ck); acb_init(cknext); /* d = (y-1)*y */ acb_sub_ui(d, y, 1, prec); acb_mul(d, d, y, prec); acb_one(xpow); for (k = 0; k < num; k++) { if (k == 0) { acb_set(ck, f0); acb_set(cknext, f1); } else { acb_add_ui(w, b, k-1, prec); acb_mul(w, w, ck, prec); acb_add_ui(e, a, k-1, prec); acb_mul(w, w, e, prec); acb_add(e, a, b, prec); acb_add_ui(e, e, 2*(k+1)-3, prec); acb_mul(e, e, y, prec); acb_sub(e, e, c, prec); acb_sub_ui(e, e, k-1, prec); acb_mul_ui(e, e, k, prec); acb_addmul(w, e, cknext, prec); acb_mul_ui(e, d, k+1, prec); acb_mul_ui(e, e, k, prec); acb_div(w, w, e, prec); acb_neg(w, w); acb_set(ck, cknext); acb_set(cknext, w); } acb_addmul(s, ck, xpow, prec); acb_mul_ui(w, cknext, k+1, prec); acb_addmul(s2, w, xpow, prec); acb_mul(xpow, xpow, x, prec); } acb_set(res, s); acb_set(res1, s2); acb_clear(s); acb_clear(s2); acb_clear(w); acb_clear(d); acb_clear(e); acb_clear(xpow); acb_clear(ck); acb_clear(cknext); }