1 /* Copyright (C) 2000 The PARI group.
2 This file is part of the PARI/GP package.
3
4 PARI/GP is free software; you can redistribute it and/or modify it under the
5 terms of the GNU General Public License as published by the Free Software
6 Foundation; either version 2 of the License, or (at your option) any later
7 version. It is distributed in the hope that it will be useful, but WITHOUT
8 ANY WARRANTY WHATSOEVER.
9
10 Check the License for details. You should have received a copy of it, along
11 with the package; see the file 'COPYING'. If not, write to the Free Software
12 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
13
14 /********************************************************************/
15 /** **/
16 /** MULTIPLE ZETA VALUES **/
17 /** **/
18 /********************************************************************/
19 #include "pari.h"
20 #include "paripriv.h"
21
22 /********************************************************************/
23 /** CONVERSIONS **/
24 /********************************************************************/
25 /* vecsmall to binary */
26 static long
fd(GEN evec,long a,long b)27 fd(GEN evec, long a, long b)
28 {
29 long i, s = 0;
30 for (i = a; i <= b; i++) s = evec[i] | (s << 1);
31 return s;
32 }
33 /* 2^(b-a+1) + fd(evec) */
34 static long
fd1(GEN evec,long a,long b)35 fd1(GEN evec, long a, long b)
36 {
37 long i, s = 1;
38 for (i = a; i <= b; i++) s = evec[i] | (s << 1);
39 return s;
40 }
41
42 /* m > 0 */
43 static GEN
mtoevec(GEN m)44 mtoevec(GEN m)
45 {
46 GEN e = vecsmall_append(binary_zv(m), 1);
47 e[1] = 0; return e;
48 }
49 static GEN
etoindex(GEN evec)50 etoindex(GEN evec) { return utoipos(fd1(evec, 2, lg(evec)-2)); }
51
52 /* dual of evec[1..l-1] */
53 static GEN
revslice(GEN evec,long l)54 revslice(GEN evec, long l)
55 {
56 GEN res = cgetg(l, t_VECSMALL);
57 long i;
58 for (i = 1; i < l; i++) res[i] = 1 - evec[l-i];
59 return res;
60 }
61
62 /* N.B. evec[ne] = 1 */
63 static GEN
etoa(GEN evec)64 etoa(GEN evec)
65 {
66 long c = 0, cold = 0, i = 1, l = lg(evec);
67 GEN avec = cgetg(l, t_VECSMALL);
68 while (++c < l)
69 if (evec[c] == 1) { avec[i++] = c - cold; cold = c; }
70 setlg(avec, i); return avec;
71 }
72
73 static GEN
atoe(GEN avec)74 atoe(GEN avec)
75 {
76 long i, j, l = lg(avec), n = zv_sum(avec);
77 GEN evec = zero_zv(n);
78 for (i = 1, j = 0; i < l; i++) { long a = avec[i]; j += a; evec[j] = 1; }
79 return evec;
80 }
81
82
83 /* Conversions: types are evec, avec, m (if evec=0y1, m=(1y)_2).
84 fl is respectively 0, 1, 2. Type of a is autodetected. */
85 static GEN
zetamultconvert_i(GEN a,long fl)86 zetamultconvert_i(GEN a, long fl)
87 {
88 long i, l;
89 if (fl < 0 || fl > 2) pari_err_FLAG("zetamultconvert");
90 switch(typ(a))
91 {
92 case t_INT:
93 if (signe(a) <= 0) pari_err_TYPE("zetamultconvert",a);
94 switch (fl)
95 {
96 case 0: a = mtoevec(a); break;
97 case 1: a = etoa(mtoevec(a)); break;
98 case 2: a = icopy(a); break;
99 }
100 break;
101 case t_VEC: case t_COL: case t_VECSMALL:
102 a = gtovecsmall(a);
103 l = lg(a);
104 if (a[1] == 0)
105 {
106 if (!a[l-1]) pari_err_TYPE("zetamultconvert", a);
107 for (i = 1; i < l; i++)
108 if (a[i] & ~1UL) pari_err_TYPE("zetamultconvert", a);
109 switch (fl)
110 {
111 case 1: a = etoa(a); break;
112 case 2: a = etoindex(a);
113 }
114 }
115 else
116 {
117 if (a[1] < 2) pari_err_TYPE("zetamultconvert", a);
118 for (i = 2; i < l; i++)
119 if (a[i] <= 0) pari_err_TYPE("zetamultconvert", a);
120 switch (fl)
121 {
122 case 0: a = atoe(a); break;
123 case 2: a = etoindex(atoe(a));
124 }
125 }
126 break;
127 default: pari_err_TYPE("zetamultconvert", a);
128 }
129 return a;
130 }
131 GEN
zetamultconvert(GEN a,long fl)132 zetamultconvert(GEN a, long fl)
133 {
134 pari_sp av = avma;
135 return gerepileuptoleaf(av, zetamultconvert_i(a, fl));
136 }
137
138 GEN
zetamultdual(GEN s)139 zetamultdual(GEN s)
140 {
141 pari_sp av = avma;
142 GEN e = zetamultconvert_i(s, 0);
143 return gerepileuptoleaf(av, etoa(revslice(e, lg(e))));
144 }
145
146 /********************************************************************/
147 /** AVEC -> LIST OF STAR AVECS **/
148 /********************************************************************/
149 /* all star avecs corresponding to given t_VECSMALL avec */
150 static GEN
allstar(GEN avec)151 allstar(GEN avec)
152 {
153 long i, la = lg(avec), K = 1 << (la - 2);
154 GEN w = cgetg(K + 1, t_VEC);
155
156 gel(w, 1) = avec;
157 for (i = 2; i < la; i++)
158 {
159 long L = 1 << (i - 2), j;
160 for (j = 1; j <= L; j++)
161 {
162 GEN u = gel(w,j), v;
163 long k, l = lg(u) - 1, ind = l - la + i;
164 gel(w, L + j) = v = cgetg(l, t_VECSMALL);
165 for (k = 1; k < ind; k++) v[k] = u[k];
166 v[ind] = u[ind] + u[ind + 1];
167 for (k = ind + 1; k < l; k++) v[k] = u[k+1];
168 }
169 }
170 return w;
171 }
172 /* same for multipolylogs */
173 static GEN
allstar2(GEN avec,GEN zvec)174 allstar2(GEN avec, GEN zvec)
175 {
176 long la = lg(avec), i, K = 1 << (la - 2);
177 GEN W = cgetg(K + 1, t_VEC), Z = cgetg(K + 1, t_VEC);
178
179 gel(W, 1) = avec;
180 gel(Z, 1) = zvec = gtovec(zvec);
181 for (i = 2; i < la; i++)
182 {
183 long L = 1 << (i - 2), j;
184 for (j = 1; j <= L; j++)
185 {
186 GEN u = gel(W, j), w, y = gel(Z, j), z;
187 long l = lg(u) - 1, ind = l - la + i, k;
188 w = cgetg(l, t_VECSMALL);
189 z = cgetg(l, t_VEC);
190 for (k = 1; k < ind; k++) { w[k] = u[k]; gel(z, k) = gel(y, k); }
191 w[ind] = u[ind] + u[ind + 1];
192 gel(z, ind) = gmul(gel(y, ind), gel(y, ind + 1));
193 for (k = ind + 1; k < l; k++) { w[k] = u[k+1]; gel(z, k) = gel(y, k+1); }
194 gel(W, L + j) = w;
195 gel(Z, L + j) = z;
196 }
197 }
198 return mkvec2(W, Z);
199 }
200
201 /**************************************************************/
202 /* ZAGIER & RADCHENKO'S ALGORITHM */
203 /**************************************************************/
204 /* accuracy 2^(-b); s << (b/log b)^2, l << b/sqrt(log b) */
205 static void
zparams(long * s,long * l,long b)206 zparams(long *s, long *l, long b)
207 {
208 double D = b * LOG10_2, E = 3*D/2 / log(3*D);
209 *s = (long)floor(E*E);
210 *l = (long)floor(sqrt(*s * log((double)*s)/2.));
211 }
212
213 static GEN
zetamult_Zagier(GEN avec,long bit,long prec)214 zetamult_Zagier(GEN avec, long bit, long prec)
215 {
216 pari_sp av;
217 GEN ze, z = NULL, b;
218 long h, r, n, s, l, t = lg(avec) - 1;
219
220 zparams(&s, &l, bit);
221 ze= cgetg(s + 1, t_VEC);
222 b = cgetg(l + 1, t_VEC);
223 for (r = 1; r <= s; r++) gel(ze,r) = cgetr(prec);
224 for (r = 1; r <= l; r++) { gel(b,r) = cgetr(prec); affur(0,gel(b,r)); }
225 affur(1, gel(b,1)); av = avma;
226 for (r = 1, h = -1; r <= t; r++)
227 {
228 long m, j = avec[r];
229 GEN q;
230
231 h += j - 1; z = gen_0;
232 q = h? invr(itor(powuu(s,h), prec)): real_1(prec);
233 for (m = 1; m <= l; m++)
234 {
235 pari_sp av2;
236 GEN S = gel(b, m), C;
237 q = divru(q, s); av2 = avma;
238 C = binomialuu(h + m, m);
239 for (n = 1; n < m; n++)
240 { /* C = binom(h+m, m-n+1) */
241 S = gsub(S, mulir(C, gel(b, n)));
242 C = diviuexact(muliu(C, m-n+1), h+n);
243 }
244 affrr(divru(S, h+m), gel(b,m)); set_avma(av2);
245 z = gadd(z, gmul(gel(b, m), q));
246 }
247 for (m = s; m >= 1; m--)
248 {
249 GEN z1 = r == 1? ginv(powuu(m,j)): gdiv(gel(ze, m), powuu(m,j));
250 z1 = gadd(z, z1);
251 affrr(z, gel(ze, m)); z = z1;
252 }
253 set_avma(av);
254 }
255 return z;
256 }
257
258 /* Compute t-mzvs; slower than Zagier's code for t=0 */
259 static GEN
zetamult_interpolate2_i(GEN avec,GEN t,long prec)260 zetamult_interpolate2_i(GEN avec, GEN t, long prec)
261 {
262 pari_sp av;
263 GEN a, b, ze, _1;
264 long i, j, n, s, l;
265
266 zparams(&s, &l, prec2nbits(prec));
267 n = lg(avec) - 1;
268 a = zeromatcopy(n + 1, l);
269 b = zerovec(l + 1);
270 for (i = 1; i <= n; i++)
271 {
272 long h = avec[n + 1 - i];
273 if (i == 1) gel(b, h) = gen_1;
274 else
275 for (j = l + 1; j >= 1; j--)
276 {
277 if (j <= h) gel(b, j) = gen_0;
278 else gel(b, j) = gadd(gcoeff(a, i, j-h), gmul(t, gel(b, j-h)));
279 }
280 gcoeff(a, i+1, 1) = gel(b, 2); /* j = 1 */
281 for (j = 2; j <= l; j++)
282 { /* b[j+1] - sum_{0 <= u < j-1} binom(j,u) a[i+1,u+1]*/
283 pari_sp av = avma;
284 GEN S = gel(b, j + 1);
285 S = gsub(S, gcoeff(a, i+1, 1)); /* u = 0 */
286 if (j > 2) S = gsub(S, gmulgs(gcoeff(a, i+1, 2), j)); /* u = 1 */
287 if (j >= 4)
288 {
289 GEN C = utoipos(j*(j-1) / 2);
290 long u, U = (j-1)/2;
291 for (u = 2; u <= U; u++)
292 { /* C = binom(j, u) = binom(j, j-u) */
293 GEN A = gadd(gcoeff(a, i+1, u+1), gcoeff(a, i+1, j-u+1));
294 S = gsub(S, gmul(C, A));
295 C = diviuexact(muliu(C, j-u), u+1);
296 }
297 if (!odd(j)) S = gsub(S, gmul(C, gcoeff(a,i+1, j/2+1)));
298 }
299 gcoeff(a, i+1, j) = gerepileupto(av, gdivgs(S, j));
300 }
301 }
302 _1 = real_1(prec + EXTRAPRECWORD); av = avma;
303 ze = cgetg(n+1, t_VEC);
304 for (i = 1; i <= n; i++)
305 {
306 GEN S = gdivgs(gcoeff(a, n+2-i, 1), s), sj = utoipos(s);
307 for (j = 2; j <= l; j++)
308 {
309 sj = muliu(sj, s); /* = s^j */
310 S = gadd(S, gdiv(gcoeff(a, n+2-i, j), sj));
311 }
312 gel(ze, i) = S;
313 }
314 for (i = s; i >= 1; i--)
315 {
316 GEN b0 = divri(_1, powuu(i, avec[n])), z;
317 z = gel(ze,n); gel(ze,n) = gadd(z, b0);
318 for (j = n-1; j >= 1; j--)
319 {
320 b0 = gdiv(gadd(gmul(t, b0), z), powuu(i, avec[j]));
321 z = gel(ze,j); gel(ze,j) = gadd(gel(ze,j), b0);
322 }
323 if (gc_needed(av, 1))
324 {
325 if (DEBUGMEM>1) pari_warn(warnmem,"zetamult: i = %ld", i);
326 ze = gerepilecopy(av, ze);
327 }
328 }
329 return gel(ze, 1);
330 }
331
332 /********************************************************************/
333 /** AKHILESH ALGORITHM **/
334 /********************************************************************/
335 /* a t_VECSMALL, upper bound for -log2(zeta(a)) */
336 static long
log2zeta_bound(GEN a)337 log2zeta_bound(GEN a)
338 { return ceil(-dbllog2(zetamult_Zagier(a, 32, LOWDEFAULTPREC))); }
339 /* ibin[n+1] = 1 / binom(2n, n) as a t_REAL */
340 static void
get_ibin(GEN * pibin,GEN * pibin1,long N,long prec)341 get_ibin(GEN *pibin, GEN *pibin1, long N, long prec)
342 {
343 GEN ibin, ibin1;
344 long n;
345 *pibin = ibin = cgetg(N + 2, t_VEC);
346 *pibin1= ibin1= cgetg(N + 2, t_VEC);
347 gel(ibin,1) = gel(ibin1,1) = gen_0; /* unused */
348 gel(ibin,2) = gel(ibin1,2) = real2n(-1,prec);
349 for (n = 2; n <= N; n++)
350 {
351 gel(ibin, n+1) = divru(mulru(gel(ibin, n), n), 4*n-2);
352 gel(ibin1, n+1) = divru(gel(ibin, n+1), n);
353 }
354 }
355 /**************************************************************/
356 /* ALL MZV's */
357 /**************************************************************/
358
359 /* Generalization to Multiple Polylogarithms.
360 The basic function is polylogmult which takes two arguments
361 avec, as above, and zvec, the vector of z_j, and the result
362 is $\sum_{n_1>n_2>...>n_r>0}z_1^{n_1}...z_r^{n_r}/(n_1^a_1...n_r^{a_r})$. */
363
364 /* Given admissible evec = xe_2....e_{k-1}y, (k>=2), compute a,b,v such that
365 evec = x{1}_{a-1}v{0}_{b-1}y with v empty or admissible.
366 Input: vector w=evec
367 Output: v=wmid, wini, wfin */
368 static void
findabvgen(GEN evec,long _0,long _1,GEN * pwmid,GEN * pwini,GEN * pwfin,long * pa,long * pb)369 findabvgen(GEN evec, long _0, long _1, GEN *pwmid, GEN *pwini, GEN *pwfin,
370 long *pa, long *pb)
371 {
372 long s = lg(evec) - 1, m, a, b, j, x = evec[1], y = evec[s];
373 GEN wmid, wini, wfin;
374 if (s == 2)
375 {
376 *pwmid = cgetg(1, t_VECSMALL);
377 *pwini = mkvecsmall(x);
378 *pwfin = mkvecsmall(y);
379 *pa = *pb = 1; return;
380 }
381 a = s - 1;
382 for (j = 1; j <= s - 2; j++) if (evec[j + 1] != _1) { a = j; break; }
383 *pa = a;
384 b = s - 1;
385 for (j = s - 2; j >= 1; j--) if (evec[j + 1] != _0) { b = s - 1 - j; break; }
386 *pb = b;
387
388 *pwmid = wmid = a+b < s? vecslice(evec, a+1, s-b): cgetg(1, t_VECSMALL);
389 m = lg(wmid) - 1;
390 *pwini = wini = cgetg(a + m + 1, t_VECSMALL);
391 wini[1] = x; for (j = 2; j <= a; j++) wini[j] = _1;
392 for (; j <= a + m; j++) wini[j] = wmid[j-a];
393 *pwfin = wfin = cgetg(b + m + 1, t_VECSMALL);
394 for (j = 1; j <= m; j++) wfin[j] = wmid[j];
395 for (; j < b + m; j++) wfin[j] = _0;
396 wfin[j] = y;
397 }
398
399 /* y != 0,1 */
400 static GEN
filllg1(GEN ibin1,GEN r1,GEN y,long N,long prec)401 filllg1(GEN ibin1, GEN r1, GEN y, long N, long prec)
402 {
403 GEN v, y1 = gsubgs(gmulsg(2, y), 1), y3 = gmul(y, gsubsg(1, y));
404 long n;
405
406 v = cgetg(N + 2, t_VEC); gel(v, N + 1) = gen_0;
407 if (gcmpgs(gnorm(y3),1) > 0)
408 {
409 GEN y2 = gdiv(r1, y3);
410 for (n = N; n >= 1; n--)
411 {
412 pari_sp av2 = avma;
413 GEN z = gmul(y2, gsub(gel(v, n+1), gmul(y1, gel(ibin1, n+1))));
414 gel(v, n) = gerepileupto(av2, z);
415 }
416 }
417 else
418 {
419 pari_sp av0 = avma;
420 gel(v, 1) = gerepileupto(av0, glog(gdiv(y, gsubgs(y, 1)), prec));
421 for (n = 1; n < N; n++)
422 {
423 pari_sp av2 = avma;
424 GEN z = gadd(gmul(y3, gel(v, n)), gmul(y1, gel(ibin1, n+1)));
425 gel(v, n + 1) = gerepileupto(av2, z);
426 }
427 }
428 return v;
429 }
430 static GEN
fillrec(hashtable * H,GEN evec,long _0,long _1,GEN X,GEN pab,GEN r1,long N,long prec)431 fillrec(hashtable *H, GEN evec, long _0, long _1, GEN X, GEN pab, GEN r1,
432 long N, long prec)
433 {
434 long n, a, b, s, x0;
435 GEN xy1, x, y, r, wmid, wini, wfin, mid, ini, fin;
436 hashentry *ep = hash_search(H, evec);
437
438 if (ep) return (GEN)ep->val;
439 findabvgen(evec, _0, _1, &wmid, &wini, &wfin, &a, &b);
440 x = gel(X, evec[1]); s = lg(evec)-1; /* > 1 */
441 y = gel(X, evec[s]);
442 mid = fillrec(H, wmid, _0, _1, X, pab, r1, N, prec);
443 ini = fillrec(H, wini, _0, _1, X, pab, r1, N, prec);
444 fin = fillrec(H, wfin, _0, _1, X, pab, r1, N, prec);
445 if (evec[1] == _0) { x0 = 1; xy1 = gdiv(r1, y); }
446 else { x0 = 0; xy1 = gdiv(r1, gmul(gsubsg(1, x), y)); }
447 r = cgetg(N+2, t_VEC); gel(r, N+1) = gen_0;
448 for (n = N; n > 1; n--)
449 {
450 pari_sp av = avma;
451 GEN t = gmul(gel(ini, n+1), gmael(pab, n, a));
452 GEN u = gadd(gmul(gel(fin, n+1), gmael(pab, n, b)), gel(mid, n+1));
453 GEN v = gdiv(x0? gadd(t, u): gsub(t, u), gmael(pab, n, a+b));
454 gel(r, n) = gerepileupto(av, gmul(xy1, gadd(gel(r, n+1), v)));
455 }
456 { /* n = 1 */
457 pari_sp av = avma;
458 GEN t = gel(ini, 2), u = gadd(gel(fin, 2), gel(mid, 2));
459 GEN v = x0? gadd(t, u): gsub(t, u);
460 gel(r,1) = gerepileupto(av, gmul(xy1, gadd(gel(r,2), v)));
461 }
462 hash_insert(H, (void*)evec, (void*)r); return r;
463 }
464
465 static GEN
aztoe(GEN avec,GEN zvec,long prec)466 aztoe(GEN avec, GEN zvec, long prec)
467 {
468 GEN y, E, u = subsr(1, real2n(10-prec2nbits(prec), LOWDEFAULTPREC));
469 long i, l = lg(avec);
470
471 E = cgetg(l, t_VEC); if (l == 1) return E;
472 y = gen_1;
473 for (i = 1; i < l; i++)
474 {
475 long a = avec[i];
476 GEN e, zi = gel(zvec, i);
477 if (a <= 0 || (a == 1 && i == 1 && gequal1(zi)))
478 pari_err_TYPE("polylogmult [divergent]", avec);
479 if (gequal0(zi)) return NULL;
480 gel(E, i) = e = zerovec(a);
481 gel(e, a) = y = gdiv(y, zi);
482 if (gcmp(gnorm(y), u) < 0) pari_err_TYPE("polylogmult [divergent]", zvec);
483 }
484 return shallowconcat1(E);
485 }
486
487 /***********************************************************/
488 /* Special case of zvec = [1,1,...], i.e., zetamult. */
489 /***********************************************************/
490 static void
findabvgens(GEN evec,GEN * pwmid,GEN * pwini,GEN * pwfin,long * pa,long * pb)491 findabvgens(GEN evec, GEN *pwmid, GEN *pwini, GEN *pwfin, long *pa, long *pb)
492 {
493 GEN wmid, wini, wfin;
494 long s = lg(evec) - 1, a, b, j, m;
495 if (s == 2)
496 {
497 *pwmid = cgetg(1, t_VECSMALL);
498 *pwini = mkvecsmall(0);
499 *pwfin = mkvecsmall(1);
500 *pa = *pb = 1; return;
501 }
502 a = s - 1;
503 for (j = 1; j <= s - 2; j++) if (!evec[j + 1]) { a = j; break; }
504 *pa = a;
505 b = s - 1;
506 for (j = s - 2; j >= 1; j--) if (evec[j + 1]) { b = s - 1 - j; break; }
507 *pb = b;
508
509 *pwmid = wmid = a+b < s? vecslice(evec, a+1, s-b): cgetg(1, t_VECSMALL);
510 m = lg(wmid) - 1;
511 *pwini = wini = cgetg(a + m + 1, t_VECSMALL);
512 wini[1] = 0; for (j = 2; j <= a; j++) wini[j] = 1;
513 for (; j <= a + m; j++) wini[j] = wmid[j-a];
514 *pwfin = wfin = cgetg(b + m + 1, t_VECSMALL);
515 for (j = 1; j <= m; j++) wfin[j] = wmid[j];
516 for (; j < b + m; j++) wfin[j] = 0;
517 wfin[j] = 1;
518 }
519 static GEN
fillrecs(hashtable * H,GEN evec,GEN pab,long N,long prec)520 fillrecs(hashtable *H, GEN evec, GEN pab, long N, long prec)
521 {
522 long n, a, b;
523 GEN r, wmid, wini, wfin, mid, ini, fin;
524 hashentry *ep = hash_search(H, evec);
525
526 if (ep) return (GEN)ep->val;
527 findabvgens(evec, &wmid, &wini, &wfin, &a, &b);
528 mid = fillrecs(H, wmid, pab, N, prec);
529 ini = fillrecs(H, wini, pab, N, prec);
530 fin = fillrecs(H, wfin, pab, N, prec);
531 r = cgetg(N + 2, t_VEC); gel(r, N+1) = gen_0;
532 for (n = N; n > 1; n--)
533 {
534 GEN z = cgetr(prec);
535 pari_sp av = avma;
536 GEN t = mpmul(gel(ini, n+1), gmael(pab, n, a));
537 GEN u = mpadd(mpmul(gel(fin, n+1), gmael(pab, n, b)), gel(mid,n+1));
538 GEN v = mpdiv(mpadd(t, u), gmael(pab, n, a+b));
539 mpaff(mpadd(gel(r, n+1), v), z); set_avma(av); gel(r,n) = z;
540 }
541 { /* n = 1 */
542 GEN z = cgetr(prec);
543 pari_sp av = avma;
544 GEN t = gel(ini,2), u = mpadd(gel(fin,2), gel(mid,2)), v = mpadd(t, u);
545 mpaff(mpadd(gel(r, 2), v), z); set_avma(av); gel(r,1) = z;
546 }
547 hash_insert(H, (void*)evec, (void*)r); return r;
548 }
549 /* [n, ..., n^k] */
550 static GEN
powersu(ulong n,long k)551 powersu(ulong n, long k)
552 {
553 GEN v, gn = utoipos(n);
554 long i, l = k+1;
555 v = cgetg(l, t_VEC); gel(v,1) = gn;
556 for (i = 2; i < l; i++) gel(v,i) = muliu(gel(v,i-1), n);
557 return v;
558 }
559 /* n^a = pab[n][a] */
560 static GEN
get_pab(long N,long k)561 get_pab(long N, long k)
562 {
563 GEN v = cgetg(N+1, t_VEC);
564 long j;
565 gel(v, 1) = gen_0; /* not needed */
566 for (j = 2; j <= N; j++) gel(v, j) = powersu(j, k);
567 return v;
568 }
569 static hashtable *
zetamult_hash(long _0,long _1,GEN ibin,GEN ibin1)570 zetamult_hash(long _0, long _1, GEN ibin, GEN ibin1)
571 {
572 hashtable *H = hash_create(4096, (ulong(*)(void*))&hash_zv,
573 (int(*)(void*,void*))&zv_equal, 1);
574 hash_insert(H, (void*)cgetg(1, t_VECSMALL), (void*)ibin);
575 hash_insert(H, (void*)mkvecsmall(_0), (void*)ibin1);
576 hash_insert(H, (void*)mkvecsmall(_1), (void*)ibin1); return H;
577 }
578 /* Akhilesh recursive algorithm, #a > 1;
579 * e t_VECSMALL, prec final precision, bit required bitprecision */
580 static GEN
zetamult_Akhilesh(GEN e,long bit,long prec)581 zetamult_Akhilesh(GEN e, long bit, long prec)
582 {
583 long k = lg(e) - 1, N = 1 + bit/2, prec2 = nbits2prec(bit);
584 GEN r, pab, ibin, ibin1;
585 hashtable *H;
586
587 get_ibin(&ibin, &ibin1, N, prec2);
588 pab = get_pab(N, k);
589 H = zetamult_hash(0, 1, ibin, ibin1);
590 r = fillrecs(H, e, pab, lg(pab)-1, prec2);
591 if (DEBUGLEVEL) err_printf("polylogmult: k = %ld, %ld nodes\n", k, H->nb);
592 return gprec_wtrunc(gel(r,1), prec);
593 }
594 /* evec t_VEC */
595 static GEN
zetamultevec(GEN evec,long prec)596 zetamultevec(GEN evec, long prec)
597 {
598 pari_sp av = avma;
599 double *x, *y, z = 0;
600 long i, j, l, lH, bitprec, prec2, N, _0 = 0, _1 = 0, k = lg(evec) - 1;
601 GEN r1, r, pab, ibin, ibin1, X, Evec, v;
602 hashtable *H;
603
604 if (k == 0) return gen_1;
605 v = vec_equiv(evec); l = lg(v);
606 Evec = cgetg(k+1, t_VECSMALL);
607 X = cgetg(l + 2, t_VEC); /* our alphabet */
608 for (i = lH = 1; i < l; i++)
609 {
610 GEN vi = gel(v,i), xi = gel(evec, vi[1]);
611 long li = lg(vi);
612 gel(X,i) = xi;
613 if (!_0 && gequal0(xi)) _0 = i;
614 else if (!_1 && gequal1(xi)) _1 = i;
615 for (j = 1; j < li; j++) Evec[vi[j]] = i;
616 }
617 /* add 0,1 if needed */
618 if (!_0) { gel(X, i) = gen_0; _0 = i++; }
619 if (!_1) { gel(X, i) = gen_1; _1 = i++; }
620 l = i; setlg(X, l);
621 av = avma;
622 x = (double*)stack_malloc_align(l * sizeof(double), sizeof(double));
623 y = (double*)stack_malloc_align(l * sizeof(double), sizeof(double));
624 for (j = 1; j < l; j++)
625 {
626 GEN t = gel(X,j);
627 x[j] = (j == _1)? 0: -dbllog2(gsubsg(1, t));
628 y[j] = (j == _0)? 0: -dbllog2(t);
629 }
630 for (i = 1; i < l; i++)
631 for (j = i+1; j < l; j++) z = maxdd(z, x[i] + y[j]);
632 set_avma(av);
633 if (z >= 2) pari_err_IMPL("polylogmult in this range");
634 bitprec = prec2nbits(prec) + 64*(1 + (k >> 5));
635 N = 1 + bitprec/ (2 - z);
636 bitprec += z * N;
637 prec2 = nbits2prec(bitprec);
638 X = gprec_wensure(X, prec2);
639 get_ibin(&ibin, &ibin1, N, prec2);
640 pab = get_pab(N, k);
641 H = zetamult_hash(_0, _1, ibin, ibin1);
642 r1 = real_1(prec2);
643 for (i = 1; i < l; i++)
644 if (i != _0 && i != _1)
645 hash_insert(H, mkvecsmall(i), filllg1(ibin1, r1, gel(X,i), N, prec2));
646 r = fillrec(H, Evec, _0, _1, X, pab, r1, N, prec2);
647 if (DEBUGLEVEL) err_printf("polylogmult: k = %ld, %ld nodes\n", k, H->nb);
648 return gprec_wtrunc(gel(r,1), prec);
649 }
650
651 /* a t_VECSMALL */
652 static GEN
zetamult_i(GEN a,long prec)653 zetamult_i(GEN a, long prec)
654 {
655 long r = lg(a)-1, k, bit;
656 if (r == 0) return gen_1;
657 if (r == 1) return szeta(a[1], prec);
658 bit = prec2nbits(prec);
659 if (bit <= 128)
660 return zetamult_Zagier(a, bit, prec + EXTRAPRECWORD);
661 k = zv_sum(a);
662 if (((double)r) / (k*k) * bit / log((double)10*bit) < 0.5)
663 return zetamult_Zagier(a, bit, prec + EXTRAPRECWORD);
664 bit += maxss(log2zeta_bound(a), 64);
665 return zetamult_Akhilesh(atoe(a), bit, prec);
666 }
667 GEN
zetamult(GEN s,long prec)668 zetamult(GEN s, long prec)
669 {
670 pari_sp av0 = avma, av;
671 GEN z, avec, r = cgetr(prec);
672
673 av = avma; avec = zetamultconvert_i(s,1);
674 if (lg(avec) == 1) return gc_const(av0, gen_1);
675 z = zetamult_i(avec, prec); affrr(z, r); return gc_const(av, r);
676 }
677
678 /* If star = NULL: MZV, otherwise Yamamoto interpolation (MZSV for t=1) */
679 GEN
zetamult_interpolate(GEN s,GEN t,long prec)680 zetamult_interpolate(GEN s, GEN t, long prec)
681 {
682 pari_sp av = avma, av2;
683 long i, k, l, la, bit;
684 GEN avec, v, V;
685
686 if (!t) return zetamult(s, prec);
687 avec = zetamultconvert_i(s, 1); k = zv_sum(avec);
688 bit = prec2nbits(prec);
689 if (bit <= 128 || k > 20 || (bit >> k) < 4)
690 return zetamult_interpolate2_i(vecsmall_reverse(avec), t, prec);
691 v = allstar(avec); l = lg(v); la = lg(avec);
692 V = cgetg(la, t_VEC);
693 for (i = 1; i < la; i++)
694 { gel(V,i) = cgetr(prec + EXTRAPRECWORD); affur(0, gel(V,i)); }
695 av2 = avma;
696 for (i = 1; i < l; i++, set_avma(av2))
697 {
698 GEN a = gel(v,i); /* avec */
699 long n = lg(a)-1; /* > 0 */
700 affrr(addrr(gel(V,n), zetamult_i(a, prec)), gel(V,n));
701 }
702 return gerepileupto(av, poleval(vecreverse(V),t));
703 }
704
705
706 GEN
polylogmult(GEN a,GEN z,long prec)707 polylogmult(GEN a, GEN z, long prec)
708 {
709 pari_sp av = avma;
710 if (!z) return zetamult(a, prec);
711 switch(typ(a))
712 {
713 case t_VEC:
714 case t_COL: a = gtovecsmall(a); break;
715 case t_VECSMALL: break;
716 default: pari_err_TYPE("polylogmult", a);
717 return NULL;/*LCOV_EXCL_LINE*/
718 }
719 switch (typ(z))
720 {
721 case t_INT: case t_FRAC: case t_REAL: case t_COMPLEX:
722 z = mkvec(z); break;
723 case t_VEC: case t_COL: break;
724 case t_VECSMALL: z = zv_to_ZV(z); break;
725 default: pari_err_TYPE("polylogmult [z]", z);
726 }
727 if (lg(z) != lg(a))
728 pari_err_TYPE("polylogmult [#s != #z]", mkvec2(a,z));
729 return gerepilecopy(av, zetamultevec(aztoe(a,z,prec), prec));
730 }
731
732 GEN
polylogmult_interpolate(GEN s,GEN zvec,GEN t,long prec)733 polylogmult_interpolate(GEN s, GEN zvec, GEN t, long prec)
734 {
735 pari_sp av = avma;
736 GEN V, avec, A, AZ, Z;
737 long i, la, l;
738
739 if (!t) return polylogmult(s, zvec, prec);
740 if (!zvec) return zetamult_interpolate(s, t, prec);
741 avec = zetamultconvert_i(s, 1); la = lg(avec);
742 AZ = allstar2(avec, zvec);
743 A = gel(AZ, 1); l = lg(A);
744 Z = gel(AZ, 2); V = zerovec(la-1);
745 for (i = 1; i < l; i++)
746 {
747 pari_sp av2 = avma;
748 GEN a = gel(A,i), e = aztoe(a, gel(Z,i), prec);
749 long n = lg(a)-1; /* > 0 */
750 gel(V,n) = gerepileupto(av2, gadd(gel(V,n), zetamultevec(e, prec)));
751 }
752 return gerepileupto(av, poleval(vecreverse(V),t));
753 }
754
755 /**************************************************************/
756 /* ALL MZV's */
757 /**************************************************************/
758
759 /* Given admissible evec w = 0e_2....e_{k-1}1, compute a,b,v such that
760 * w=0{1}_{b-1}v{0}_{a-1}1 with v empty or admissible.
761 * Input: binary vector evec */
762 static void
findabv(GEN w,long * pa,long * pb,long * pminit,long * pmmid,long * pmfin)763 findabv(GEN w, long *pa, long *pb, long *pminit, long *pmmid, long *pmfin)
764 {
765 long le = lg(w) - 2;
766 if (le == 0)
767 {
768 *pa = 1;
769 *pb = 1;
770 *pminit = 2;
771 *pmfin = 2;
772 *pmmid = 1;
773 }
774 else
775 {
776 long a, b, j, lv;
777 for (j = 1; j <= le; j++)
778 if (!w[j+1]) break;
779 *pb = b = j;
780 for (j = le; j >= 1; j--)
781 if (w[j+1]) break;
782 *pa = a = le + 1 - j;
783 lv = le + 2 - a - b;
784 if (lv > 0)
785 {
786 long v = fd(w, b + 1, le - a + 2), u = v + (1 << (lv-1));
787 *pminit = (((1 << b) - 1) << (lv - 1)) + (v/2) + 2;
788 *pmfin = (u << (a - 1)) + 2;
789 *pmmid = (u >> 1) + 2;
790 }
791 else
792 {
793 *pminit = (1 << (b - 1)) + 1;
794 *pmfin = (a == 1) ? 2 : (1 << (a - 2)) + 2;
795 *pmmid = 1;
796 }
797 }
798 }
799
800 /* Returns L:
801 * L[1] contains zeta(emptyset)_{n-1,n-1},
802 * L[2] contains zeta({0})_{n-1,n-1}=zeta({1})_{n-1,n-1} for n >= 2,
803 * L[m+2][n] : 1 <= m < 2^{k-2}, 1 <= n <= N + 1
804 * contains zeta(w)_{n-1,n-1}, w corresponding to m,n
805 * L[m+2] : 2^{k-2} <= m < 2^{k-1} contains zeta(w), w corresponding to m
806 (code: w=0y1 iff m=1y). */
807 static GEN
fillL(long k,long bitprec)808 fillL(long k, long bitprec)
809 {
810 long N = 1 + bitprec/2, prec = nbits2prec(bitprec);
811 long s, j, n, m, K = 1 << (k - 1), K2 = K/2;
812 GEN p1, p2, pab = get_pab(N, k), L = cgetg(K + 2, t_VEC);
813
814 get_ibin(&gel(L,1), &gel(L,2), N, prec);
815 for (m = 1; m < K2; m++)
816 {
817 gel(L, m+2) = p1 = cgetg(N+1, t_VEC);
818 for (n = 1; n < N; n++) gel(p1, n) = cgetr(prec);
819 gel(p1, n) = gen_0;
820 }
821 for (m = K2; m < K; m++) gel(L, m+2) = utor(0, prec);
822 for (s = 2; s <= k; s++)
823 { /* Assume length evec < s filled */
824 /* If evec = 0e_2...e_{s-1}1 then m = (1e_2...e_{s-1})_2 */
825 GEN w = cgetg(s, t_VECSMALL);
826 long M = 1 << (s - 2);
827 pari_sp av = avma;
828 for (m = M; m < 2*M; m++)
829 {
830 GEN pinit, pfin, pmid;
831 long comp, a, b, mbar, minit, mfin, mmid, mc;
832 p1 = gel(L, m + 2);
833 for (j = s - 1, mc = m, mbar = 1; j >= 2; j--, mc >>= 1)
834 {
835 w[j] = mc & 1;
836 mbar = (1 - w[j]) | (mbar << 1);
837 }
838 /* m, mbar are dual; handle smallest, copy the other */
839 comp = mbar - m; if (comp < 0) continue; /* m > mbar */
840 if (comp)
841 {
842 p2 = gel(L, mbar + 2);
843 setisclone(p2); /* flag as dual */
844 }
845 else
846 p2 = NULL; /* no copy needed if m = mbar */
847 findabv(w, &a,&b,&minit,&mmid,&mfin);
848 pinit= gel(L, minit);
849 pfin = gel(L, mfin);
850 pmid = gel(L, mmid);
851 for (n = N-1; n > 1; n--, set_avma(av))
852 {
853 GEN t = mpmul(gel(pinit,n+1), gmael(pab, n, b));
854 GEN u = mpmul(gel(pfin, n+1), gmael(pab, n, a));
855 GEN v = gel(pmid, n+1), S = s < k ? gel(p1, n+1): p1;
856 S = mpadd(S, mpdiv(mpadd(mpadd(t, u), v), gmael(pab, n, a+b)));
857 mpaff(S, s < k ? gel(p1, n) : p1);
858 if (p2 && s < k) mpaff(S, gel(p2, n));
859 }
860 { /* n = 1: same formula simplifies */
861 GEN t = gel(pinit,2), u = gel(pfin,2), v = gel(pmid,2);
862 GEN S = s < k ? gel(p1,2): p1;
863 S = mpadd(S, mpadd(mpadd(t, u), v));
864 mpaff(S, s < k ? gel(p1,1) : p1);
865 if (p2 && s < k) mpaff(S, gel(p2, 1));
866 set_avma(av);
867 }
868 if (p2 && s == k) mpaff(p1, p2);
869 }
870 }
871 return L;
872 }
873
874 /* bit 1 of flag unset: full, otherwise up to duality (~ half)
875 * bit 2 of flag unset: all <= k, otherwise only k
876 * half: 2^(k-3)+ delta_{k even} * 2^(k/2-2), sum = 2^(k-2)+2^(floor(k/2)-1)-1
877 * full: 2^(k-2); sum = 2^(k-1)-1 */
878 static GEN
zetamultall_i(long k,long flag,long prec)879 zetamultall_i(long k, long flag, long prec)
880 {
881 GEN res, ind, L = fillL(k, prec2nbits(prec) + 32);
882 long m, K2 = 1 << (k-2), n = lg(L) - 1, m0 = (flag & 4L) ? K2 : 1;
883
884 if (!(flag & 2L))
885 {
886 res = cgetg(n - m0, t_VEC);
887 ind = cgetg(n - m0, t_VECSMALL);
888 for (m = m0; m < n - 1; m++)
889 {
890 gel(res, m - m0 + 1) = m < K2 ? gmael(L, m + 2, 1) : gel(L, m + 2);
891 ind[m - m0 + 1] = m;
892 }
893 }
894 else
895 { /* up to duality */
896 long nres, c;
897 if (k == 2) nres = 1;
898 else if (!(flag & 2L))
899 nres = (1 << (k - 2)) + (1 << ((k/2) - 1)) - 1;
900 else
901 nres = (1 << (k - 1));
902 res = cgetg(nres + 1, t_VEC);
903 ind = cgetg(nres + 1, t_VECSMALL);
904 for (m = m0, c = 1; m < n - 1; m++)
905 {
906 GEN z = gel(L,m+2);
907 if (isclone(z)) continue; /* dual */
908 if (m < K2) z = gel(z,1);
909 gel(res, c) = z;
910 ind[c] = m; c++;
911 }
912 setlg(res, c);
913 setlg(ind, c);
914 }
915 return mkvec2(res, ind);
916 }
917
918 /* fd(e, 2, lg(e)-2), e = atoe(avec) */
919 static long
atom(GEN avec)920 atom(GEN avec)
921 {
922 long i, m, l = lg(avec);
923 if (l < 3) return 0;
924 m = 1; /* avec[1] != 0 */
925 for (i = 2; i < l-1; i++) m = (m << avec[i]) + 1;
926 return m << (avec[i]-1);
927 }
928 static long
atoind(GEN avec,long flag)929 atoind(GEN avec, long flag)
930 { return atom(avec) + (flag? 1: (1 << (zv_sum(avec) - 2))); }
931 /* If flag is unset, L has all k1 <= k, otherwise only k */
932 static GEN
zetamultstar_i(GEN L,GEN avec,long flag)933 zetamultstar_i(GEN L, GEN avec, long flag)
934 {
935 GEN s = allstar(avec), S = gen_0;
936 long i, l = lg(s);
937 for (i = 1; i < l; i++) S = gadd(S, gel(L, atoind(gel(s,i), flag)));
938 return S;
939 }
940
941 /* bit 0: notstar/star
942 * bit 1: full/half (ignored if star, always full)
943 * bit 2: all <= k / only k
944 * bit 3: without / with index */
945 GEN
zetamultall(long k,long flag,long prec)946 zetamultall(long k, long flag, long prec)
947 {
948 pari_sp av = avma;
949 GEN Lind, L, res;
950 long K, k1, ct, fl;
951
952 if (flag < 0 || flag > 15) pari_err_FLAG("zetamultall");
953 if (k < 1) pari_err_DOMAIN("zetamultall", "k", "<", gen_1, stoi(k));
954 if (k >= 64) pari_err_OVERFLOW("zetamultall");
955 if (!(flag & 1L))
956 { /* not star */
957 Lind = zetamultall_i(k, flag, prec);
958 res = (flag & 8L)? Lind : gel(Lind, 1);
959 return gerepilecopy(av, res);
960 }
961 /* star */
962 fl = flag & 4L; /* 4 if k, else 0 (all <= k) */
963 Lind = gerepilecopy(av, zetamultall_i(k, fl, prec)); /* full */
964 L = gel(Lind, 1);
965 K = 1 << (k - 2);
966 res = cgetg(fl? K+1: 2*K, t_VEC);
967 for (ct = 1, k1 = fl? k: 2; k1 <= k; k1++)
968 {
969 GEN w = cgetg(k1 + 1, t_VECSMALL);
970 long M = 1 << (k1 - 1), m;
971 for (m = 1; m <= M; m += 2)
972 {
973 pari_sp av = avma;
974 long j, mc = m;
975 for (j = k1; j >= 1; j--) { w[j] = mc & 1; mc >>= 1; }
976 gel(res, ct++) = gerepileupto(av, zetamultstar_i(L, etoa(w), fl));
977 }
978 }
979 if (flag & 8L) res = mkvec2(res, gel(Lind, 2));
980 return gerepilecopy(av, res);
981 }
982