void arb_hypgeom_coulomb_jet(arb_ptr F, arb_ptr G, const arb_t l, const arb_t eta, const arb_t z, slong len, slong prec) { acb_ptr tmp, tmpF, tmpG; slong k; if (len <= 0) return; if (len == 1) { arb_hypgeom_coulomb(F, G, l, eta, z, prec); return; } tmp = _acb_vec_init(3); tmpF = _acb_vec_init(len); tmpG = _acb_vec_init(len); acb_set_arb(tmp, l); acb_set_arb(tmp + 1, eta); acb_set_arb(tmp + 2, z); acb_hypgeom_coulomb_jet(F ? tmpF : NULL, G ? tmpG : NULL, NULL, NULL, tmp, tmp + 1, tmp + 2, len, prec); if (F != NULL) { if (acb_is_real(tmpF)) for (k = 0; k < len; k++) arb_set(F + k, acb_realref(tmpF + k)); else _arb_vec_indeterminate(F, len); } if (G != NULL) { if (acb_is_real(tmpG)) for (k = 0; k < len; k++) arb_set(G + k, acb_realref(tmpG + k)); else _arb_vec_indeterminate(G, len); } _acb_vec_clear(tmpF, len); _acb_vec_clear(tmpG, len); _acb_vec_clear(tmp, 3); }
void arb_poly_inv_series(arb_poly_t Qinv, const arb_poly_t Q, slong n, slong prec) { if (n == 0) { arb_poly_zero(Qinv); return; } if (Q->length == 0) { arb_poly_fit_length(Qinv, n); _arb_vec_indeterminate(Qinv->coeffs, n); _arb_poly_set_length(Qinv, n); return; } if (Qinv == Q) { arb_poly_t t; arb_poly_init(t); arb_poly_inv_series(t, Q, n, prec); arb_poly_swap(Qinv, t); arb_poly_clear(t); return; } arb_poly_fit_length(Qinv, n); _arb_poly_inv_series(Qinv->coeffs, Q->coeffs, Q->length, n, prec); _arb_poly_set_length(Qinv, n); _arb_poly_normalise(Qinv); }
void arb_poly_sqrt_series(arb_poly_t g, const arb_poly_t h, long n, long prec) { if (n == 0) { arb_poly_zero(g); return; } if (g == h) { arb_poly_t t; arb_poly_init(t); arb_poly_sqrt_series(t, h, n, prec); arb_poly_swap(g, t); arb_poly_clear(t); return; } arb_poly_fit_length(g, n); if (h->length == 0) _arb_vec_indeterminate(g->coeffs, n); else _arb_poly_sqrt_series(g->coeffs, h->coeffs, h->length, n, prec); _arb_poly_set_length(g, n); _arb_poly_normalise(g); }
void arb_poly_cot_pi_series(arb_poly_t res, const arb_poly_t f, slong len, slong prec) { arb_poly_fit_length(res, len); if (f->length == 0 || len == 0) _arb_vec_indeterminate(res->coeffs, len); else _arb_poly_cot_pi_series(res->coeffs, f->coeffs, f->length, len, prec); _arb_poly_set_length(res, len); _arb_poly_normalise(res); }
void arb_poly_log_series(arb_poly_t res, const arb_poly_t f, slong n, slong prec) { if (n == 0) { arb_poly_zero(res); return; } arb_poly_fit_length(res, n); if (f->length == 0) _arb_vec_indeterminate(res->coeffs, n); else _arb_poly_log_series(res->coeffs, f->coeffs, f->length, n, prec); _arb_poly_set_length(res, n); _arb_poly_normalise(res); }
void arb_poly_div_series(arb_poly_t Q, const arb_poly_t A, const arb_poly_t B, long n, long prec) { if (n == 0) { arb_poly_zero(Q); return; } if (B->length == 0) { arb_poly_fit_length(Q, n); _arb_vec_indeterminate(Q->coeffs, n); _arb_poly_set_length(Q, n); return; } if (A->length == 0) { arb_poly_zero(Q); return; } if (Q == A || Q == B) { arb_poly_t t; arb_poly_init(t); arb_poly_div_series(t, A, B, n, prec); arb_poly_swap(Q, t); arb_poly_clear(t); return; } arb_poly_fit_length(Q, n); _arb_poly_div_series(Q->coeffs, A->coeffs, A->length, B->coeffs, B->length, n, prec); _arb_poly_set_length(Q, n); _arb_poly_normalise(Q); }
/* F = 1 + U + U^2 + ... = 1/(1-U) assuming that U[0] is positive; indeterminate if not convergent */ static void arb_poly_geometric_sum(arb_poly_t F, const arb_poly_t U, long len, long prec) { if (U->length == 0) { arb_poly_one(F); return; } arb_poly_add_si(F, U, -1, prec); arb_poly_neg(F, F); if (F->length > 0 && arb_is_positive(F->coeffs)) { arb_poly_inv_series(F, F, len, prec); } else { arb_poly_fit_length(F, len); _arb_vec_indeterminate(F->coeffs, len); _arb_poly_set_length(F, len); } }
/* F = 1 + U + U^2 + U^3 + ... = 1/(1-U) U = product of (1 + |A-B|/(|B[0] - |B[1:]|) product of (1 / (|B[0] - |B[1:]|)) * |Z| */ void acb_hypgeom_pfq_series_bound_factor(arb_poly_t F, const acb_poly_struct * a, long p, const acb_poly_struct * b, long q, const acb_poly_t z, long n, long len, long prec) { long i; arb_poly_t T, U, V; acb_poly_t BN, AB; /* not convergent */ if (p > q) { arb_poly_fit_length(F, len); _arb_vec_indeterminate(F->coeffs, len); _arb_poly_set_length(F, len); return; } arb_poly_init(T); arb_poly_init(U); arb_poly_init(V); acb_poly_init(BN); acb_poly_init(AB); acb_poly_majorant(U, z, prec); for (i = 0; i < q; i++) { acb_poly_add_si(BN, b + i, n, prec); if (acb_poly_length(BN) != 0 && arb_is_positive(acb_realref(BN->coeffs))) { if (i < p) { /* 1 + |a-b|/reciprocal_majorant(b + n) */ acb_poly_sub(AB, a + i, b + i, prec); acb_poly_majorant(T, AB, prec); acb_poly_reciprocal_majorant(V, BN, prec); arb_poly_div_series(T, T, V, len, prec); arb_poly_add_si(T, T, 1, prec); arb_poly_mullow(U, U, T, len, prec); } else { acb_poly_reciprocal_majorant(T, BN, prec); arb_poly_div_series(U, U, T, len, prec); } } else { arb_poly_fit_length(U, len); _arb_vec_indeterminate(U->coeffs, len); _arb_poly_set_length(U, len); break; } } /* F = 1/(1-U) */ arb_poly_geometric_sum(F, U, len, prec); arb_poly_clear(T); arb_poly_clear(U); arb_poly_clear(V); acb_poly_clear(BN); acb_poly_clear(AB); }
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); }
void _arb_poly_lgamma_series(arb_ptr res, arb_srcptr h, slong hlen, slong len, slong prec) { int reflect; slong r, n, wp; arb_t zr; arb_ptr t, u; if (!arb_is_positive(h)) { _arb_vec_indeterminate(res, len); return; } hlen = FLINT_MIN(hlen, len); wp = prec + FLINT_BIT_COUNT(prec); t = _arb_vec_init(len); u = _arb_vec_init(len); arb_init(zr); /* use zeta values at small integers */ if (arb_is_int(h) && (arf_cmpabs_ui(arb_midref(h), prec / 2) < 0)) { r = arf_get_si(arb_midref(h), ARF_RND_DOWN); if (r <= 0) { _arb_vec_indeterminate(res, len); goto cleanup; } else { _arb_poly_lgamma_series_at_one(u, len, wp); if (r != 1) { arb_one(zr); _log_rising_ui_series(t, zr, r - 1, len, wp); _arb_vec_add(u, u, t, len, wp); } } } else if (len <= 2) { arb_lgamma(u, h, wp); if (len == 2) arb_digamma(u + 1, h, wp); } else { /* otherwise use Stirling series */ arb_gamma_stirling_choose_param(&reflect, &r, &n, h, 0, 0, wp); arb_add_ui(zr, h, r, wp); _arb_poly_gamma_stirling_eval(u, zr, n, len, wp); if (r != 0) { _log_rising_ui_series(t, h, r, len, wp); _arb_vec_sub(u, u, t, len, wp); } } /* compose with nonconstant part */ arb_zero(t); _arb_vec_set(t + 1, h + 1, hlen - 1); _arb_poly_compose_series(res, u, len, t, hlen, len, prec); cleanup: arb_clear(zr); _arb_vec_clear(t, len); _arb_vec_clear(u, len); }
void acb_hypgeom_pfq_series_direct(acb_poly_t res, const acb_poly_struct * a, long p, const acb_poly_struct * b, long q, const acb_poly_t z, int regularized, long n, long len, long prec) { acb_poly_t s, t, err; arb_poly_t C, T; long i; int is_real; int terminating; /* default algorithm to choose number of terms */ if (n < 0) { n = acb_hypgeom_pfq_series_choose_n(a, p, b, q, z, len, prec); } terminating = 0; /* check if it terminates due to a root of the numerator */ for (i = 0; i < p; i++) { if (acb_poly_length(a + i) == 0 && n > 0) { terminating = 1; } else if (acb_poly_length(a + i) == 1) { acb_srcptr c = acb_poly_get_coeff_ptr(a + i, 0); if (acb_is_int(c) && arb_is_negative(acb_realref(c)) && arf_cmpabs_ui(arb_midref(acb_realref(c)), n) < 0) { terminating = 1; } } } /* check if it terminates (to order n) due to z */ /* the following tests could be made stronger... */ if (z->length == 0 && n >= 1) { terminating = 1; } else if (!terminating && z->length > 0 && acb_is_zero(z->coeffs) && n >= len) { if (regularized) { terminating = 1; } else { terminating = 1; for (i = 0; i < q; i++) { acb_srcptr c = acb_poly_get_coeff_ptr(b + i, 0); if (!arb_is_positive(acb_realref(c)) && acb_contains_int(c)) terminating = 0; } } } acb_poly_init(s); acb_poly_init(t); acb_poly_init(err); arb_poly_init(C); arb_poly_init(T); acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z, regularized, n, len, prec); if (!terminating) { is_real = acb_poly_is_real(z); for (i = 0; i < p; i++) is_real = is_real && acb_poly_is_real(a + i); for (i = 0; i < q; i++) is_real = is_real && acb_poly_is_real(b + i); acb_poly_majorant(T, t, MAG_BITS); acb_hypgeom_pfq_series_bound_factor(C, a, p, b, q, z, n, len, MAG_BITS); if (!_arb_vec_is_finite(T->coeffs, T->length) || !_arb_vec_is_finite(C->coeffs, C->length)) { arb_poly_fit_length(T, len); _arb_vec_indeterminate(T->coeffs, len); _arb_poly_set_length(T, len); } else { arb_poly_mullow(T, T, C, len, MAG_BITS); } /* create polynomial of errors */ acb_poly_fit_length(err, len); for (i = 0; i < FLINT_MIN(len, T->length); i++) { arb_add_error(acb_realref(err->coeffs + i), T->coeffs + i); if (!is_real) arb_add_error(acb_imagref(err->coeffs + i), T->coeffs + i); } _acb_poly_set_length(err, len); _acb_poly_normalise(err); acb_poly_add(s, s, err, prec); } acb_poly_set(res, s); acb_poly_clear(s); acb_poly_clear(t); acb_poly_clear(err); arb_poly_clear(C); arb_poly_clear(T); }