void zeta_ui(fmprb_t x, ulong n, long prec) { if (n == 0) { fmprb_set_si(x, -1); fmprb_mul_2exp_si(x, x, -1); } else if (n == 1) { printf("exception: zeta_ui(1)\n"); abort(); } /* fast detection of asymptotic case */ else if (n > 0.7 * prec) { zeta_ui_asymp(x, n, prec); } else { /* even */ if (n % 2 == 0) { if (((prec < 10000) && (n < 40 + 0.11*prec)) || ((prec >= 10000) && (arith_bernoulli_number_size(n) * 0.9 < prec))) { zeta_ui_bernoulli(x, n, prec); } else { zeta_ui_euler_product(x, n, prec); } } else { if (n == 3) { zeta_apery_bsplit(x, prec); } else if (n < prec * 0.0006) { /* small odd n, extremely high precision */ zeta_ui_borwein_bsplit(x, n, prec); } else if (prec > 20 && n > 6 && n > 0.4 * pow(prec, 0.8)) { /* large n */ zeta_ui_euler_product(x, n, prec); } else { /* fallback */ zeta_ui_vec_borwein(x, n, 1, 0, prec); } } } }
void fmprb_si_pow_ui(fmprb_t y, long b, ulong e, long prec) { fmprb_t t; fmprb_init(t); fmprb_set_si(t, b); fmprb_pow_ui(y, t, e, prec); fmprb_clear(t); }
void fmprb_add_si(fmprb_t z, const fmprb_t x, slong y, slong prec) { fmprb_t t; fmprb_init(t); fmprb_set_si(t, y); fmprb_add(z, x, t, prec); fmprb_clear(t); }
void fmprb_sub_si(fmprb_t z, const fmprb_t x, long y, long prec) { fmprb_t t; fmprb_init(t); fmprb_set_si(t, y); fmprb_sub(z, x, t, prec); fmprb_clear(t); }
static __inline__ void zeta_coeff_k(zeta_bsplit_t S, long k, long n, long s) { fmprb_set_si(S->D, 2 * (n + k)); fmprb_mul_si(S->D, S->D, n - k, FMPR_PREC_EXACT); fmprb_set_si(S->Q1, k + 1); fmprb_mul_si(S->Q1, S->Q1, 2*k + 1, FMPR_PREC_EXACT); if (k == 0) { fmprb_zero(S->A); fmprb_one(S->Q2); } else { fmprb_set_si(S->A, k % 2 ? 1 : -1); fmprb_mul(S->A, S->A, S->Q1, FMPR_PREC_EXACT); fmprb_ui_pow_ui(S->Q2, k, s, FMPR_PREC_EXACT); } fmprb_mul(S->Q3, S->Q1, S->Q2, FMPR_PREC_EXACT); fmprb_zero(S->B); fmprb_set(S->C, S->Q1); }
void fmprb_mat_det_inplace(fmprb_t det, fmprb_mat_t A, long prec) { long i, n, sign, rank; n = fmprb_mat_nrows(A); rank = fmprb_mat_gauss_partial(A, prec); sign = (rank < 0) ? -1 : 1; rank = FLINT_ABS(rank); fmprb_set_si(det, sign); for (i = 0; i < rank; i++) fmprb_mul(det, det, fmprb_mat_entry(A, i, i), prec); /* bound unreduced part using Hadamard's inequality */ if (rank < n) { fmpr_t t; fmprb_t d; fmpr_init(t); fmprb_init(d); fmpr_one(fmprb_radref(d)); for (i = rank; i < n; i++) { fmprb_vec_get_fmpr_2norm_squared_bound(t, A->rows[i] + rank, n - rank, FMPRB_RAD_PREC); fmpr_mul(fmprb_radref(d), fmprb_radref(d), t, FMPRB_RAD_PREC, FMPR_RND_UP); } fmpr_sqrt(fmprb_radref(d), fmprb_radref(d), FMPRB_RAD_PREC, FMPR_RND_UP); fmprb_mul(det, det, d, prec); fmprb_clear(d); fmpr_clear(t); } }
void _fmprb_poly_zeta_series(fmprb_ptr res, fmprb_srcptr h, long hlen, const fmprb_t a, int deflate, long len, long prec) { long i; fmpcb_t cs, ca; fmpcb_ptr z; fmprb_ptr t, u; if (fmprb_contains_nonpositive(a)) { _fmprb_vec_indeterminate(res, len); return; } hlen = FLINT_MIN(hlen, len); z = _fmpcb_vec_init(len); t = _fmprb_vec_init(len); u = _fmprb_vec_init(len); fmpcb_init(cs); fmpcb_init(ca); /* use reflection formula */ if (fmpr_sgn(fmprb_midref(h)) < 0 && fmprb_is_one(a)) { /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */ fmprb_t pi; fmprb_ptr f, s1, s2, s3, s4; fmprb_init(pi); f = _fmprb_vec_init(2); s1 = _fmprb_vec_init(len); s2 = _fmprb_vec_init(len); s3 = _fmprb_vec_init(len); s4 = _fmprb_vec_init(len); fmprb_const_pi(pi, prec); /* s1 = (2*pi)**s */ fmprb_mul_2exp_si(pi, pi, 1); _fmprb_poly_pow_cpx(s1, pi, h, len, prec); fmprb_mul_2exp_si(pi, pi, -1); /* s2 = sin(pi*s/2) / pi */ fmprb_mul_2exp_si(pi, pi, -1); fmprb_mul(f, pi, h, prec); fmprb_set(f + 1, pi); fmprb_mul_2exp_si(pi, pi, 1); _fmprb_poly_sin_series(s2, f, 2, len, prec); _fmprb_vec_scalar_div(s2, s2, len, pi, prec); /* s3 = gamma(1-s) */ fmprb_sub_ui(f, h, 1, prec); fmprb_neg(f, f); fmprb_set_si(f + 1, -1); _fmprb_poly_gamma_series(s3, f, 2, len, prec); /* s4 = zeta(1-s) */ fmprb_sub_ui(f, h, 1, prec); fmprb_neg(f, f); fmpcb_set_fmprb(cs, f); fmpcb_one(ca); zeta_series(z, cs, ca, 0, len, prec); for (i = 0; i < len; i++) fmprb_set(s4 + i, fmpcb_realref(z + i)); for (i = 1; i < len; i += 2) fmprb_neg(s4 + i, s4 + i); _fmprb_poly_mullow(u, s1, len, s2, len, len, prec); _fmprb_poly_mullow(s1, s3, len, s4, len, len, prec); _fmprb_poly_mullow(t, u, len, s1, len, len, prec); /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */ if (deflate) { fmprb_sub_ui(u, h, 1, prec); fmprb_neg(u, u); fmprb_ui_div(u, 1, u, prec); for (i = 1; i < len; i++) fmprb_mul(u + i, u + i - 1, u, prec); _fmprb_vec_add(t, t, u, len, prec); } fmprb_clear(pi); _fmprb_vec_clear(f, 2); _fmprb_vec_clear(s1, len); _fmprb_vec_clear(s2, len); _fmprb_vec_clear(s3, len); _fmprb_vec_clear(s4, len); } else { fmpcb_set_fmprb(cs, h); fmpcb_set_fmprb(ca, a); zeta_series(z, cs, ca, deflate, len, prec); for (i = 0; i < len; i++) fmprb_set(t + i, fmpcb_realref(z + i)); } /* compose with nonconstant part */ fmprb_zero(u); _fmprb_vec_set(u + 1, h + 1, hlen - 1); _fmprb_poly_compose_series(res, t, len, u, hlen, len, prec); _fmpcb_vec_clear(z, len); _fmprb_vec_clear(t, len); _fmprb_vec_clear(u, len); fmpcb_init(cs); fmpcb_init(ca); }
void _fmprb_poly_rgamma_series(fmprb_ptr res, fmprb_srcptr h, long hlen, long len, long prec) { int reflect; long i, rflen, r, n, wp; fmprb_ptr t, u, v; fmprb_struct f[2]; hlen = FLINT_MIN(hlen, len); wp = prec + FLINT_BIT_COUNT(prec); t = _fmprb_vec_init(len); u = _fmprb_vec_init(len); v = _fmprb_vec_init(len); fmprb_init(f); fmprb_init(f + 1); /* use zeta values at small integers */ if (fmprb_is_int(h) && (fmpr_cmpabs_ui(fmprb_midref(h), prec / 2) < 0)) { r = fmpr_get_si(fmprb_midref(h), FMPR_RND_DOWN); gamma_lgamma_series_at_one(u, len, wp); _fmprb_vec_neg(u, u, len); _fmprb_poly_exp_series(t, u, len, len, wp); if (r == 1) { _fmprb_vec_swap(v, t, len); } else if (r <= 0) { fmprb_set(f, h); fmprb_one(f + 1); rflen = FLINT_MIN(len, 2 - r); _fmprb_poly_rising_ui_series(u, f, FLINT_MIN(2, len), 1 - r, rflen, wp); _fmprb_poly_mullow(v, t, len, u, rflen, len, wp); } else { fmprb_one(f); fmprb_one(f + 1); rflen = FLINT_MIN(len, r); _fmprb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r - 1, rflen, wp); /* TODO: use div_series? */ _fmprb_poly_inv_series(u, v, rflen, len, wp); _fmprb_poly_mullow(v, t, len, u, len, len, wp); } } else { /* otherwise use Stirling series */ gamma_stirling_choose_param_fmprb(&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) */ fmprb_sub_ui(f, h, r + 1, wp); fmprb_neg(f, f); gamma_stirling_eval_fmprb_series(t, f, n, len, wp); _fmprb_poly_exp_series(u, t, len, len, wp); for (i = 1; i < len; i += 2) fmprb_neg(u + i, u + i); /* v = sin(pi x) */ fmprb_const_pi(f + 1, wp); fmprb_mul(f, h, f + 1, wp); _fmprb_poly_sin_series(v, f, 2, len, wp); _fmprb_poly_mullow(t, u, len, v, len, len, wp); /* rf(1-h,r) * pi */ if (r == 0) { fmprb_const_pi(u, wp); _fmprb_vec_scalar_div(v, t, len, u, wp); } else { fmprb_sub_ui(f, h, 1, wp); fmprb_neg(f, f); fmprb_set_si(f + 1, -1); rflen = FLINT_MIN(len, r + 1); _fmprb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r, rflen, wp); fmprb_const_pi(u, wp); _fmprb_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 */ _fmprb_poly_inv_series(u, v, rflen, len, wp); _fmprb_poly_mullow(v, t, len, u, len, len, wp); } } else { /* rgamma(h) = rgamma(h+r) rf(h,r) */ if (r == 0) { fmprb_add_ui(f, h, r, wp); gamma_stirling_eval_fmprb_series(t, f, n, len, wp); _fmprb_vec_neg(t, t, len); _fmprb_poly_exp_series(v, t, len, len, wp); } else { fmprb_set(f, h); fmprb_one(f + 1); rflen = FLINT_MIN(len, r + 1); _fmprb_poly_rising_ui_series(t, f, FLINT_MIN(2, len), r, rflen, wp); fmprb_add_ui(f, h, r, wp); gamma_stirling_eval_fmprb_series(v, f, n, len, wp); _fmprb_vec_neg(v, v, len); _fmprb_poly_exp_series(u, v, len, len, wp); _fmprb_poly_mullow(v, u, len, t, rflen, len, wp); } } } /* compose with nonconstant part */ fmprb_zero(t); _fmprb_vec_set(t + 1, h + 1, hlen - 1); _fmprb_poly_compose_series(res, v, len, t, hlen, len, prec); fmprb_clear(f); fmprb_clear(f + 1); _fmprb_vec_clear(t, len); _fmprb_vec_clear(u, len); _fmprb_vec_clear(v, len); }