**zeta.h** -- support for the zeta function =============================================================================== Integer zeta values ------------------------------------------------------------------------------- .. function:: void zeta_apery_bsplit(fmprb_t x, long prec) Sets *x* to Apery's constant `\zeta(3)`, computed by applying binary splitting to a hypergeometric series. .. function:: void zeta_ui_asymp(fmprb_t z, ulong s, long prec) Assuming `s \ge 2`, approximates `\zeta(s)` by `1 + 2^{-s}` along with a correct error bound. We use the following bounds: for `s > b`, `\zeta(s) - 1 < 2^{-b}`, and generally, `\zeta(s) - (1 + 2^{-s}) < 2^{2-\lfloor 3 s/2 \rfloor}`. .. function:: void zeta_ui_euler_product(fmprb_t z, ulong s, long prec) Computes `\zeta(s)` using the Euler product. This is fast only if *s* is large compared to the precision. Writing `P(a,b) = \prod_{a \le p \le b} (1 - p^{-s})`, we have `1/\zeta(s) = P(a,M) P(M+1,\infty)`. To bound the error caused by truncating the product at `M`, we write `P(M+1,\infty) = 1 - \epsilon(s,M)`. Since `0 < P(a,M) \le 1`, the absolute error for `\zeta(s)` is bounded by `\epsilon(s,M)`. According to the analysis in [Fil1992]_, it holds for all `s \ge 6` and `M \ge 1` that `1/P(M+1,\infty) - 1 \le f(s,M) \equiv 2 M^{1-s} / (s/2 - 1)`. Thus, we have `1/(1-\epsilon(s,M)) - 1 \le f(s,M)`, and expanding the geometric series allows us to conclude that `\epsilon(M) \le f(s,M)`. .. function:: void zeta_ui_bernoulli(fmprb_t x, ulong n, long prec) Computes `\zeta(n)` for even *n* via the corresponding Bernoulli number. .. function:: void zeta_ui_vec_borwein(fmprb_ptr z, ulong start, long num, ulong step, long prec) Evaluates `\zeta(s)` at `\mathrm{num}` consecutive integers *s* beginning with *start* and proceeding in increments of *step*. Uses Borwein's formula ([Bor2000]_, [GS2003]_), implemented to support fast multi-evaluation (but also works well for a single *s*). Requires `\mathrm{start} \ge 2`. For efficiency, the largest *s* should be at most about as large as *prec*. Arguments approaching *LONG_MAX* will cause overflows. One should therefore only use this function for *s* up to about *prec*, and then switch to the Euler product. The algorithm for single *s* is basically identical to the one used in MPFR (see [MPFR2012]_ for a detailed description). In particular, we evaluate the sum backwards to avoid storing more than one `d_k` coefficient, and use integer arithmetic throughout since it is convenient and the terms turn out to be slightly larger than `2^\mathrm{prec}`. The only numerical error in the main loop comes from the division by `k^s`, which adds less than 1 unit of error per term. For fast multi-evaluation, we repeatedly divide by `k^{\mathrm{step}}`. Each division reduces the input error and adds at most 1 unit of additional rounding error, so by induction, the error per term is always smaller than 2 units. .. function:: void zeta_ui_borwein_bsplit(fmprb_t x, ulong s, long prec) Computes `\zeta(s)` for arbitrary `s \ge 2` using a binary splitting implementation of Borwein's algorithm. This has quasilinear complexity with respect to the precision (assuming that `s` is fixed). We have .. math :: \zeta(s) = \frac{1}{d_n (1-2^{1-s})} \sum_{k=0}^{n-1} \frac{(-1)^k(d_n-d_k)}{(k+1)^s} + \gamma_n(s) where .. math :: d_k = n \sum_{i=0}^k \frac{(n+i-1)! 4^i}{(n-i)! (2i)!}. On the domain of interest, `|\gamma_n(s)| \le 3 / (3 + \sqrt 8)^n`. We write the summation as a system of first-order recurrences for `(s_k, d_k, t_k)` where `t_k = d_k - d_{k-1}`. This system is described by the matrix equation .. math :: \begin{pmatrix} s_{k+1} \\ d_{k+2} \\ t_{k+3} \end{pmatrix} = \begin{pmatrix} 1 & (-1)^k (k+1)^{-s} & 0 \\ 0 & 1 & 1 \\ 0 & 0 & u(k) \end{pmatrix} \begin{pmatrix} s_k \\ d_{k+1} \\ t_{k+2} \end{pmatrix}. We derive the binary splitting scheme by considering a product of an arbitrary pair in the chain `M_{n-1} M_{n-2} \cdots M_1 M_0`. This gives .. math :: \begin{pmatrix} 1 & A_L & B_L \\ 0 & 1 & C_L \\ 0 & 0 & D_L \end{pmatrix} \begin{pmatrix} 1 & A_R & B_R \\ 0 & 1 & C_R \\ 0 & 0 & D_R \end{pmatrix} = \begin{pmatrix} 1 & A_L+A_R & B_R+A_L C_R+B_L D_R \\ 0 & 1 & C_R+C_L D_R \\ 0 & 0 & D_L D_R \end{pmatrix}. The next step is to clear denominators. Instead of putting the whole matrix on a common denominator, we optimize by putting `C, D` on a denominator `Q_1` (the product of denominators of `u`) and `A, B` on a common denominator `Q_3 = Q_1 Q_2` (where `Q_2` is the product of `(k+1)^s` factors). This gives a small efficiency improvement. Thus, we have .. math :: \begin{pmatrix} 1 & \dfrac{A_L}{Q_{3L}} & \dfrac{B_L}{Q_{3L}} \\[3ex] 0 & 1 & \dfrac{C_L}{Q_{1L}} \\[3ex] 0 & 0 & \dfrac{D_L}{Q_{1L}} \end{pmatrix} \begin{pmatrix} 1 & \dfrac{A_R}{Q_{3R}} & \dfrac{B_R}{Q_{3R}} \\[3ex] 0 & 1 & \dfrac{C_R}{Q_{1R}} \\[3ex] 0 & 0 & \dfrac{D_R}{Q_{1R}} \end{pmatrix} = \begin{pmatrix} 1 & \dfrac{Q_{3L} A_R + A_L Q_{3R}}{Q_{3L} Q_{3R}} & \dfrac{Q_{3L} B_R + A_L C_R Q_{2R} + B_L D_R Q_{2R}}{Q_{3L} Q_{3R}} \\[3ex] 0 & 1 & \dfrac{Q_{1L} C_R + C_L D_R}{Q_{1L} Q_{1R}} \\[3ex] 0 & 0 & \dfrac{D_L D_R}{Q_{1L} Q_{1R}} \end{pmatrix}. In the final matrix, we note that `A / Q_3 = \sum_k (-1)^k (k+1)^{-s}`, and `C / Q_1 = d_n`. Thus `(1 / d_n) \sum_k (-1)^k (k+1)^{-s} (d_n - d_k)` is given by `A/Q_3 - (B/Q_3) / (C/Q_1) = (A C - B Q_1) / (Q_3 C)`. .. function:: void zeta_ui(fmprb_t x, ulong s, long prec) Computes `\zeta(s)` for nonnegative integer `s \ne 1`, automatically choosing an appropriate algorithm. .. function:: void zeta_ui_vec(fmprb_ptr x, ulong start, long num, long prec) .. function:: void zeta_ui_vec_even(fmprb_ptr x, ulong start, long num, long prec) .. function:: void zeta_ui_vec_odd(fmprb_ptr x, ulong start, long num, long prec) Computes `\zeta(s)` at num consecutive integers (respectively num even or num odd integers) beginning with `s = \mathrm{start} \ge 2`, automatically choosing an appropriate algorithm. Euler-Maclaurin summation ------------------------------------------------------------------------------- .. function:: void zeta_series_em_sum(fmpcb_ptr z, const fmpcb_t s, const fmpcb_t a, int deflate, ulong N, ulong M, long d, long prec) .. function:: void zeta_series(fmpcb_ptr z, const fmpcb_t s, const fmpcb_t a, int deflate, long d, long prec) Evaluates the truncated Euler-Maclaurin sum of order `N, M` for the length-*d* truncated Taylor series of the Hurwitz zeta function `\zeta(s,a)` at `s`, using a working precision of *prec* bits. With `a = 1`, this gives the usual Riemann zeta function. If *deflate* is nonzero, `\zeta(s,a) - 1/(s-1)` is evaluated (which permits series expansion at `s = 1`). The *fmpcb_zeta_series* function chooses default values for `N, M` using *fmpcb_zeta_series_em_choose_param*, targeting an absolute truncation error of `2^{-\operatorname{prec}}`. The Euler-Maclaurin (EM) formula states that .. math :: \sum_{k=N}^U f(k) = \int_N^U f(t) dt + \frac{1}{2} \left(f(N) + f(U)\right) + \sum_{k=1}^{M} \frac{B_{2k}}{(2k)!} \left( f^{(2k-1)}(U) - f^{(2k-1)}(N) \right) - \int_N^U \frac{\tilde B_{2M}(t)}{(2M)!} f^{(2M)}(t) dt where `f` is a sufficiently differentiable function (for example, analytic), `B_n` is a Bernoulli number, and `\tilde B_n(t) = B_n(t-\lfloor t\rfloor)` is a periodic Bernoulli polynomial. If `f` decreases sufficiently rapidly, the formula remains valid after letting `U \to \infty`. To evaluate the Hurwitz zeta function, we set `f(k) = (a + k)^{-s}`, giving `\zeta(s,a) = \sum_{k=0}^{N-1} f(k) + \sum_{k=N}^{\infty} f(k)`, where EM summation is applied to the right sum. By choosing `M` and `N` large enough, and taking the standard logarithm branch cut, the EM formula gives an analytic continuation of `\zeta(s,a)` to all `a, s \in \mathbb{C}` (except for poles at `s = 1` and `\mathrm{Re}(s) > 0, a = 0, -1, -2, \ldots`). In order to evaluate derivatives with respect to `s` of `\zeta(s,a)`, we substitute `s \to s + x \in \mathbb{C}[[x]]`. We choose `N` such that `\Re(a+N) > 0`. Then the first integral is well-defined for `s` with `\Re(s) > 1` and has the closed form .. math :: \int_N^{\infty} f(t) dt = \int_N^{\infty} (a + t)^{-s}dt = \frac{(a+N)^{1-s}}{s-1}, providing analytic continuation of this term with respect to `s`. Removing the singularity from this term also conveniently allows us to evaluate derivatives of `\zeta(s,a) - 1/(s-1)` at `s = 1`. The derivatives of `f(k)` are given by .. math :: f^{(r)}(k) = \frac{(-1)^r (s)_{r}}{(a+k)^{s+r}} where `(s)_{r} = s (s+1) \cdots (s+r-1)` denotes a rising factorial. Thus, the remainder integral becomes .. math :: R(s) = \int_N^{\infty} \frac{\tilde B_{2M}(t)}{(2M)!} \frac{(s)_{2M}}{(a+t)^{s+2M}} dt, valid when `\Re(a+N) > 0` and `\Re(s+2M-1) > 0`. We will use the stronger condition `\Re(a+N) > 1`. If `F = \sum_k f_k x^k \in \mathbb{C}[[x]]`, define `|F| = \sum_k |f_k| x^k` and `|F| \le |G|` if `\forall_k : |f_k| \le |g_k|`. It is easy to check that `|F + G| \le |F| + |G|` and `|FG| \le |F||G|`. With this notation, .. math :: |R(s+x)| = \left|\int_N^{\infty} \frac{\tilde B_{2M}(t)}{(2M)!} \frac{(s+x)_{2M}}{(a+t)^{s+x+2M}} dt\right| \le \int_N^{\infty} \left| \frac{\tilde B_{2M}(t)}{(2M)!} \frac{(s+x)_{2M}}{(a+t)^{s+x+2M}} \right| dt \le \frac{4 \left| (s+x)_{2M} \right|}{(2 \pi)^{2M}} \int_N^{\infty} \left| \frac{1}{(a+t)^{s+x+2M}} \right| dt where the fact that `|\tilde B_{2M}(x)| < 4 (2M)! / (2\pi)^{2M}` has been invoked. Thus it remains to bound the coefficients `R_k` satisfying .. math :: \int_N^{\infty} \left| \frac{1}{(a+t)^{s+x+2M}} \right| dt = \sum_k R_k x^k, \quad R_k = \int_N^{\infty} \frac{1}{k!} \left| \frac{\log(a+t)^k}{(a+t)^{s+2M}} \right| dt. Writing `a = \alpha + \beta i`, where by assumption `\alpha + t \ge \alpha + N \ge 1`, we have .. math :: |\log(\alpha + \beta i + t)| = \left|\log(\alpha + t) + \log\left( 1 + \frac{\beta i}{\alpha + t}\right) \right| \le \log(\alpha + t) + \left|\log\left(1 + \frac{\beta i}{\alpha+t}\right)\right| = \log(\alpha+t) + \left|\frac{1}{2}\log\left(1+\frac{\beta^2}{(\alpha+t)^2}\right) + i\tan^{-1}\left(\frac{\beta}{\alpha + t}\right)\right| \le \log(\alpha + t) + C where .. math :: C = \frac{1}{2}\log\left(1+\frac{\beta^2}{(\alpha+N)^2}\right) + \tan^{-1}\left(\frac{|\beta|}{\alpha+N}\right) \le \frac{\beta^2}{2 (\alpha+N)^2} + \frac{|\beta|}{(\alpha+N)}. Also writing `s = \sigma + \tau i`, where by assumption `\sigma + 2M > 1`, we have .. math :: \frac{1}{|(\alpha+\beta i+t)^{\sigma+\tau i + 2M}|} = \frac{e^{\tau \operatorname{arg}(\alpha+\beta i+t)}}{|\alpha+\beta i+t|^{\sigma+2M}} \le \frac{K}{(\alpha + t)^{\sigma+2M}} where `K = \exp(\max(0, \tau \tan^{-1}(\beta / (\alpha + N))))`. Finally, .. math :: R_k \le \frac{K}{k!} \, I_k(N+\alpha, \sigma + 2M, C) with the `K` and `C` defined above, where `I_k(A,B,C)` denotes the sequence of integrals .. math :: I_k(A,B,C) \equiv \int_A^{\infty} t^{-B} (C + \log t)^k dt which can be evaluated as .. math :: I_k(A,B,C) = \frac{L_k}{(B-1)^{k+1} A^{B-1}} where `L_0 = 1`, `L_k = k L_{k-1} + D^k` and `D = (B-1) (C + \log A)`. .. function:: void zeta_series_em_choose_param(fmpr_t bound, ulong * N, ulong * M, const fmpcb_t s, const fmpcb_t a, long d, long target, long prec) Chooses *N* and *M* using a default algorithm.