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; /* default algorithm to choose number of terms */ if (n < 0) { n = acb_hypgeom_pfq_series_choose_n(a, p, b, q, z, len, prec); } 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 (acb_poly_length(t) != 0) { 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); 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); }
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); }