void _arb_poly_revert_series_lagrange_fast(arb_ptr Qinv, arb_srcptr Q, long Qlen, long n, long prec) { long i, j, k, m; arb_ptr R, S, T, tmp; arb_t t; if (n <= 2) { if (n >= 1) arb_zero(Qinv); if (n == 2) arb_inv(Qinv + 1, Q + 1, prec); return; } m = n_sqrt(n); arb_init(t); R = _arb_vec_init((n - 1) * m); S = _arb_vec_init(n - 1); T = _arb_vec_init(n - 1); arb_zero(Qinv); arb_inv(Qinv + 1, Q + 1, prec); _arb_poly_inv_series(Ri(1), Q + 1, FLINT_MIN(Qlen, n) - 1, n - 1, prec); for (i = 2; i <= m; i++) _arb_poly_mullow(Ri(i), Ri((i + 1) / 2), n - 1, Ri(i / 2), n - 1, n - 1, prec); for (i = 2; i < m; i++) arb_div_ui(Qinv + i, Ri(i) + i - 1, i, prec); _arb_vec_set(S, Ri(m), n - 1); for (i = m; i < n; i += m) { arb_div_ui(Qinv + i, S + i - 1, i, prec); for (j = 1; j < m && i + j < n; j++) { arb_mul(t, S + 0, Ri(j) + i + j - 1, prec); for (k = 1; k <= i + j - 1; k++) arb_addmul(t, S + k, Ri(j) + i + j - 1 - k, prec); arb_div_ui(Qinv + i + j, t, i + j, prec); } if (i + 1 < n) { _arb_poly_mullow(T, S, n - 1, Ri(m), n - 1, n - 1, prec); tmp = S; S = T; T = tmp; } } arb_clear(t); _arb_vec_clear(R, (n - 1) * m); _arb_vec_clear(S, n - 1); _arb_vec_clear(T, n - 1); }
void _arb_poly_tan_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); if (hlen == 1) { arb_tan(g, h, prec); _arb_vec_zero(g + 1, len - 1); } else if (len == 2) { arb_t t; arb_init(t); arb_tan(g, h, prec); arb_mul(t, g, g, prec); arb_add_ui(t, t, 1, prec); arb_mul(g + 1, t, h + 1, prec); /* safe since hlen >= 2 */ arb_clear(t); } else { arb_ptr t, u; t = _arb_vec_init(2 * len); u = t + len; NEWTON_INIT(TAN_NEWTON_CUTOFF, len) NEWTON_BASECASE(n) _arb_poly_sin_cos_series_basecase(t, u, h, hlen, n, prec, 0); _arb_poly_div_series(g, t, n, u, n, n, prec); NEWTON_END_BASECASE NEWTON_LOOP(m, n) _arb_poly_mullow(u, g, m, g, m, n, prec); arb_add_ui(u, u, 1, prec); _arb_poly_atan_series(t, g, m, n, prec); _arb_poly_sub(t + m, h + m, FLINT_MAX(0, hlen - m), t + m, n - m, prec); _arb_poly_mullow(g + m, u, n, t + m, n - m, n - m, prec); NEWTON_END_LOOP NEWTON_END _arb_vec_clear(t, 2 * len); } }
void _arb_poly_sqrt_series(arb_ptr g, arb_srcptr h, long hlen, long len, long prec) { hlen = FLINT_MIN(hlen, len); if (hlen == 1) { arb_sqrt(g, h, prec); _arb_vec_zero(g + 1, len - 1); } else if (len == 2) { arb_sqrt(g, h, prec); arb_div(g + 1, h + 1, h, prec); arb_mul(g + 1, g + 1, g, prec); arb_mul_2exp_si(g + 1, g + 1, -1); } else { arb_ptr t; t = _arb_vec_init(len); _arb_poly_rsqrt_series(t, h, hlen, len, prec); _arb_poly_mullow(g, t, len, h, hlen, len, prec); _arb_vec_clear(t, len); } }
static void _arb_poly_rising_ui_series_bsplit(arb_ptr res, arb_srcptr f, slong flen, ulong a, ulong b, slong trunc, slong prec) { flen = FLINT_MIN(flen, trunc); if (b - a == 1) { arb_add_ui(res, f, a, prec); _arb_vec_set(res + 1, f + 1, flen - 1); } else { arb_ptr L, R; slong len1, len2; slong m = a + (b - a) / 2; len1 = poly_pow_length(flen, m - a, trunc); len2 = poly_pow_length(flen, b - m, trunc); L = _arb_vec_init(len1 + len2); R = L + len1; _arb_poly_rising_ui_series_bsplit(L, f, flen, a, m, trunc, prec); _arb_poly_rising_ui_series_bsplit(R, f, flen, m, b, trunc, prec); _arb_poly_mullow(res, L, len1, R, len2, FLINT_MIN(trunc, len1 + len2 - 1), prec); _arb_vec_clear(L, len1 + len2); } }
void _arb_poly_divrem(arb_ptr Q, arb_ptr R, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) { const slong lenQ = lenA - lenB + 1; _arb_poly_div(Q, A, lenA, B, lenB, prec); if (lenB > 1) { if (lenQ >= lenB - 1) _arb_poly_mullow(R, Q, lenQ, B, lenB - 1, lenB - 1, prec); else _arb_poly_mullow(R, B, lenB - 1, Q, lenQ, lenB - 1, prec); _arb_vec_sub(R, A, R, lenB - 1, prec); } }
void _arb_poly_log1p_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec) { arb_t a; flen = FLINT_MIN(flen, n); arb_init(a); arb_log1p(a, f, prec); if (flen == 1) { _arb_vec_zero(res + 1, n - 1); } else if (n == 2) { arb_add_ui(res, f + 0, 1, prec); arb_div(res + 1, f + 1, res + 0, prec); } else if (_arb_vec_is_zero(f + 1, flen - 2)) /* f = a + bx^d */ { slong i, j, d = flen - 1; arb_add_ui(res, f + 0, 1, prec); for (i = 1, j = d; j < n; j += d, i++) { if (i == 1) arb_div(res + j, f + d, res, prec); else arb_mul(res + j, res + j - d, res + d, prec); _arb_vec_zero(res + j - d + 1, flen - 2); } _arb_vec_zero(res + j - d + 1, n - (j - d + 1)); for (i = 2, j = 2 * d; j < n; j += d, i++) arb_div_si(res + j, res + j, i % 2 ? i : -i, prec); } else { arb_ptr f_diff, f_inv; slong alloc; alloc = n + flen; f_inv = _arb_vec_init(alloc); f_diff = f_inv + n; arb_add_ui(f_diff, f, 1, prec); _arb_vec_set(f_diff + 1, f + 1, flen - 1); _arb_poly_inv_series(f_inv, f_diff, flen, n, prec); _arb_poly_derivative(f_diff, f, flen, prec); _arb_poly_mullow(res, f_inv, n - 1, f_diff, flen - 1, n - 1, prec); _arb_poly_integral(res, res, n, prec); _arb_vec_clear(f_inv, alloc); } arb_swap(res, a); arb_clear(a); }
void _arb_poly_asin_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec) { arb_t c; arb_init(c); arb_asin(c, h, prec); hlen = FLINT_MIN(hlen, n); if (hlen == 1) { _arb_vec_zero(g + 1, n - 1); } else { arb_ptr t, u; slong ulen; t = _arb_vec_init(n); u = _arb_vec_init(n); /* asin(h(x)) = integral(h'(x)/sqrt(1-h(x)^2)) */ ulen = FLINT_MIN(n, 2 * hlen - 1); _arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec); arb_sub_ui(u, u, 1, prec); _arb_vec_neg(u, u, ulen); _arb_poly_rsqrt_series(t, u, ulen, n, prec); _arb_poly_derivative(u, h, hlen, prec); _arb_poly_mullow(g, t, n, u, hlen - 1, n, prec); _arb_poly_integral(g, g, n, prec); _arb_vec_clear(t, n); _arb_vec_clear(u, n); } arb_swap(g, c); arb_clear(c); }
void arb_poly_mullow(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, long n, long prec) { long len_out; if (poly1->length == 0 || poly2->length == 0 || n == 0) { arb_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (n > len_out) n = len_out; if (res == poly1 || res == poly2) { arb_poly_t t; arb_poly_init2(t, n); _arb_poly_mullow(t->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n, prec); arb_poly_swap(res, t); arb_poly_clear(t); } else { arb_poly_fit_length(res, n); _arb_poly_mullow(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, n, prec); } _arb_poly_set_length(res, n); _arb_poly_normalise(res); }
void _arb_poly_div_series(arb_ptr Q, arb_srcptr A, long Alen, arb_srcptr B, long Blen, long n, long prec) { Alen = FLINT_MIN(Alen, n); Blen = FLINT_MIN(Blen, n); if (Blen == 1) { _arb_vec_scalar_div(Q, A, Alen, B, prec); _arb_vec_zero(Q + Alen, n - Alen); } else { arb_ptr Binv; Binv = _arb_vec_init(n); _arb_poly_inv_series(Binv, B, Blen, n, prec); _arb_poly_mullow(Q, Binv, n, A, Alen, n, prec); _arb_vec_clear(Binv, n); } }
int sin_x2(arb_ptr out, const arb_t inp, void * params, long order, long prec) { arb_ptr x; int xlen = FLINT_MIN(2, order); int ylen = FLINT_MIN(3, order); x = _arb_vec_init(xlen); arb_set(x, inp); if (xlen > 1) arb_one(x + 1); _arb_poly_mullow(out, x, xlen, x, xlen, ylen, prec); _arb_poly_sin_series(out, out, ylen, order, prec); _arb_vec_clear(x, xlen); eval_count++; return 0; }
void _arb_poly_sqrt_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec) { hlen = FLINT_MIN(hlen, len); while (hlen > 0 && arb_is_zero(h + hlen - 1)) hlen--; if (hlen <= 1) { arb_sqrt(g, h, prec); _arb_vec_zero(g + 1, len - 1); } else if (len == 2) { arb_sqrt(g, h, prec); arb_div(g + 1, h + 1, h, prec); arb_mul(g + 1, g + 1, g, prec); arb_mul_2exp_si(g + 1, g + 1, -1); } else if (_arb_vec_is_zero(h + 1, hlen - 2)) { arb_t t; arb_init(t); arf_set_si_2exp_si(arb_midref(t), 1, -1); _arb_poly_binomial_pow_arb_series(g, h, hlen, t, len, prec); arb_clear(t); } else { arb_ptr t; t = _arb_vec_init(len); _arb_poly_rsqrt_series(t, h, hlen, len, prec); _arb_poly_mullow(g, t, len, h, hlen, len, prec); _arb_vec_clear(t, len); } }
void _arb_poly_rgamma_series(arb_ptr res, arb_srcptr h, long hlen, long len, long prec) { int reflect; long i, rflen, r, n, wp; arb_ptr t, u, v; arb_struct f[2]; hlen = FLINT_MIN(hlen, len); wp = prec + FLINT_BIT_COUNT(prec); t = _arb_vec_init(len); u = _arb_vec_init(len); v = _arb_vec_init(len); arb_init(f); arb_init(f + 1); /* 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); _arb_poly_lgamma_series_at_one(u, len, wp); _arb_vec_neg(u, u, len); _arb_poly_exp_series(t, u, len, len, wp); if (r == 1) { _arb_vec_swap(v, t, len); } else if (r <= 0) { arb_set(f, h); arb_one(f + 1); rflen = FLINT_MIN(len, 2 - r); _arb_poly_rising_ui_series(u, f, FLINT_MIN(2, len), 1 - r, rflen, wp); _arb_poly_mullow(v, t, len, u, rflen, len, wp); } else { arb_one(f); arb_one(f + 1); rflen = FLINT_MIN(len, r); _arb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r - 1, rflen, wp); /* TODO: use div_series? */ _arb_poly_inv_series(u, v, rflen, len, wp); _arb_poly_mullow(v, t, len, u, len, len, wp); } } else { /* otherwise use Stirling series */ arb_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 0, wp); /* rgamma(h) = (gamma(1-h+r) sin(pi h)) / (rf(1-h, r) * pi), h = h0 + t*/ if (reflect) { /* u = gamma(r+1-h) */ arb_sub_ui(f, h, r + 1, wp); arb_neg(f, f); _arb_poly_gamma_stirling_eval(t, f, n, len, wp); _arb_poly_exp_series(u, t, len, len, wp); for (i = 1; i < len; i += 2) arb_neg(u + i, u + i); /* v = sin(pi x) */ arb_const_pi(f + 1, wp); arb_mul(f, h, f + 1, wp); _arb_poly_sin_series(v, f, 2, len, wp); _arb_poly_mullow(t, u, len, v, len, len, wp); /* rf(1-h,r) * pi */ if (r == 0) { arb_const_pi(u, wp); _arb_vec_scalar_div(v, t, len, u, wp); } else { arb_sub_ui(f, h, 1, wp); arb_neg(f, f); arb_set_si(f + 1, -1); rflen = FLINT_MIN(len, r + 1); _arb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r, rflen, wp); arb_const_pi(u, wp); _arb_vec_scalar_mul(v, v, rflen, u, wp); /* divide by rising factorial */ /* TODO: might better to use div_series, when it has a good basecase */ _arb_poly_inv_series(u, v, rflen, len, wp); _arb_poly_mullow(v, t, len, u, len, len, wp); } } else { /* rgamma(h) = rgamma(h+r) rf(h,r) */ if (r == 0) { arb_add_ui(f, h, r, wp); _arb_poly_gamma_stirling_eval(t, f, n, len, wp); _arb_vec_neg(t, t, len); _arb_poly_exp_series(v, t, len, len, wp); } else { arb_set(f, h); arb_one(f + 1); rflen = FLINT_MIN(len, r + 1); _arb_poly_rising_ui_series(t, f, FLINT_MIN(2, len), r, rflen, wp); arb_add_ui(f, h, r, wp); _arb_poly_gamma_stirling_eval(v, f, n, len, wp); _arb_vec_neg(v, v, len); _arb_poly_exp_series(u, v, len, len, wp); _arb_poly_mullow(v, u, len, t, rflen, len, wp); } } } /* compose with nonconstant part */ arb_zero(t); _arb_vec_set(t + 1, h + 1, hlen - 1); _arb_poly_compose_series(res, v, len, t, hlen, len, prec); arb_clear(f); arb_clear(f + 1); _arb_vec_clear(t, len); _arb_vec_clear(u, len); _arb_vec_clear(v, len); }
void _arb_poly_pow_ui_trunc_binexp(arb_ptr res, arb_srcptr f, slong flen, ulong exp, slong len, slong prec) { arb_ptr v, R, S, T; slong rlen; ulong bit; if (exp <= 1) { if (exp == 0) arb_one(res); else if (exp == 1) _arb_vec_set_round(res, f, len, prec); return; } /* (f * x^r)^m = x^(rm) * f^m */ while (flen > 1 && arb_is_zero(f)) { if (((ulong) len) > exp) { _arb_vec_zero(res, exp); len -= exp; res += exp; } else { _arb_vec_zero(res, len); return; } f++; flen--; } if (exp == 2) { _arb_poly_mullow(res, f, flen, f, flen, len, prec); return; } if (flen == 1) { arb_pow_ui(res, f, exp, prec); return; } v = _arb_vec_init(len); bit = UWORD(1) << (FLINT_BIT_COUNT(exp) - 2); if (n_zerobits(exp) % 2) { R = res; S = v; } else { R = v; S = res; } MUL(R, rlen, f, flen, f, flen, len, prec); if (bit & exp) { MUL(S, rlen, R, rlen, f, flen, len, prec); T = R; R = S; S = T; } while (bit >>= 1) { if (bit & exp) { MUL(S, rlen, R, rlen, R, rlen, len, prec); MUL(R, rlen, S, rlen, f, flen, len, prec); } else { MUL(S, rlen, R, rlen, R, rlen, len, prec); T = R; R = S; S = T; } } _arb_vec_clear(v, len); }
/* with inverse=1 simultaneously computes g = exp(-x) to length n with inverse=0 uses g as scratch space, computing g = exp(-x) only to length (n+1)/2 */ static void _arb_poly_exp_series_newton(arb_ptr f, arb_ptr g, arb_srcptr h, slong len, slong prec, int inverse, slong cutoff) { slong alloc; arb_ptr T, U, hprime; alloc = 3 * len; T = _arb_vec_init(alloc); U = T + len; hprime = U + len; _arb_poly_derivative(hprime, h, len, prec); arb_zero(hprime + len - 1); NEWTON_INIT(cutoff, len) /* f := exp(h) + O(x^m), g := exp(-h) + O(x^m2) */ NEWTON_BASECASE(n) _arb_poly_exp_series_basecase(f, h, n, n, prec); _arb_poly_inv_series(g, f, (n + 1) / 2, (n + 1) / 2, prec); NEWTON_END_BASECASE /* extend from length m to length n */ NEWTON_LOOP(m, n) slong m2 = (m + 1) / 2; slong l = m - 1; /* shifted for derivative */ /* g := exp(-h) + O(x^m) */ _arb_poly_mullow(T, f, m, g, m2, m, prec); _arb_poly_mullow(g + m2, g, m2, T + m2, m - m2, m - m2, prec); _arb_vec_neg(g + m2, g + m2, m - m2); /* U := h' + g (f' - f h') + O(x^(n-1)) Note: should replace h' by h' mod x^(m-1) */ _arb_vec_zero(f + m, n - m); _arb_poly_mullow(T, f, n, hprime, n, n, prec); /* should be mulmid */ _arb_poly_derivative(U, f, n, prec); arb_zero(U + n - 1); /* should skip low terms */ _arb_vec_sub(U + l, U + l, T + l, n - l, prec); _arb_poly_mullow(T + l, g, n - m, U + l, n - m, n - m, prec); _arb_vec_add(U + l, hprime + l, T + l, n - m, prec); /* f := f + f * (h - int U) + O(x^n) = exp(h) + O(x^n) */ _arb_poly_integral(U, U, n, prec); /* should skip low terms */ _arb_vec_sub(U + m, h + m, U + m, n - m, prec); _arb_poly_mullow(f + m, f, n - m, U + m, n - m, n - m, prec); /* g := exp(-h) + O(x^n) */ /* not needed if we only want exp(x) */ if (n == len && inverse) { _arb_poly_mullow(T, f, n, g, m, n, prec); _arb_poly_mullow(g + m, g, m, T + m, n - m, n - m, prec); _arb_vec_neg(g + m, g + m, n - m); } NEWTON_END_LOOP NEWTON_END _arb_vec_clear(T, alloc); }
void _acb_poly_zeta_em_bound(arb_ptr bound, const acb_t s, const acb_t a, ulong N, ulong M, slong len, slong wp) { arb_t K, C, AN, S2M; arb_ptr F, R; slong k; arb_srcptr alpha = acb_realref(a); arb_srcptr beta = acb_imagref(a); arb_srcptr sigma = acb_realref(s); arb_srcptr tau = acb_imagref(s); arb_init(AN); arb_init(S2M); /* require alpha + N > 1, sigma + 2M > 1 */ arb_add_ui(AN, alpha, N - 1, wp); arb_add_ui(S2M, sigma, 2*M - 1, wp); if (!arb_is_positive(AN) || !arb_is_positive(S2M) || N < 1 || M < 1) { arb_clear(AN); arb_clear(S2M); for (k = 0; k < len; k++) arb_pos_inf(bound + k); return; } /* alpha + N, sigma + 2M */ arb_add_ui(AN, AN, 1, wp); arb_add_ui(S2M, S2M, 1, wp); R = _arb_vec_init(len); F = _arb_vec_init(len); arb_init(K); arb_init(C); /* bound for power integral */ bound_C(C, AN, beta, wp); bound_K(K, AN, beta, tau, wp); bound_I(R, AN, S2M, C, len, wp); for (k = 0; k < len; k++) { arb_mul(R + k, R + k, K, wp); arb_div_ui(K, K, k + 1, wp); } /* bound for rising factorial */ bound_rfac(F, s, 2*M, len, wp); /* product (TODO: only need upper bound; write a function for this) */ _arb_poly_mullow(bound, F, len, R, len, len, wp); /* bound for bernoulli polynomials, 4 / (2pi)^(2M) */ arb_const_pi(C, wp); arb_mul_2exp_si(C, C, 1); arb_pow_ui(C, C, 2 * M, wp); arb_ui_div(C, 4, C, wp); _arb_vec_scalar_mul(bound, bound, len, C, wp); arb_clear(K); arb_clear(C); arb_clear(AN); arb_clear(S2M); _arb_vec_clear(R, len); _arb_vec_clear(F, len); }
void _arb_poly_sin_cos_series_tangent(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong len, slong prec, int times_pi) { arb_ptr t, u, v; arb_t s0, c0; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { if (times_pi) arb_sin_cos_pi(s, c, h, prec); else arb_sin_cos(s, c, h, prec); _arb_vec_zero(s + 1, len - 1); _arb_vec_zero(c + 1, len - 1); return; } /* sin(x) = 2*tan(x/2)/(1+tan(x/2)^2) cos(x) = (1-tan(x/2)^2)/(1+tan(x/2)^2) */ arb_init(s0); arb_init(c0); t = _arb_vec_init(3 * len); u = t + len; v = u + len; /* sin, cos of h0 */ if (times_pi) arb_sin_cos_pi(s0, c0, h, prec); else arb_sin_cos(s0, c0, h, prec); /* t = tan((h-h0)/2) */ arb_zero(u); _arb_vec_scalar_mul_2exp_si(u + 1, h + 1, hlen - 1, -1); if (times_pi) { arb_const_pi(t, prec); _arb_vec_scalar_mul(u + 1, u + 1, hlen - 1, t, prec); } _arb_poly_tan_series(t, u, hlen, len, prec); /* v = 1 + t^2 */ _arb_poly_mullow(v, t, len, t, len, len, prec); arb_add_ui(v, v, 1, prec); /* u = 1/(1+t^2) */ _arb_poly_inv_series(u, v, len, len, prec); /* sine */ _arb_poly_mullow(s, t, len, u, len, len, prec); _arb_vec_scalar_mul_2exp_si(s, s, len, 1); /* cosine */ arb_sub_ui(v, v, 2, prec); _arb_vec_neg(v, v, len); _arb_poly_mullow(c, v, len, u, len, len, prec); /* sin(h0 + h1) = cos(h0) sin(h1) + sin(h0) cos(h1) cos(h0 + h1) = cos(h0) cos(h1) - sin(h0) sin(h1) */ if (!arb_is_zero(s0)) { _arb_vec_scalar_mul(t, s, len, c0, prec); _arb_vec_scalar_mul(u, c, len, s0, prec); _arb_vec_scalar_mul(v, s, len, s0, prec); _arb_vec_add(s, t, u, len, prec); _arb_vec_scalar_mul(t, c, len, c0, prec); _arb_vec_sub(c, t, v, len, prec); } _arb_vec_clear(t, 3 * len); arb_clear(s0); arb_clear(c0); }
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 _acb_poly_mullow_transpose_gauss(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec) { arb_ptr a, b, c, d, e, f, w; arb_ptr t, u, v; slong i; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); w = flint_malloc(sizeof(arb_struct) * (2 * (len1 + len2 + n))); a = w; b = a + len1; c = b + len1; d = c + len2; e = d + len2; f = e + n; t = _arb_vec_init(n); u = _arb_vec_init(n); v = _arb_vec_init(n); for (i = 0; i < len1; i++) { a[i] = *acb_realref(poly1 + i); b[i] = *acb_imagref(poly1 + i); } for (i = 0; i < len2; i++) { c[i] = *acb_realref(poly2 + i); d[i] = *acb_imagref(poly2 + i); } for (i = 0; i < n; i++) { e[i] = *acb_realref(res + i); f[i] = *acb_imagref(res + i); } _arb_vec_add(t, a, b, len1, prec); _arb_vec_add(u, c, d, len2, prec); _arb_poly_mullow(v, t, len1, u, len2, n, prec); _arb_poly_mullow(t, a, len1, c, len2, n, prec); _arb_poly_mullow(u, b, len1, d, len2, n, prec); _arb_vec_sub(e, t, u, n, prec); _arb_vec_sub(f, v, t, n, prec); _arb_vec_sub(f, f, u, n, prec); for (i = 0; i < n; i++) { *acb_realref(res + i) = e[i]; *acb_imagref(res + i) = f[i]; } _arb_vec_clear(t, n); _arb_vec_clear(u, n); _arb_vec_clear(v, n); flint_free(w); }
void _arb_poly_mul(arb_ptr C, arb_srcptr A, slong lenA, arb_srcptr B, slong lenB, slong prec) { _arb_poly_mullow(C, A, lenA, B, lenB, lenA + lenB - 1, prec); }
void _acb_poly_mullow_transpose(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec) { arb_ptr a, b, c, d, e, f, w; arb_ptr t; slong i; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); w = flint_malloc(sizeof(arb_struct) * (2 * (len1 + len2 + n))); a = w; b = a + len1; c = b + len1; d = c + len2; e = d + len2; f = e + n; /* (e+fi) = (a+bi)(c+di) = (ac - bd) + (ad + bc)i */ t = _arb_vec_init(n); for (i = 0; i < len1; i++) { a[i] = *acb_realref(poly1 + i); b[i] = *acb_imagref(poly1 + i); } for (i = 0; i < len2; i++) { c[i] = *acb_realref(poly2 + i); d[i] = *acb_imagref(poly2 + i); } for (i = 0; i < n; i++) { e[i] = *acb_realref(res + i); f[i] = *acb_imagref(res + i); } _arb_poly_mullow(e, a, len1, c, len2, n, prec); _arb_poly_mullow(t, b, len1, d, len2, n, prec); _arb_vec_sub(e, e, t, n, prec); _arb_poly_mullow(f, a, len1, d, len2, n, prec); /* squaring */ if (poly1 == poly2 && len1 == len2) { _arb_vec_scalar_mul_2exp_si(f, f, n, 1); } else { _arb_poly_mullow(t, b, len1, c, len2, n, prec); _arb_vec_add(f, f, t, n, prec); } for (i = 0; i < n; i++) { *acb_realref(res + i) = e[i]; *acb_imagref(res + i) = f[i]; } _arb_vec_clear(t, n); flint_free(w); }