Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

Testing latest pari + WASM + node.js... and it works?! Wow.

28479 views
License: GPL3
ubuntu2004
1
/* Copyright (C) 2018 The PARI group.
2
3
This file is part of the PARI/GP package.
4
5
PARI/GP is free software; you can redistribute it and/or modify it under the
6
terms of the GNU General Public License as published by the Free Software
7
Foundation; either version 2 of the License, or (at your option) any later
8
version. It is distributed in the hope that it will be useful, but WITHOUT
9
ANY WARRANTY WHATSOEVER.
10
11
Check the License for details. You should have received a copy of it, along
12
with the package; see the file 'COPYING'. If not, write to the Free Software
13
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14
15
#include "pari.h"
16
#include "paripriv.h"
17
18
#define DEBUGLEVEL DEBUGLEVEL_bern
19
20
/********************************************************************/
21
/** **/
22
/** BERNOULLI NUMBERS B_2k **/
23
/** **/
24
/********************************************************************/
25
26
/* D = divisorsu(n). Return a/b = \sum_{p-1 | 2n: p prime} 1/p
27
* B_2k + a/b in Z [Clausen-von Staudt] */
28
static GEN
29
fracB2k(GEN D)
30
{
31
GEN a = utoipos(5), b = utoipos(6); /* 1/2 + 1/3 */
32
long i, l = lg(D);
33
for (i = 2; i < l; i++) /* skip 1 */
34
{
35
ulong p = 2*D[i] + 1; /* a/b += 1/p */
36
if (uisprime(p)) { a = addii(muliu(a,p), b); b = muliu(b,p); }
37
}
38
return mkfrac(a,b);
39
}
40
/* precision needed to compute B_k for all k <= N */
41
long
42
bernbitprec(long N)
43
{ /* 1.612086 ~ log(8Pi) / 2 */
44
const double log2PI = 1.83787706641;
45
double t = (N + 0.5) * log((double)N) - N*(1 + log2PI) + 1.612086;
46
return (long)ceil(t / M_LN2) + 16;
47
}
48
static long
49
bernprec(long N) { return nbits2prec(bernbitprec(N)); }
50
/* \sum_{k > M} k^(-n) <= M^(1-n) / (n-1) < 2^-bit_accuracy(prec) */
51
static long
52
zetamaxpow(long n, long prec)
53
{
54
long b = bit_accuracy(prec), M = (long)exp2((double)b/(n-1.0));
55
return M | 1; /* make it odd */
56
}
57
/* zeta(k) using 'max' precomputed odd powers */
58
static GEN
59
bern_zeta(long k, GEN pow, long max, long prec)
60
{
61
GEN s = gel(pow, max);
62
long j;
63
for (j = max - 2; j >= 3; j -= 2) s = addrr(s, gel(pow,j));
64
return divrr(addrs(s,1), subsr(1, real2n(-k, prec)));
65
}
66
/* z * j^2 */
67
static GEN
68
mulru2(GEN z, ulong j)
69
{ return (j | HIGHMASK)? mulru(mulru(z, j), j)
70
: mulru(z, j*j); }
71
/* 1 <= m <= n, set y[1] = B_{2m}, ... y[n-m+1] = B_{2n} in Q */
72
static void
73
bernset(GEN *y, long m, long n)
74
{
75
long i, j, k, bit, prec, max, N = n << 1; /* up to B_N */
76
GEN A, C, pow;
77
bit = bernbitprec(N);
78
prec = nbits2prec(bit);
79
A = sqrr(Pi2n(1, prec)); /* (2Pi)^2 */
80
C = divrr(mpfactr(N, prec), powru(A, n)); shiftr_inplace(C,1);
81
max = zetamaxpow(N, prec);
82
pow = cgetg(max+1, t_VEC);
83
for (j = 3; j <= max; j += 2)
84
{ /* fixed point, precision decreases with j */
85
long b = bit - N * log2(j), p = b <= 0? LOWDEFAULTPREC: nbits2prec(b);
86
gel(pow,j) = invr(rpowuu(j, N, p));
87
}
88
y += n - m;
89
for (i = n, k = N;; i--)
90
{ /* set B_n, k = 2i */
91
pari_sp av2 = avma;
92
GEN B, z = fracB2k(divisorsu(i)), s = bern_zeta(k, pow, max, prec);
93
long j;
94
/* s = zeta(k), C = 2*k! / (2Pi)^k */
95
B = mulrr(s, C); if (!odd(i)) setsigne(B, -1); /* B ~ B_n */
96
B = roundr(addrr(B, fractor(z,LOWDEFAULTPREC))); /* B - z = B_n */
97
*y-- = gclone(gsub(B, z));
98
if (i == m) break;
99
affrr(divrunu(mulrr(C,A), k-1), C);
100
for (j = max; j >= 3; j -= 2) affrr(mulru2(gel(pow,j), j), gel(pow,j));
101
set_avma(av2);
102
k -= 2;
103
if ((k & 0xf) == 0)
104
{ /* reduce precision if possible */
105
long bit2 = bernbitprec(k), prec2 = nbits2prec(bit2), max2;
106
if (prec2 == prec) continue;
107
prec = prec2;
108
max2 = zetamaxpow(k,prec);
109
if (max2 > max) continue;
110
bit = bit2;
111
max = max2;
112
setprec(C, prec);
113
for (j = 3; j <= max; j += 2)
114
{
115
GEN P = gel(pow,j);
116
long b = bit + expo(P), p = b <= 0? LOWDEFAULTPREC: nbits2prec(b);
117
if (realprec(P) > p) setprec(P, p);
118
}
119
}
120
}
121
}
122
/* need B[2..2*nb] as t_INT or t_FRAC */
123
void
124
constbern(long nb)
125
{
126
const pari_sp av = avma;
127
long i, l;
128
GEN B;
129
pari_timer T;
130
131
l = bernzone? lg(bernzone): 0;
132
if (l > nb) return;
133
134
nb = maxss(nb, l + 127);
135
B = cgetg_block(nb+1, t_VEC);
136
if (bernzone)
137
{ for (i = 1; i < l; i++) gel(B,i) = gel(bernzone,i); }
138
else
139
{
140
gel(B,1) = gclone(mkfracss(1,6));
141
gel(B,2) = gclone(mkfracss(-1,30));
142
gel(B,3) = gclone(mkfracss(1,42));
143
gel(B,4) = gclone(mkfracss(-1,30));
144
gel(B,5) = gclone(mkfracss(5,66));
145
gel(B,6) = gclone(mkfracss(-691,2730));
146
gel(B,7) = gclone(mkfracss(7,6));
147
gel(B,8) = gclone(mkfracss(-3617,510));
148
gel(B,9) = gclone(mkfracss(43867,798));
149
gel(B,10)= gclone(mkfracss(-174611,330));
150
gel(B,11)= gclone(mkfracss(854513,138));
151
gel(B,12)= gclone(mkfracss(-236364091,2730));
152
gel(B,13)= gclone(mkfracss(8553103,6)); /* B_26 */
153
l = 14;
154
}
155
set_avma(av);
156
if (DEBUGLEVEL) {
157
err_printf("caching Bernoulli numbers 2*%ld to 2*%ld\n", l, nb);
158
timer_start(&T);
159
}
160
bernset((GEN*)B + l, l, nb);
161
if (DEBUGLEVEL) timer_printf(&T, "Bernoulli");
162
swap(B, bernzone); guncloneNULL(B);
163
set_avma(av);
164
}
165
/* Obsolete, kept for backward compatibility */
166
void
167
mpbern(long n, long prec) { (void)prec; constbern(n); }
168
169
/* assume n even > 0, if iz != NULL, assume iz = 1/zeta(n) */
170
static GEN
171
bernreal_using_zeta(long n, long prec)
172
{
173
GEN pi2 = Pi2n(1, prec+EXTRAPRECWORD);
174
GEN iz = inv_szeta_euler(n, prec);
175
GEN z = divrr(mpfactr(n, prec), mulrr(powru(pi2, n), iz));
176
shiftr_inplace(z, 1); /* 2 * n! * zeta(n) / (2Pi)^n */
177
if ((n & 3) == 0) setsigne(z, -1);
178
return z;
179
}
180
/* assume n even > 0, B = NULL or good approximation to B_n */
181
static GEN
182
bernfrac_i(long n, GEN B)
183
{
184
GEN z = fracB2k(divisorsu(n >> 1));
185
if (!B) B = bernreal_using_zeta(n, bernprec(n));
186
B = roundr( gadd(B, fractor(z,LOWDEFAULTPREC)) );
187
return gsub(B, z);
188
}
189
GEN
190
bernfrac(long n)
191
{
192
pari_sp av;
193
long k;
194
if (n <= 1)
195
{
196
if (n < 0) pari_err_DOMAIN("bernfrac", "index", "<", gen_0, stoi(n));
197
return n? mkfrac(gen_m1,gen_2): gen_1;
198
}
199
if (odd(n)) return gen_0;
200
k = n >> 1;
201
if (!bernzone) constbern(0);
202
if (bernzone && k < lg(bernzone)) return gel(bernzone, k);
203
av = avma;
204
return gerepileupto(av, bernfrac_i(n, NULL));
205
}
206
GEN
207
bernvec(long n)
208
{
209
long i, l;
210
GEN y;
211
if (n < 0) return cgetg(1, t_VEC);
212
constbern(n);
213
l = n+2; y = cgetg(l, t_VEC); gel(y,1) = gen_1;
214
for (i = 2; i < l; i++) gel(y,i) = gel(bernzone,i-1);
215
return y;
216
}
217
218
/* x := pol_x(v); B_k(x) = \sum_{i=0}^k binomial(k, i) B_i x^{k-i} */
219
static GEN
220
bernpol_i(long k, long v)
221
{
222
GEN B, C;
223
long i;
224
if (v < 0) v = 0;
225
constbern(k >> 1); /* cache B_2, ..., B_2[k/2] */
226
C = vecbinomial(k);
227
B = cgetg(k + 3, t_POL);
228
for (i = 0; i <= k; ++i) gel(B, k-i+2) = gmul(gel(C,i+1), bernfrac(i));
229
B[1] = evalsigne(1) | evalvarn(v);
230
return B;
231
}
232
GEN
233
bernpol(long k, long v)
234
{
235
pari_sp av = avma;
236
if (k < 0) pari_err_DOMAIN("bernpol", "index", "<", gen_0, stoi(k));
237
return gerepileupto(av, bernpol_i(k, v));
238
}
239
/* x := pol_x(v); return 1^e + ... + x^e = x^e + (B_{e+1}(x) - B_{e+1})/(e+1) */
240
static GEN
241
faulhaber(long e, long v)
242
{
243
GEN B;
244
if (e == 0) return pol_x(v);
245
B = RgX_integ(bernpol_i(e, v)); /* (B_{e+1}(x) - B_{e+1}) / (e+1) */
246
gel(B,e+2) = gaddgs(gel(B,e+2), 1); /* add x^e, in place */
247
return B;
248
}
249
/* sum_v T(v), T a polynomial expression in v */
250
GEN
251
sumformal(GEN T, long v)
252
{
253
pari_sp av = avma, av2;
254
long i, t, d;
255
GEN R;
256
257
T = simplify_shallow(T);
258
t = typ(T);
259
if (is_scalar_t(t))
260
return gerepileupto(av, monomialcopy(T, 1, v < 0? 0: v));
261
if (t != t_POL) pari_err_TYPE("sumformal [not a t_POL]", T);
262
if (v < 0) v = varn(T);
263
av2 = avma;
264
R = gen_0;
265
d = poldegree(T,v);
266
for (i = d; i >= 0; i--)
267
{
268
GEN c = polcoef(T, i, v);
269
if (gequal0(c)) continue;
270
R = gadd(R, gmul(c, faulhaber(i, v)));
271
if (gc_needed(av2,3))
272
{
273
if(DEBUGMEM>1) pari_warn(warnmem,"sumformal, i = %ld/%ld", i,d);
274
R = gerepileupto(av2, R);
275
}
276
}
277
return gerepileupto(av, R);
278
}
279
280
/* 1/zeta(n) using Euler product. Assume n > 0. */
281
GEN
282
inv_szeta_euler(long n, long prec)
283
{
284
long bit = prec2nbits(prec);
285
GEN z, res;
286
pari_sp av, av2;
287
double A, D, lba;
288
ulong p, lim;
289
forprime_t S;
290
291
if (n > bit) return real_1(prec);
292
293
lba = prec2nbits_mul(prec, M_LN2);
294
D = exp((lba - log((double)(n-1))) / (n-1));
295
lim = 1 + (ulong)ceil(D);
296
if (lim < 3) return subir(gen_1,real2n(-n,prec));
297
res = cgetr(prec); av = avma; incrprec(prec);
298
299
(void)u_forprime_init(&S, 3, lim);
300
av2 = avma; A = n / M_LN2; z = subir(gen_1, real2n(-n, prec));
301
while ((p = u_forprime_next(&S)))
302
{
303
long l = bit - (long)floor(A * log((double)p));
304
GEN h;
305
306
if (l < BITS_IN_LONG) l = BITS_IN_LONG;
307
l = minss(prec, nbits2prec(l));
308
h = divrr(z, rpowuu(p, (ulong)n, l));
309
z = subrr(z, h);
310
if (gc_needed(av,1))
311
{
312
if (DEBUGMEM>1) pari_warn(warnmem,"inv_szeta_euler, p = %lu/%lu", p,lim);
313
z = gerepileuptoleaf(av2, z);
314
}
315
}
316
affrr(z, res); set_avma(av); return res;
317
}
318
319
/* Return B_n */
320
GEN
321
bernreal(long n, long prec)
322
{
323
pari_sp av;
324
GEN B;
325
long p, k;
326
if (n < 0) pari_err_DOMAIN("bernreal", "index", "<", gen_0, stoi(n));
327
if (n == 0) return real_1(prec);
328
if (n == 1) return real_m2n(-1,prec); /*-1/2*/
329
if (odd(n)) return real_0(prec);
330
331
k = n >> 1;
332
if (!bernzone) constbern(0);
333
if (k < lg(bernzone)) return fractor(gel(bernzone,k), prec);
334
p = bernprec(n); av = avma;
335
B = bernreal_using_zeta(n, minss(p, prec));
336
if (p < prec) B = fractor(bernfrac_i(n, B), prec);
337
return gerepileuptoleaf(av, B);
338
}
339
340
GEN
341
eulerpol(long k, long v)
342
{
343
pari_sp av = avma;
344
GEN B, E;
345
if (k < 0) pari_err_DOMAIN("eulerpol", "index", "<", gen_0, stoi(k));
346
k++; B = bernpol_i(k, v);
347
E = RgX_Rg_mul(RgX_sub(B, RgX_rescale(B, gen_2)), sstoQ(2,k));
348
return gerepileupto(av, E);
349
}
350
351
/**************************************************************/
352
/* Euler numbers */
353
/**************************************************************/
354
355
/* precision needed to compute E_k for all k <= N */
356
static long
357
eulerbitprec(long N)
358
{ /* 1.1605 ~ log(32/Pi) / 2 */
359
const double logPIS2 = 0.4515827;
360
double t = (N + 0.5) * log((double)N) - N*(1 + logPIS2) + 1.1605;
361
return (long)ceil(t / M_LN2) + 16;
362
}
363
static long
364
eulerprec(long N) { return nbits2prec(eulerbitprec(N)); }
365
366
/* sum_{k > M, k odd} (-1)^((k-1)/2)k^(-n) < M^(-n) < 2^-bit_accuracy(prec) */
367
static long
368
lfun4maxpow(long n, long prec)
369
{
370
long b = bit_accuracy(prec), M = (long)exp2((double)b/(n+0.));
371
return M | 1; /* make it odd */
372
}
373
374
/* lfun4(k) using 'max' precomputed odd powers */
375
static GEN
376
euler_lfun4(GEN pow, long max)
377
{
378
GEN s = ((max & 3L) == 1) ? gel(pow, max) : negr(gel(pow, max));
379
long j;
380
for (j = max - 2; j >= 3; j -= 2)
381
s = ((j & 3L) == 1) ? addrr(s, gel(pow,j)) : subrr(s, gel(pow,j));
382
return addrs(s, 1);
383
}
384
385
/* 1 <= m <= n, set y[1] = E_{2m}, ... y[n-m+1] = E_{2n} in Z */
386
static void
387
eulerset(GEN *y, long m, long n)
388
{
389
long i, j, k, bit, prec, max, N = n << 1, N1 = N + 1; /* up to E_N */
390
GEN A, C, pow;
391
bit = eulerbitprec(N);
392
prec = nbits2prec(bit);
393
A = sqrr(Pi2n(-1, prec)); /* (Pi/2)^2 */
394
C = divrr(mpfactr(N, prec), mulrr(powru(A, n), Pi2n(-2,prec)));
395
max = lfun4maxpow(N1, prec);
396
pow = cgetg(max+1, t_VEC);
397
for (j = 3; j <= max; j += 2)
398
{ /* fixed point, precision decreases with j */
399
long b = bit - N1 * log2(j), p = b <= 0? LOWDEFAULTPREC: nbits2prec(b);
400
gel(pow,j) = invr(rpowuu(j, N1, p));
401
}
402
y += n - m;
403
for (i = n, k = N1;; i--)
404
{ /* set E_n, k = 2i + 1 */
405
pari_sp av2 = avma;
406
GEN E, s = euler_lfun4(pow, max);
407
long j;
408
/* s = lfun4(k), C = (4/Pi)*k! / (Pi/2)^k */
409
E = roundr(mulrr(s, C)); if (odd(i)) setsigne(E, -1); /* E ~ E_n */
410
*y-- = gclone(E);
411
if (i == m) break;
412
affrr(divrunu(mulrr(C,A), k-2), C);
413
for (j = max; j >= 3; j -= 2) affrr(mulru2(gel(pow,j), j), gel(pow,j));
414
set_avma(av2);
415
k -= 2;
416
if ((k & 0xf) == 0)
417
{ /* reduce precision if possible */
418
long bit2 = eulerbitprec(k), prec2 = nbits2prec(bit2), max2;
419
if (prec2 == prec) continue;
420
prec = prec2;
421
max2 = lfun4maxpow(k,prec);
422
if (max2 > max) continue;
423
bit = bit2;
424
max = max2;
425
setprec(C, prec);
426
for (j = 3; j <= max; j += 2)
427
{
428
GEN P = gel(pow,j);
429
long b = bit + expo(P), p = b <= 0? LOWDEFAULTPREC: nbits2prec(b);
430
if (realprec(P) > p) setprec(P, p);
431
}
432
}
433
}
434
}
435
436
/* need E[2..2*nb] as t_INT */
437
static void
438
constreuler(long nb)
439
{
440
const pari_sp av = avma;
441
long i, l;
442
GEN E;
443
pari_timer T;
444
445
l = eulerzone? lg(eulerzone): 0;
446
if (l > nb) return;
447
448
nb = maxss(nb, l + 127);
449
E = cgetg_block(nb+1, t_VEC);
450
if (eulerzone)
451
{ for (i = 1; i < l; i++) gel(E,i) = gel(eulerzone,i); }
452
else
453
{
454
gel(E,1) = gclone(stoi(-1));
455
gel(E,2) = gclone(stoi(5));
456
gel(E,3) = gclone(stoi(-61));
457
gel(E,4) = gclone(stoi(1385));
458
gel(E,5) = gclone(stoi(-50521));
459
gel(E,6) = gclone(stoi(2702765));
460
gel(E,7) = gclone(stoi(-199360981));
461
l = 8;
462
}
463
set_avma(av);
464
if (DEBUGLEVEL) {
465
err_printf("caching Euler numbers 2*%ld to 2*%ld\n", l, nb);
466
timer_start(&T);
467
}
468
eulerset((GEN*)E + l, l, nb);
469
if (DEBUGLEVEL) timer_printf(&T, "Euler");
470
swap(E, eulerzone); guncloneNULL(E);
471
set_avma(av);
472
}
473
474
/* 1/lfun(-4,n) using Euler product. Assume n > 0. */
475
static GEN
476
inv_lfun4(long n, long prec)
477
{
478
long bit = prec2nbits(prec);
479
GEN z, res;
480
pari_sp av, av2;
481
double A;
482
ulong p, lim;
483
forprime_t S;
484
485
if (n > bit) return real_1(prec);
486
487
lim = 1 + (ulong)ceil(exp2((double)bit / n));
488
res = cgetr(prec); av = avma; incrprec(prec);
489
490
(void)u_forprime_init(&S, 3, lim);
491
av2 = avma; A = n / M_LN2; z = real_1(prec);
492
while ((p = u_forprime_next(&S)))
493
{
494
long l = bit - (long)floor(A * log((double)p));
495
GEN h;
496
497
if (l < BITS_IN_LONG) l = BITS_IN_LONG;
498
l = minss(prec, nbits2prec(l));
499
h = rpowuu(p, (ulong)n, l); if ((p & 3UL) == 1) setsigne(h, -1);
500
z = addrr(z, divrr(z, h)); /* z *= 1 - chi_{-4}(p) / p^n */
501
if (gc_needed(av,1))
502
{
503
if (DEBUGMEM>1) pari_warn(warnmem,"inv_lfun4, p = %lu/%lu", p,lim);
504
z = gerepileuptoleaf(av2, z);
505
}
506
}
507
affrr(z, res); set_avma(av); return res;
508
}
509
/* assume n even > 0, E_n = (-1)^(n/2) (4/Pi) n! lfun4(n+1) / (Pi/2)^n */
510
static GEN
511
eulerreal_using_lfun4(long n, long prec)
512
{
513
GEN pisur2 = Pi2n(-1, prec+EXTRAPRECWORD);
514
GEN iz = inv_lfun4(n+1, prec);
515
GEN z = divrr(mpfactr(n, prec), mulrr(powru(pisur2, n+1), iz));
516
if ((n & 3L) == 2) setsigne(z, -1);
517
shiftr_inplace(z, 1); return z;
518
}
519
/* Euler numbers: 1, 0, -1, 0, 5, 0, -61,... */
520
GEN
521
eulerfrac(long n)
522
{
523
pari_sp av;
524
long k;
525
GEN E;
526
if (n <= 0)
527
{
528
if (n < 0) pari_err_DOMAIN("eulerfrac", "index", "<", gen_0, stoi(n));
529
return gen_1;
530
}
531
if (odd(n)) return gen_0;
532
k = n >> 1;
533
if (!eulerzone) constreuler(0);
534
if (eulerzone && k < lg(eulerzone)) return gel(eulerzone, k);
535
av = avma; E = eulerreal_using_lfun4(n, eulerprec(n));
536
return gerepileuptoleaf(av, roundr(E));
537
}
538
GEN
539
eulervec(long n)
540
{
541
long i, l;
542
GEN y;
543
if (n < 0) return cgetg(1, t_VEC);
544
constreuler(n);
545
l = n+2; y = cgetg(l, t_VEC); gel(y,1) = gen_1;
546
for (i = 2; i < l; i++) gel(y,i) = gel(eulerzone,i-1);
547
return y;
548
}
549
550
/* Return E_n */
551
GEN
552
eulerreal(long n, long prec)
553
{
554
pari_sp av = avma;
555
GEN B;
556
long p, k;
557
if (n < 0) pari_err_DOMAIN("eulerreal", "index", "<", gen_0, stoi(n));
558
if (n == 0) return real_1(prec);
559
if (odd(n)) return real_0(prec);
560
561
k = n >> 1;
562
if (!eulerzone) constreuler(0);
563
if (k < lg(eulerzone)) return itor(gel(eulerzone,k), prec);
564
p = eulerprec(n);
565
B = eulerreal_using_lfun4(n, minss(p, prec));
566
if (p < prec) B = itor(roundr(B), prec);
567
return gerepileuptoleaf(av, B);
568
}
569
570