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_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_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_sinh_cosh_series_exponential(arb_ptr s, arb_ptr c, const arb_srcptr h, slong hlen, slong len, slong prec) { arb_ptr t, u, v; arb_t s0, c0; hlen = FLINT_MIN(hlen, len); if (hlen == 1) { arb_sinh_cosh(s, c, h, prec); _arb_vec_zero(s + 1, len - 1); _arb_vec_zero(c + 1, len - 1); return; } arb_init(s0); arb_init(c0); t = _arb_vec_init(3 * len); u = t + len; v = u + len; arb_sinh_cosh(s0, c0, h, prec); _arb_vec_set(t + 1, h + 1, hlen - 1); _arb_poly_exp_series(t, t, len, len, prec); /* todo: part of the inverse could be avoided since exp computes it internally to half the length */ _arb_poly_inv_series(u, t, len, len, prec); /* hyperbolic sine */ _arb_vec_sub(s, t, u, len, prec); _arb_vec_scalar_mul_2exp_si(s, s, len, -1); /* hyperbolic cosine */ _arb_vec_add(c, t, u, len, prec); _arb_vec_scalar_mul_2exp_si(c, c, len, -1); /* sinh(h0 + h1) = cosh(h0) sinh(h1) + sinh(h0) cosh(h1) cosh(h0 + h1) = cosh(h0) cosh(h1) + sinh(h0) sinh(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_add(c, t, v, len, prec); } _arb_vec_clear(t, 3 * len); arb_clear(s0); arb_clear(c0); }
void arb_poly_set(arb_poly_t dest, const arb_poly_t src) { slong len = arb_poly_length(src); arb_poly_fit_length(dest, len); _arb_vec_set(dest->coeffs, src->coeffs, len); _arb_poly_set_length(dest, len); }
void _arb_poly_interpolate_newton(arb_ptr poly, arb_srcptr xs, arb_srcptr ys, long n, long prec) { if (n == 1) { arb_set(poly, ys); } else { _arb_vec_set(poly, ys, n); _interpolate_newton(poly, xs, n, prec); while (n > 0 && arb_is_zero(poly + n - 1)) n--; _newton_to_monomial(poly, xs, n, prec); } }
void cross_site_ws_update_with_edge_rates(cross_site_ws_t w, const model_and_data_t m, const arb_struct *edge_rates, slong prec) { w->prec = prec; /* update rate mixture */ rate_mixture_summarize( w->rate_mix_prior, w->rate_mix_rates, w->rate_mix_expect, m->rate_mixture, prec); /* update the equilibrium if necessary, ignoring diagonal entries */ if (model_and_data_uses_equilibrium(m)) { _arb_vec_rate_matrix_equilibrium(w->equilibrium, m->mat, prec); } /* update the unscaled rate matrix, and zero the diagonal */ arb_mat_set(w->rate_matrix, m->mat); _arb_mat_zero_diagonal(w->rate_matrix); /* update the rate divisor, optionally using the equilibrium */ _update_rate_divisor(w, m, prec); /* * Scale the rate matrix according to the rate divisor. * Each rate matrix associated with a specific rate category * and branch will need to be further scaled. */ arb_mat_scalar_div_arb(w->rate_matrix, w->rate_matrix, w->rate_divisor, prec); /* update the diagonal of the rate matrix */ _arb_update_rate_matrix_diagonal(w->rate_matrix, prec); /* optionally set edge rates */ if (edge_rates) { _arb_vec_set(w->edge_rates, edge_rates, w->edge_count); } /* update the transition probability matrices */ _update_transition_matrices(w, prec); }
void arb_poly_add_si(arb_poly_t res, const arb_poly_t x, long y, long prec) { long len = x->length; if (len == 0) { arb_poly_set_si(res, y); } else { arb_poly_fit_length(res, len); arb_add_si(res->coeffs, x->coeffs, y, prec); if (res != x) _arb_vec_set(res->coeffs + 1, x->coeffs + 1, len - 1); _arb_poly_set_length(res, len); _arb_poly_normalise(res); } }
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_exp_series(arb_ptr f, arb_srcptr h, slong hlen, slong n, slong prec) { hlen = FLINT_MIN(hlen, n); if (hlen == 1) { arb_exp(f, h, prec); _arb_vec_zero(f + 1, n - 1); } else if (n == 2) { arb_exp(f, h, prec); arb_mul(f + 1, f, h + 1, prec); /* safe since hlen >= 2 */ } else if (_arb_vec_is_zero(h + 1, hlen - 2)) /* h = a + bx^d */ { slong i, j, d = hlen - 1; arb_t t; arb_init(t); arb_set(t, h + d); arb_exp(f, h, prec); for (i = 1, j = d; j < n; j += d, i++) { arb_mul(f + j, f + j - d, t, prec); arb_div_ui(f + j, f + j, i, prec); _arb_vec_zero(f + j - d + 1, hlen - 2); } _arb_vec_zero(f + j - d + 1, n - (j - d + 1)); arb_clear(t); } else if (hlen <= arb_poly_newton_exp_cutoff) { _arb_poly_exp_series_basecase(f, h, hlen, n, prec); } else { arb_ptr g, t; arb_t u; int fix; g = _arb_vec_init((n + 1) / 2); fix = (hlen < n || h == f || !arb_is_zero(h)); if (fix) { t = _arb_vec_init(n); _arb_vec_set(t + 1, h + 1, hlen - 1); } else t = (arb_ptr) h; arb_init(u); arb_exp(u, h, prec); _arb_poly_exp_series_newton(f, g, t, n, prec, 0, arb_poly_newton_exp_cutoff); if (!arb_is_one(u)) _arb_vec_scalar_mul(f, f, n, u, prec); _arb_vec_clear(g, (n + 1) / 2); if (fix) _arb_vec_clear(t, n); arb_clear(u); } }
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 _arb_poly_evaluate_vec_fast_precomp(arb_ptr vs, arb_srcptr poly, long plen, arb_ptr * tree, long len, long prec) { long height, i, j, pow, left; long tree_height; long tlen; arb_ptr t, u, swap, pa, pb, pc; /* avoid worrying about some degenerate cases */ if (len < 2 || plen < 2) { if (len == 1) { arb_t tmp; arb_init(tmp); arb_neg(tmp, tree[0] + 0); _arb_poly_evaluate(vs + 0, poly, plen, tmp, prec); arb_clear(tmp); } else if (len != 0 && plen == 0) { _arb_vec_zero(vs, len); } else if (len != 0 && plen == 1) { for (i = 0; i < len; i++) arb_set(vs + i, poly + 0); } return; } t = _arb_vec_init(len); u = _arb_vec_init(len); left = len; /* Initial reduction. We allow the polynomial to be larger or smaller than the number of points. */ height = FLINT_BIT_COUNT(plen - 1) - 1; tree_height = FLINT_CLOG2(len); while (height >= tree_height) height--; pow = 1L << height; for (i = j = 0; i < len; i += pow, j += (pow + 1)) { tlen = ((i + pow) <= len) ? pow : len % pow; _arb_poly_rem(t + i, poly, plen, tree[height] + j, tlen + 1, prec); } for (i = height - 1; i >= 0; i--) { pow = 1L << i; left = len; pa = tree[i]; pb = t; pc = u; while (left >= 2 * pow) { _arb_poly_rem_2(pc, pb, 2 * pow, pa, pow + 1, prec); _arb_poly_rem_2(pc + pow, pb, 2 * pow, pa + pow + 1, pow + 1, prec); pa += 2 * pow + 2; pb += 2 * pow; pc += 2 * pow; left -= 2 * pow; } if (left > pow) { _arb_poly_rem(pc, pb, left, pa, pow + 1, prec); _arb_poly_rem(pc + pow, pb, left, pa + pow + 1, left - pow + 1, prec); } else if (left > 0) _arb_vec_set(pc, pb, left); swap = t; t = u; u = swap; } _arb_vec_set(vs, t, len); _arb_vec_clear(t, len); _arb_vec_clear(u, len); }