/* x(x+1)...(x+7) = (28 + 98x + 63x^2 + 14x^3 + x^4)^2 - 16 (7+2x)^2 */ static void rfac_eight(fmprb_t t, const fmprb_t x, long prec) { fmprb_t u, v; fmprb_init(u); fmprb_init(v); /* t = x^2, v = x^3, u = x^4 */ fmprb_mul(t, x, x, prec); fmprb_mul(v, x, t, prec); fmprb_mul(u, t, t, prec); /* u = (28 + ...)^2 */ fmprb_addmul_ui(u, v, 14UL, prec); fmprb_addmul_ui(u, t, 63UL, prec); fmprb_addmul_ui(u, x, 98UL, prec); fmprb_add_ui(u, u, 28UL, prec); fmprb_mul(u, u, u, prec); /* 16 (7+2x)^2 = 784 + 448x + 64x^2 */ fmprb_sub_ui(u, u, 784UL, prec); fmprb_submul_ui(u, x, 448UL, prec); fmprb_mul_2exp_si(t, t, 6); fmprb_sub(t, u, t, prec); fmprb_clear(u); fmprb_clear(v); }
void fmprb_sub_fmpz(fmprb_t z, const fmprb_t x, const fmpz_t y, slong prec) { fmprb_t t; fmprb_init(t); fmprb_set_fmpz(t, y); fmprb_sub(z, x, t, prec); fmprb_clear(t); }
void fmprb_sub_si(fmprb_t z, const fmprb_t x, slong y, slong prec) { fmprb_t t; fmprb_init(t); fmprb_set_si(t, y); fmprb_sub(z, x, t, prec); fmprb_clear(t); }
/* This gives some speedup for small lengths. */ static __inline__ void _fmprb_poly_rem_2(fmprb_ptr r, fmprb_srcptr a, long al, fmprb_srcptr b, long bl, long prec) { if (al == 2) { fmprb_mul(r + 0, a + 1, b + 0, prec); fmprb_sub(r + 0, a + 0, r + 0, prec); } else { _fmprb_poly_rem(r, a, al, b, bl, prec); } }
void zeta_ui_borwein_bsplit(fmprb_t x, ulong s, long prec) { zeta_bsplit_t sum; fmpr_t err; long wp, n; /* zeta(0) = -1/2 */ if (s == 0) { fmpr_set_si_2exp_si(fmprb_midref(x), -1, -1); fmpr_zero(fmprb_radref(x)); return; } if (s == 1) { printf("zeta_ui_borwein_bsplit: zeta(1)"); abort(); } n = prec / ERROR_B + 2; wp = prec + 30; zeta_bsplit_init(sum); zeta_bsplit(sum, 0, n + 1, n, s, 0, wp); /* A/Q3 - B/Q3 / (C/Q1) = (A*C - B*Q1) / (Q3*C) */ fmprb_mul(sum->A, sum->A, sum->C, wp); fmprb_mul(sum->B, sum->B, sum->Q1, wp); fmprb_sub(sum->A, sum->A, sum->B, wp); fmprb_mul(sum->Q3, sum->Q3, sum->C, wp); fmprb_div(sum->C, sum->A, sum->Q3, wp); fmpr_init(err); borwein_error(err, n); fmprb_add_error_fmpr(sum->C, err); fmpr_clear(err); /* convert from eta(s) to zeta(s) */ fmprb_div_2expm1_ui(x, sum->C, s - 1, wp); fmprb_mul_2exp_si(x, x, s - 1); zeta_bsplit_clear(sum); }
void fmprb_lgamma(fmprb_t y, const fmprb_t x, long prec) { int reflect; long r, n, wp; fmprb_t t, u; wp = prec + FLINT_BIT_COUNT(prec); gamma_stirling_choose_param_fmprb(&reflect, &r, &n, x, 0, 0, wp); /* log(gamma(x)) = log(gamma(x+r)) - log(rf(x,r)) */ fmprb_init(t); fmprb_init(u); fmprb_add_ui(t, x, r, wp); gamma_stirling_eval_fmprb(u, t, n, 0, wp); gamma_rising_fmprb_ui_bsplit(t, x, r, wp); fmprb_log(t, t, wp); fmprb_sub(y, u, t, prec); fmprb_clear(t); fmprb_clear(u); }
void gamma_stirling_eval_fmprb(fmprb_t s, const fmprb_t z, long nterms, int digamma, long prec) { fmprb_t b, t, logz, zinv, zinv2; fmpr_t err; long k, term_prec; double z_mag, term_mag; fmprb_init(b); fmprb_init(t); fmprb_init(logz); fmprb_init(zinv); fmprb_init(zinv2); fmprb_log(logz, z, prec); fmprb_ui_div(zinv, 1UL, z, prec); nterms = FLINT_MAX(nterms, 1); fmprb_zero(s); if (nterms > 1) { fmprb_mul(zinv2, zinv, zinv, prec); z_mag = fmpr_get_d(fmprb_midref(logz), FMPR_RND_UP) * 1.44269504088896; for (k = nterms - 1; k >= 1; k--) { term_mag = bernoulli_bound_2exp_si(2 * k); term_mag -= (2 * k - 1) * z_mag; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); if (prec > 2000) { fmprb_set_round(t, zinv2, term_prec); fmprb_mul(s, s, t, term_prec); } else fmprb_mul(s, s, zinv2, term_prec); gamma_stirling_coeff(b, k, digamma, term_prec); fmprb_add(s, s, b, term_prec); } if (digamma) fmprb_mul(s, s, zinv2, prec); else fmprb_mul(s, s, zinv, prec); } /* remainder bound */ fmpr_init(err); gamma_stirling_bound_fmprb(err, z, digamma ? 1 : 0, 1, nterms); fmprb_add_error_fmpr(s, err); fmpr_clear(err); if (digamma) { fmprb_neg(s, s); fmprb_mul_2exp_si(zinv, zinv, -1); fmprb_sub(s, s, zinv, prec); fmprb_add(s, s, logz, prec); } else { /* (z-0.5)*log(z) - z + log(2*pi)/2 */ fmprb_one(t); fmprb_mul_2exp_si(t, t, -1); fmprb_sub(t, z, t, prec); fmprb_mul(t, logz, t, prec); fmprb_add(s, s, t, prec); fmprb_sub(s, s, z, prec); fmprb_const_log_sqrt2pi(t, prec); fmprb_add(s, s, t, prec); } fmprb_clear(t); fmprb_clear(b); fmprb_clear(zinv); fmprb_clear(zinv2); fmprb_clear(logz); }
void fmpcb_calc_cauchy_bound(fmprb_t bound, fmpcb_calc_func_t func, void * param, const fmpcb_t x, const fmprb_t radius, long maxdepth, long prec) { long i, n, depth, wp; fmprb_t pi, theta, v, s1, c1, s2, c2, st, ct; fmpcb_t t, u; fmprb_t b; fmprb_init(pi); fmprb_init(theta); fmprb_init(v); fmprb_init(s1); fmprb_init(c1); fmprb_init(s2); fmprb_init(c2); fmprb_init(st); fmprb_init(ct); fmpcb_init(t); fmpcb_init(u); fmprb_init(b); wp = prec + 20; fmprb_const_pi(pi, wp); fmprb_zero_pm_inf(b); for (depth = 0, n = 16; depth < maxdepth; n *= 2, depth++) { fmprb_zero(b); /* theta = 2 pi / n */ fmprb_div_ui(theta, pi, n, wp); fmprb_mul_2exp_si(theta, theta, 1); /* sine and cosine of i*theta and (i+1)*theta */ fmprb_zero(s1); fmprb_one(c1); fmprb_sin_cos(st, ct, theta, wp); fmprb_set(s2, st); fmprb_set(c2, ct); for (i = 0; i < n; i++) { /* sine and cosine of 2 pi ([i,i+1]/n) */ /* since we use power of two subdivision points, the sine and cosine are monotone on each subinterval */ fmprb_union(fmpcb_realref(t), c1, c2, wp); fmprb_union(fmpcb_imagref(t), s1, s2, wp); fmpcb_mul_fmprb(t, t, radius, wp); fmpcb_add(t, t, x, prec); /* next angle */ fmprb_mul(v, c2, ct, wp); fmprb_mul(c1, s2, st, wp); fmprb_sub(c1, v, c1, wp); fmprb_mul(v, c2, st, wp); fmprb_mul(s1, s2, ct, wp); fmprb_add(s1, v, s1, wp); fmprb_swap(c1, c2); fmprb_swap(s1, s2); func(u, t, param, 1, prec); fmpcb_abs(v, u, prec); fmprb_add(b, b, v, prec); } fmprb_div_ui(b, b, n, prec); if (fmprb_is_exact(b) || fmpr_cmp(fmprb_radref(b), fmprb_midref(b)) < 0) break; } fmprb_set(bound, b); fmprb_clear(pi); fmprb_clear(theta); fmprb_clear(v); fmpcb_clear(t); fmpcb_clear(u); fmprb_clear(b); fmprb_clear(s1); fmprb_clear(c1); fmprb_clear(s2); fmprb_clear(c2); fmprb_clear(st); fmprb_clear(ct); }