1 /*
2     Copyright (C) 2012 Fredrik Johansson
3 
4     This file is part of Arb.
5 
6     Arb is free software: you can redistribute it and/or modify it under
7     the terms of the GNU Lesser General Public License (LGPL) as published
8     by the Free Software Foundation; either version 2.1 of the License, or
9     (at your option) any later version.  See <http://www.gnu.org/licenses/>.
10 */
11 
12 #include "arb.h"
13 
14 /* With parameter n, the error is bounded by 3/(3+sqrt(8))^n */
15 #define ERROR_A 1.5849625007211561815 /* log2(3) */
16 #define ERROR_B 2.5431066063272239453 /* log2(3+sqrt(8)) */
17 
18 void mag_borwein_error(mag_t err, slong n);
19 
20 void
arb_zeta_ui_vec_borwein(arb_ptr z,ulong start,slong num,ulong step,slong prec)21 arb_zeta_ui_vec_borwein(arb_ptr z, ulong start, slong num, ulong step, slong prec)
22 {
23     slong j, k, s, n, wp;
24     fmpz_t c, d, t, u;
25     fmpz * zeta;
26     mag_t err;
27 
28     if (num < 1)
29         return;
30 
31     wp = prec + FLINT_BIT_COUNT(prec);
32     n = wp / 2.5431066063272239453 + 1;
33 
34     fmpz_init(c);
35     fmpz_init(d);
36     fmpz_init(t);
37     fmpz_init(u);
38     zeta = _fmpz_vec_init(num);
39 
40     fmpz_set_ui(c, 1);
41     fmpz_mul_2exp(c, c, 2 * n - 1);
42     fmpz_set(d, c);
43 
44     for (k = n; k > 0; k--)
45     {
46         /* divide by first k^s */
47         fmpz_ui_pow_ui(u, k, start);
48         fmpz_tdiv_q(t, d, u);
49         if (k % 2 == 0)
50             fmpz_neg(t, t);
51         fmpz_add(zeta, zeta, t);
52 
53         /* remaining k^s */
54         fmpz_ui_pow_ui(u, k, step);
55         for (j = 1; j < num; j++)
56         {
57             fmpz_tdiv_q(t, t, u);
58             fmpz_add(zeta + j, zeta + j, t);
59         }
60 
61         /* hypergeometric recurrence */
62         fmpz_mul2_uiui(c, c, k, 2 * k - 1);
63         fmpz_divexact2_uiui(c, c, 2 * (n - k + 1), n + k - 1);
64         fmpz_add(d, d, c);
65     }
66 
67     mag_init(err);
68     mag_borwein_error(err, n);
69 
70     for (k = 0; k < num; k++)
71     {
72         arb_ptr x = z + k;
73         s = start + step * k;
74 
75         arb_set_fmpz(x, zeta + k);
76         /* the error in each term in the main loop is < 2 */
77         mag_set_ui(arb_radref(x), 2 * n);
78         arb_div_fmpz(x, x, d, wp);
79 
80         /* mathematical error for eta(s), bounded by 3/(3+sqrt(8))^n */
81         mag_add(arb_radref(x), arb_radref(x), err);
82 
83         /* convert from eta(s) to zeta(s) */
84         arb_div_2expm1_ui(x, x, s - 1, wp);
85         arb_mul_2exp_si(x, x, s - 1);
86     }
87 
88     mag_clear(err);
89 
90     fmpz_clear(c);
91     fmpz_clear(d);
92     fmpz_clear(t);
93     fmpz_clear(u);
94     _fmpz_vec_clear(zeta, num);
95 }
96