Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

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

28485 views
License: GPL3
ubuntu2004
1
/* Copyright (C) 2000 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_intnum
19
20
static GEN
21
intlin(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec);
22
23
/********************************************************************/
24
/** NUMERICAL INTEGRATION (Romberg) **/
25
/********************************************************************/
26
typedef struct {
27
void *E;
28
GEN (*f)(void *E, GEN);
29
} invfun;
30
31
/* 1/x^2 f(1/x) */
32
static GEN
33
_invf(void *E, GEN x)
34
{
35
invfun *S = (invfun*)E;
36
GEN y = ginv(x);
37
return gmul(S->f(S->E, y), gsqr(y));
38
}
39
40
/* h and s are arrays of the same length L > D. The h[i] are (decreasing)
41
* step sizes, s[i] is the computed Riemann sum for step size h[i].
42
* Interpolate the last D+1 values so that s ~ polynomial in h of degree D.
43
* Guess that limit_{h->0} = s(0) */
44
static GEN
45
interp(GEN h, GEN s, long L, long bit, long D)
46
{
47
pari_sp av = avma;
48
long e1,e2;
49
GEN ss = polintspec(h + L-D, s + L-D, gen_0, D+1, &e2);
50
51
e1 = gexpo(ss);
52
if (DEBUGLEVEL>2)
53
{
54
err_printf("romb: iteration %ld, guess: %Ps\n", L,ss);
55
err_printf("romb: relative error < 2^-%ld [target %ld bits]\n",e1-e2,bit);
56
}
57
if (e1-e2 <= bit && (L <= 10 || e1 >= -bit)) return gc_NULL(av);
58
return cxtoreal(ss);
59
}
60
61
static GEN
62
qrom3(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long bit)
63
{
64
const long JMAX = 25, KLOC = 4;
65
GEN ss,s,h,p1,p2,qlint,del,x,sum;
66
long j, j1, it, sig, prec = nbits2prec(bit);
67
68
a = gtofp(a,prec);
69
b = gtofp(b,prec);
70
qlint = subrr(b,a); sig = signe(qlint);
71
if (!sig) return gen_0;
72
if (sig < 0) { setabssign(qlint); swap(a,b); }
73
74
s = new_chunk(JMAX+KLOC-1);
75
h = new_chunk(JMAX+KLOC-1);
76
gel(h,0) = real_1(prec);
77
78
p1 = eval(E, a); if (p1 == a) p1 = rcopy(p1);
79
p2 = eval(E, b);
80
gel(s,0) = gmul2n(gmul(qlint,gadd(p1,p2)),-1);
81
for (it=1,j=1; j<JMAX; j++, it<<=1) /* it = 2^(j-1) */
82
{
83
pari_sp av, av2;
84
gel(h,j) = real2n(-2*j, prec); /* 2^(-2j) */
85
av = avma; del = divru(qlint,it);
86
x = addrr(a, shiftr(del,-1));
87
av2 = avma;
88
for (sum = gen_0, j1 = 1; j1 <= it; j1++, x = addrr(x,del))
89
{
90
sum = gadd(sum, eval(E, x));
91
if ((j1 & 0x1ff) == 0) gerepileall(av2, 2, &sum,&x);
92
}
93
sum = gmul(sum,del);
94
gel(s,j) = gerepileupto(av, gmul2n(gadd(gel(s,j-1), sum), -1));
95
if (j >= KLOC && (ss = interp(h, s, j, bit-j-6, KLOC)))
96
return gmulsg(sig,ss);
97
}
98
pari_err_IMPL("intnumromb recovery [too many iterations]");
99
return NULL; /* LCOV_EXCL_LINE */
100
}
101
102
static GEN
103
qrom2(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long bit)
104
{
105
const long JMAX = 16, KLOC = 4;
106
GEN ss,s,h,p1,qlint,del,ddel,x,sum;
107
long j, j1, it, sig, prec = nbits2prec(bit);
108
109
a = gtofp(a, prec);
110
b = gtofp(b, prec);
111
qlint = subrr(b,a); sig = signe(qlint);
112
if (!sig) return gen_0;
113
if (sig < 0) { setabssign(qlint); swap(a,b); }
114
115
s = new_chunk(JMAX+KLOC-1);
116
h = new_chunk(JMAX+KLOC-1);
117
gel(h,0) = real_1(prec);
118
119
p1 = shiftr(addrr(a,b),-1);
120
gel(s,0) = gmul(qlint, eval(E, p1));
121
for (it=1, j=1; j<JMAX; j++, it*=3) /* it = 3^(j-1) */
122
{
123
pari_sp av, av2;
124
gel(h,j) = divru(gel(h,j-1), 9); /* 3^(-2j) */
125
av = avma; del = divru(qlint,3*it); ddel = shiftr(del,1);
126
x = addrr(a, shiftr(del,-1));
127
av2 = avma;
128
for (sum = gen_0, j1 = 1; j1 <= it; j1++)
129
{
130
sum = gadd(sum, eval(E, x)); x = addrr(x,ddel);
131
sum = gadd(sum, eval(E, x)); x = addrr(x,del);
132
if ((j1 & 0x1ff) == 0) gerepileall(av2, 2, &sum,&x);
133
}
134
sum = gmul(sum,del); p1 = gdivgs(gel(s,j-1),3);
135
gel(s,j) = gerepileupto(av, gadd(p1,sum));
136
if (j >= KLOC && (ss = interp(h, s, j, bit-(3*j/2)+3, KLOC)))
137
return gmulsg(sig, ss);
138
}
139
pari_err_IMPL("intnumromb recovery [too many iterations]");
140
return NULL; /* LCOV_EXCL_LINE */
141
}
142
143
/* integrate after change of variables x --> 1/x */
144
static GEN
145
qromi(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long bit)
146
{
147
GEN A = ginv(b), B = ginv(a);
148
invfun S;
149
S.f = eval;
150
S.E = E; return qrom2(&S, &_invf, A, B, bit);
151
}
152
153
/* a < b, assume b "small" (< 100 say) */
154
static GEN
155
rom_bsmall(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long bit)
156
{
157
if (gcmpgs(a,-100) >= 0) return qrom2(E,eval,a,b,bit);
158
if (gcmpgs(b, -1) < 0) return qromi(E,eval,a,b,bit); /* a<-100, b<-1 */
159
/* a<-100, b>=-1, split at -1 */
160
return gadd(qromi(E,eval,a,gen_m1,bit),
161
qrom2(E,eval,gen_m1,b,bit));
162
}
163
164
static GEN
165
rombint(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long bit)
166
{
167
long l = gcmp(b,a);
168
GEN z;
169
170
if (!l) return gen_0;
171
if (l < 0) swap(a,b);
172
if (gcmpgs(b,100) >= 0)
173
{
174
if (gcmpgs(a,1) >= 0)
175
z = qromi(E,eval,a,b,bit);
176
else /* split at 1 */
177
z = gadd(rom_bsmall(E,eval,a,gen_1,bit), qromi(E,eval,gen_1,b,bit));
178
}
179
else
180
z = rom_bsmall(E,eval,a,b,bit);
181
if (l < 0) z = gneg(z);
182
return z;
183
}
184
185
GEN
186
intnumromb_bitprec(void *E, GEN (*f)(void *, GEN), GEN a,GEN b, long fl, long B)
187
{
188
pari_sp av = avma;
189
GEN z;
190
switch(fl)
191
{
192
case 0: z = qrom3 (E, f, a, b, B); break;
193
case 1: z = rombint(E, f, a, b, B); break;
194
case 2: z = qromi (E, f, a, b, B); break;
195
case 3: z = qrom2 (E, f, a, b, B); break;
196
default: pari_err_FLAG("intnumromb"); return NULL; /* LCOV_EXCL_LINE */
197
}
198
return gerepileupto(av, z);
199
}
200
GEN
201
intnumromb(void *E, GEN (*f)(void *, GEN), GEN a, GEN b, long flag, long prec)
202
{ return intnumromb_bitprec(E,f,a,b,flag,prec2nbits(prec));}
203
GEN
204
intnumromb0_bitprec(GEN a, GEN b, GEN code, long flag, long bit)
205
{ EXPR_WRAP(code, intnumromb_bitprec(EXPR_ARG, a, b, flag, bit)); }
206
207
/********************************************************************/
208
/** NUMERICAL INTEGRATION (Gauss-Legendre) **/
209
/********************************************************************/
210
/* N > 1; S[n] = n^2. If !last, Newton step z - P_N(z) / P'_N(z),
211
* else [z, (N-1)!P_{N-1}(z)]. */
212
static GEN
213
Legendrenext(long N, GEN z, GEN S, int last)
214
{
215
GEN q, Z, a, b, z2 = sqrr(z);
216
long n, n0, u;
217
218
q = subrs(mulur(3, z2), 1);
219
if (odd(N))
220
{
221
n0 = 3;
222
a = mulrr(z2, subrs(mulur(5, q), 4));
223
b = q;
224
}
225
else
226
{
227
n0 = 2;
228
a = mulrr(q, z);
229
b = z;
230
}
231
for (n = n0, u = 2*n0 + 1; n < N; n += 2, u += 4)
232
{
233
b = subrr(mulur(u, a), mulir(gel(S,n), b));
234
a = subrr(mulur(u + 2, mulrr(z2, b)), mulir(gel(S,n+1), a));
235
}
236
q = divrr(a, subrr(a, mulur(N, b)));
237
Z = subrr(z, divrr(mulrr(subrs(z2, 1), q), mulur(N, z)));
238
return last? mkvec2(Z, mulrr(b, addrs(q, 1))): Z;
239
}
240
/* root ~ dz of Legendre polynomial P_N */
241
static GEN
242
Legendreroot(long N, double dz, GEN S, long bit)
243
{
244
GEN z = dbltor(dz);
245
long e = - dblexpo(1 - dz*dz), n = expu(bit + 32 - e) - 2;
246
long j, pr = 1 + e + ((bit - e) >> n);
247
for (j = 1; j <= n; j++)
248
{
249
pr = 2 * pr - e;
250
z = Legendrenext(N, rtor(z, nbits2prec(pr)), S, j == n);
251
}
252
return z;
253
}
254
GEN
255
intnumgaussinit(long N, long prec)
256
{
257
pari_sp av;
258
long N2, j, k, l, bit;
259
GEN res, V, W, F, S;
260
double d;
261
262
prec += EXTRAPREC64;
263
bit = prec2nbits(prec);
264
if (N <= 0) { N = bit >> 2; if (odd(N)) N++; }
265
if (N == 1) retmkvec2(mkvec(gen_0), mkvec(gen_2));
266
res = cgetg(3, t_VEC);
267
if (N == 2)
268
{
269
GEN z = cgetr(prec);
270
gel(res,1) = mkvec(z);
271
gel(res,2) = mkvec(gen_1);
272
av = avma; affrr(divru(sqrtr(utor(3,prec)), 3), z);
273
return gc_const(av, res);
274
}
275
N2 = N >> 1; l = (N+3)>> 1;
276
gel(res,1) = V = cgetg(l, t_VEC);
277
gel(res,2) = W = cgetg(l, t_VEC);
278
gel(V,1) = odd(N)? gen_0: cgetr(prec);
279
gel(W,1) = cgetr(prec);
280
for (k = 2; k < l; k++) { gel(V,k) = cgetr(prec); gel(W,k) = cgetr(prec); }
281
av = avma; S = vecpowuu(N, 2); F = sqrr(mpfactr(N-1, prec));
282
if (!odd(N)) k = 1;
283
else
284
{
285
GEN c = divrr(sqrr(sqrr(mpfactr(N2, prec))), mulri(F, gel(S,N)));
286
shiftr_inplace(c, 2*N-1);
287
affrr(c, gel(W,1)); k = 2;
288
}
289
F = divri(shiftr(F, 1), gel(S,N));
290
d = 1 - (N-1) / pow((double)(2*N),3);
291
for (j = 4*N2-1; j >= 3; k++, j -= 4)
292
{
293
pari_sp av2 = avma;
294
GEN zw = Legendreroot(N, d * cos(M_PI * j / (4*N+2)), S, bit);
295
GEN z = gel(zw,1), w = gel(zw,2);
296
affrr(z, gel(V,k));
297
w = mulrr(F, divrr(subsr(1, sqrr(z)), sqrr(w)));
298
affrr(w, gel(W,k)); set_avma(av2);
299
}
300
return gc_const(av, res);
301
}
302
303
GEN
304
intnumgauss(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec)
305
{
306
pari_sp ltop = avma;
307
GEN R, W, bma, bpa, S;
308
long n, i, prec2 = prec + EXTRAPREC64;
309
if (!tab)
310
tab = intnumgaussinit(0,prec);
311
else if (typ(tab) != t_INT)
312
{
313
if (typ(tab) != t_VEC || lg(tab) != 3
314
|| typ(gel(tab,1)) != t_VEC
315
|| typ(gel(tab,2)) != t_VEC
316
|| lg(gel(tab,1)) != lg(gel(tab,2)))
317
pari_err_TYPE("intnumgauss",tab);
318
}
319
else
320
tab = intnumgaussinit(itos(tab),prec);
321
322
R = gel(tab,1); n = lg(R)-1;
323
W = gel(tab,2);
324
a = gprec_wensure(a, prec2);
325
b = gprec_wensure(b, prec2);
326
bma = gmul2n(gsub(b,a), -1); /* (b-a)/2 */
327
bpa = gadd(bma, a); /* (b+a)/2 */
328
if (!signe(gel(R,1)))
329
{ /* R[1] = 0, use middle node only once */
330
S = gmul(gel(W,1), eval(E, bpa));
331
i = 2;
332
}
333
else
334
{
335
S = gen_0;
336
i = 1;
337
}
338
for (; i <= n; ++i)
339
{
340
GEN h = gmul(bma, gel(R,i)); /* != 0 */
341
GEN P = eval(E, gadd(bpa, h));
342
GEN M = eval(E, gsub(bpa, h));
343
S = gadd(S, gmul(gel(W,i), gadd(P,M)));
344
S = gprec_wensure(S, prec2);
345
}
346
return gerepilecopy(ltop, gprec_wtrunc(gmul(bma,S), prec));
347
}
348
349
GEN
350
intnumgauss0(GEN a, GEN b, GEN code, GEN tab, long prec)
351
{ EXPR_WRAP(code, intnumgauss(EXPR_ARG, a, b, tab, prec)); }
352
353
/********************************************************************/
354
/** DOUBLE EXPONENTIAL INTEGRATION **/
355
/********************************************************************/
356
357
typedef struct _intdata {
358
long bit; /* bit accuracy of current precision */
359
long l; /* table lengths */
360
GEN tabx0; /* abscissa phi(0) for t = 0 */
361
GEN tabw0; /* weight phi'(0) for t = 0 */
362
GEN tabxp; /* table of abscissas phi(kh) for k > 0 */
363
GEN tabwp; /* table of weights phi'(kh) for k > 0 */
364
GEN tabxm; /* table of abscissas phi(kh) for k < 0, possibly empty */
365
GEN tabwm; /* table of weights phi'(kh) for k < 0, possibly empty */
366
GEN h; /* integration step */
367
} intdata;
368
369
static const long LGTAB = 8;
370
#define TABh(v) gel(v,1)
371
#define TABx0(v) gel(v,2)
372
#define TABw0(v) gel(v,3)
373
#define TABxp(v) gel(v,4)
374
#define TABwp(v) gel(v,5)
375
#define TABxm(v) gel(v,6)
376
#define TABwm(v) gel(v,7)
377
378
static int
379
isinR(GEN z) { return is_real_t(typ(z)); }
380
static int
381
isinC(GEN z)
382
{ return (typ(z) == t_COMPLEX)? isinR(gel(z,1)) && isinR(gel(z,2)): isinR(z); }
383
384
static int
385
checktabsimp(GEN tab)
386
{
387
long L, LN, LW;
388
if (!tab || typ(tab) != t_VEC) return 0;
389
if (lg(tab) != LGTAB) return 0;
390
if (typ(TABxp(tab)) != t_VEC) return 0;
391
if (typ(TABwp(tab)) != t_VEC) return 0;
392
if (typ(TABxm(tab)) != t_VEC) return 0;
393
if (typ(TABwm(tab)) != t_VEC) return 0;
394
L = lg(TABxp(tab)); if (lg(TABwp(tab)) != L) return 0;
395
LN = lg(TABxm(tab)); if (LN != 1 && LN != L) return 0;
396
LW = lg(TABwm(tab)); if (LW != 1 && LW != L) return 0;
397
return 1;
398
}
399
400
static int
401
checktabdoub(GEN tab)
402
{
403
long L;
404
if (typ(tab) != t_VEC) return 0;
405
if (lg(tab) != LGTAB) return 0;
406
L = lg(TABxp(tab));
407
if (lg(TABwp(tab)) != L) return 0;
408
if (lg(TABxm(tab)) != L) return 0;
409
if (lg(TABwm(tab)) != L) return 0;
410
return 1;
411
}
412
413
static int
414
checktab(GEN tab)
415
{
416
if (typ(tab) != t_VEC) return 0;
417
if (lg(tab) != 3) return checktabsimp(tab);
418
return checktabsimp(gel(tab,1))
419
&& checktabsimp(gel(tab,2));
420
}
421
422
/* the TUNE parameter is heuristic */
423
static void
424
intinit_start(intdata *D, long m, double TUNE, long prec)
425
{
426
long l, n, bitprec = prec2nbits(prec);
427
double d = bitprec*LOG10_2;
428
GEN h, nh, pi = mppi(prec);
429
430
n = (long)ceil(d*log(d) / TUNE); /* heuristic */
431
/* nh ~ log(2npi/log(n)) */
432
nh = logr_abs(divrr(mulur(2*n, pi), logr_abs(utor(n,prec))));
433
h = divru(nh, n);
434
if (m > 0) { h = gmul2n(h,-m); n <<= m; }
435
D->h = h;
436
D->bit = bitprec;
437
D->l = l = n+1;
438
D->tabxp = cgetg(l, t_VEC);
439
D->tabwp = cgetg(l, t_VEC);
440
D->tabxm = cgetg(l, t_VEC);
441
D->tabwm = cgetg(l, t_VEC);
442
}
443
444
static GEN
445
intinit_end(intdata *D, long pnt, long mnt)
446
{
447
GEN v = cgetg(LGTAB, t_VEC);
448
if (pnt < 0) pari_err_DOMAIN("intnuminit","table length","<",gen_0,stoi(pnt));
449
TABx0(v) = D->tabx0;
450
TABw0(v) = D->tabw0;
451
TABh(v) = D->h;
452
TABxp(v) = D->tabxp; setlg(D->tabxp, pnt+1);
453
TABwp(v) = D->tabwp; setlg(D->tabwp, pnt+1);
454
TABxm(v) = D->tabxm; setlg(D->tabxm, mnt+1);
455
TABwm(v) = D->tabwm; setlg(D->tabwm, mnt+1); return v;
456
}
457
458
/* divide by 2 in place */
459
static GEN
460
divr2_ip(GEN x) { shiftr_inplace(x, -1); return x; }
461
462
/* phi(t)=tanh((Pi/2)sinh(t)): from -1 to 1, hence also from a to b compact
463
* interval */
464
static GEN
465
inittanhsinh(long m, long prec)
466
{
467
GEN e, ei, ek, eik, pi = mppi(prec);
468
long k, nt = -1;
469
intdata D;
470
471
intinit_start(&D, m, 1.86, prec);
472
D.tabx0 = real_0(prec);
473
D.tabw0 = Pi2n(-1,prec);
474
e = mpexp(D.h); ek = mulrr(pi, e);
475
ei = invr(e); eik = mulrr(pi, ei);
476
for (k = 1; k < D.l; k++)
477
{
478
GEN xp, wp, ct, st, z;
479
pari_sp av;
480
gel(D.tabxp,k) = cgetr(prec);
481
gel(D.tabwp,k) = cgetr(prec); av = avma;
482
ct = divr2_ip(addrr(ek, eik)); /* Pi ch(kh) */
483
st = subrr(ek, ct); /* Pi sh(kh) */
484
z = invr( addrs(mpexp(st), 1) );
485
shiftr_inplace(z, 1); if (expo(z) < -D.bit) { nt = k-1; break; }
486
xp = subsr(1, z);
487
wp = divr2_ip(mulrr(ct, subsr(1, sqrr(xp))));
488
affrr(xp, gel(D.tabxp,k)); mulrrz(ek, e, ek);
489
affrr(wp, gel(D.tabwp,k)); mulrrz(eik, ei, eik); set_avma(av);
490
}
491
return intinit_end(&D, nt, 0);
492
}
493
494
/* phi(t)=sinh(sinh(t)): from -oo to oo, slowly decreasing, at least
495
* as 1/x^2. */
496
static GEN
497
initsinhsinh(long m, long prec)
498
{
499
pari_sp av;
500
GEN et, ct, st, ex;
501
long k, nt = -1;
502
intdata D;
503
504
intinit_start(&D, m, 0.666, prec);
505
D.tabx0 = real_0(prec);
506
D.tabw0 = real_1(prec);
507
et = ex = mpexp(D.h);
508
for (k = 1; k < D.l; k++)
509
{
510
GEN xp, wp, ext, exu;
511
gel(D.tabxp,k) = cgetr(prec);
512
gel(D.tabwp,k) = cgetr(prec); av = avma;
513
ct = divr2_ip(addrr(et, invr(et)));
514
st = subrr(et, ct);
515
ext = mpexp(st);
516
exu = invr(ext);
517
xp = divr2_ip(subrr(ext, exu));
518
wp = divr2_ip(mulrr(ct, addrr(ext, exu)));
519
if (expo(wp) - 2*expo(xp) < -D.bit) { nt = k-1; break; }
520
affrr(xp, gel(D.tabxp,k));
521
affrr(wp, gel(D.tabwp,k)); et = gerepileuptoleaf(av, mulrr(et, ex));
522
}
523
return intinit_end(&D, nt, 0);
524
}
525
526
/* phi(t)=2sinh(t): from -oo to oo, exponentially decreasing as exp(-x) */
527
static GEN
528
initsinh(long m, long prec)
529
{
530
pari_sp av;
531
GEN et, ex, eti, xp, wp;
532
long k, nt = -1;
533
intdata D;
534
535
intinit_start(&D, m, 1.0, prec);
536
D.tabx0 = real_0(prec);
537
D.tabw0 = real2n(1, prec);
538
et = ex = mpexp(D.h);
539
for (k = 1; k < D.l; k++)
540
{
541
gel(D.tabxp,k) = cgetr(prec);
542
gel(D.tabwp,k) = cgetr(prec); av = avma;
543
eti = invr(et);
544
xp = subrr(et, eti);
545
wp = addrr(et, eti);
546
if (cmprs(xp, (long)(M_LN2*(expo(wp)+D.bit) + 1)) > 0) { nt = k-1; break; }
547
affrr(xp, gel(D.tabxp,k));
548
affrr(wp, gel(D.tabwp,k)); et = gerepileuptoleaf(av, mulrr(et, ex));
549
}
550
return intinit_end(&D, nt, 0);
551
}
552
553
/* phi(t)=exp(2sinh(t)): from 0 to oo, slowly decreasing at least as 1/x^2 */
554
static GEN
555
initexpsinh(long m, long prec)
556
{
557
GEN et, ex;
558
long k, nt = -1;
559
intdata D;
560
561
intinit_start(&D, m, 1.05, prec);
562
D.tabx0 = real_1(prec);
563
D.tabw0 = real2n(1, prec);
564
ex = mpexp(D.h);
565
et = real_1(prec);
566
for (k = 1; k < D.l; k++)
567
{
568
GEN t, eti, xp;
569
et = mulrr(et, ex);
570
eti = invr(et); t = addrr(et, eti);
571
xp = mpexp(subrr(et, eti));
572
gel(D.tabxp,k) = xp;
573
gel(D.tabwp,k) = mulrr(xp, t);
574
gel(D.tabxm,k) = invr(xp);
575
gel(D.tabwm,k) = mulrr(gel(D.tabxm,k), t);
576
if (expo(gel(D.tabxm,k)) < -D.bit) { nt = k-1; break; }
577
}
578
return intinit_end(&D, nt, nt);
579
}
580
581
/* phi(t)=exp(t-exp(-t)) : from 0 to +oo, exponentially decreasing. */
582
static GEN
583
initexpexp(long m, long prec)
584
{
585
pari_sp av;
586
GEN et, ex;
587
long k, nt = -1;
588
intdata D;
589
590
intinit_start(&D, m, 1.76, prec);
591
D.tabx0 = mpexp(real_m1(prec));
592
D.tabw0 = gmul2n(D.tabx0, 1);
593
et = ex = mpexp(negr(D.h));
594
for (k = 1; k < D.l; k++)
595
{
596
GEN xp, xm, wp, wm, eti, kh;
597
gel(D.tabxp,k) = cgetr(prec);
598
gel(D.tabwp,k) = cgetr(prec);
599
gel(D.tabxm,k) = cgetr(prec);
600
gel(D.tabwm,k) = cgetr(prec); av = avma;
601
eti = invr(et); kh = mulur(k,D.h);
602
xp = mpexp(subrr(kh, et));
603
xm = mpexp(negr(addrr(kh, eti)));
604
wp = mulrr(xp, addsr(1, et));
605
if (expo(xm) < -D.bit && cmprs(xp, (long)(M_LN2*(expo(wp)+D.bit) + 1)) > 0) { nt = k-1; break; }
606
wm = mulrr(xm, addsr(1, eti));
607
affrr(xp, gel(D.tabxp,k));
608
affrr(wp, gel(D.tabwp,k));
609
affrr(xm, gel(D.tabxm,k));
610
affrr(wm, gel(D.tabwm,k)); et = gerepileuptoleaf(av, mulrr(et, ex));
611
}
612
return intinit_end(&D, nt, nt);
613
}
614
615
/* phi(t)=(Pi/h)*t/(1-exp(-sinh(t))) from 0 to oo, sine oscillation */
616
static GEN
617
initnumsine(long m, long prec)
618
{
619
pari_sp av;
620
GEN invh, et, eti, ex, pi = mppi(prec);
621
long exh, k, nt = -1;
622
intdata D;
623
624
intinit_start(&D, m, 0.666, prec);
625
invh = invr(D.h);
626
D.tabx0 = mulrr(pi, invh);
627
D.tabw0 = gmul2n(D.tabx0,-1);
628
exh = expo(invh); /* expo(1/h) */
629
et = ex = mpexp(D.h);
630
for (k = 1; k < D.l; k++)
631
{
632
GEN xp,xm, wp,wm, ct,st, extp,extp1,extp2, extm,extm1,extm2, kct, kpi;
633
gel(D.tabxp,k) = cgetr(prec);
634
gel(D.tabwp,k) = cgetr(prec);
635
gel(D.tabxm,k) = cgetr(prec);
636
gel(D.tabwm,k) = cgetr(prec); av = avma;
637
eti = invr(et); /* exp(-kh) */
638
ct = divr2_ip(addrr(et, eti)); /* ch(kh) */
639
st = divr2_ip(subrr(et, eti)); /* sh(kh) */
640
extp = mpexp(st); extp1 = subsr(1, extp);
641
extp2 = invr(extp1); /* 1/(1-exp(sh(kh))) */
642
extm = invr(extp); extm1 = subsr(1, extm);
643
extm2 = invr(extm1);/* 1/(1-exp(sh(-kh))) */
644
kpi = mulur(k, pi);
645
kct = mulur(k, ct);
646
extm1 = mulrr(extm1, invh);
647
extp1 = mulrr(extp1, invh);
648
xp = mulrr(kpi, extm2); /* phi(kh) */
649
wp = mulrr(subrr(extm1, mulrr(kct, extm)), mulrr(pi, sqrr(extm2)));
650
xm = mulrr(negr(kpi), extp2); /* phi(-kh) */
651
wm = mulrr(addrr(extp1, mulrr(kct, extp)), mulrr(pi, sqrr(extp2)));
652
if (expo(wm) < -D.bit && expo(extm) + exh + expu(10 * k) < -D.bit) { nt = k-1; break; }
653
affrr(xp, gel(D.tabxp,k));
654
affrr(wp, gel(D.tabwp,k));
655
affrr(xm, gel(D.tabxm,k));
656
affrr(wm, gel(D.tabwm,k)); et = gerepileuptoleaf(av, mulrr(et, ex));
657
}
658
return intinit_end(&D, nt, nt);
659
}
660
661
/* End of initialization functions. These functions can be executed once
662
* and for all for a given accuracy and type of integral ([a,b], [a,oo[ or
663
* ]-oo,a], ]-oo,oo[) */
664
665
/* The numbers below can be changed, but NOT the ordering */
666
enum {
667
f_REG = 0, /* regular function */
668
f_SER = 1, /* power series */
669
f_SINGSER = 2, /* algebraic singularity, power series endpoint */
670
f_SING = 3, /* algebraic singularity */
671
f_YSLOW = 4, /* oo, slowly decreasing, at least x^(-2) */
672
f_YVSLO = 5, /* oo, very slowly decreasing, worse than x^(-2) */
673
f_YFAST = 6, /* oo, exponentially decreasing */
674
f_YOSCS = 7, /* oo, sine oscillating */
675
f_YOSCC = 8 /* oo, cosine oscillating */
676
};
677
/* is finite ? */
678
static int
679
is_fin_f(long c) { return c == f_REG || c == f_SER || c == f_SING; }
680
/* is oscillatory ? */
681
static int
682
is_osc(long c) { long a = labs(c); return a == f_YOSCC|| a == f_YOSCS; }
683
684
/* All inner functions such as intn, etc... must be called with a
685
* valid 'tab' table. The wrapper intnum provides a higher level interface */
686
687
/* compute \int_a^b f(t)dt with [a,b] compact and f nonsingular. */
688
static GEN
689
intn(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab)
690
{
691
GEN tabx0, tabw0, tabxp, tabwp;
692
GEN bpa, bma, bmb, S;
693
long i, prec;
694
pari_sp ltop = avma, av;
695
696
if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab);
697
tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0);
698
tabxp = TABxp(tab); tabwp = TABwp(tab);
699
bpa = gmul2n(gadd(b, a), -1); /* (b+a)/2 */
700
bma = gsub(bpa, a); /* (b-a)/2 */
701
av = avma;
702
bmb = gmul(bma, tabx0); /* (b-a)/2 phi(0) */
703
/* phi'(0) f( (b+a)/2 + (b-a)/2 * phi(0) ) */
704
S = gmul(tabw0, eval(E, gadd(bpa, bmb)));
705
for (i = lg(tabxp)-1; i > 0; i--)
706
{
707
GEN SP, SM;
708
bmb = gmul(bma, gel(tabxp,i));
709
SP = eval(E, gsub(bpa, bmb));
710
SM = eval(E, gadd(bpa, bmb));
711
S = gadd(S, gmul(gel(tabwp,i), gadd(SP, SM)));
712
if ((i & 0x7f) == 1) S = gerepileupto(av, S);
713
S = gprec_wensure(S, prec);
714
}
715
return gerepileupto(ltop, gmul(S, gmul(bma, TABh(tab))));
716
}
717
718
/* compute \int_a^b f(t)dt with [a,b] compact, possible singularity with
719
* exponent a[2] at lower extremity, b regular. Use tanh(sinh(t)). */
720
static GEN
721
intnsing(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab)
722
{
723
GEN tabx0, tabw0, tabxp, tabwp, ea, ba, S;
724
long i, prec;
725
pari_sp ltop = avma, av;
726
727
if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab);
728
tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0);
729
tabxp = TABxp(tab); tabwp = TABwp(tab);
730
ea = ginv(gaddsg(1, gel(a,2)));
731
a = gel(a,1);
732
ba = gdiv(gsub(b, a), gpow(gen_2, ea, prec));
733
av = avma;
734
S = gmul(gmul(tabw0, ba), eval(E, gadd(gmul(ba, addsr(1, tabx0)), a)));
735
for (i = lg(tabxp)-1; i > 0; i--)
736
{
737
GEN p = addsr(1, gel(tabxp,i));
738
GEN m = subsr(1, gel(tabxp,i));
739
GEN bp = gmul(ba, gpow(p, ea, prec));
740
GEN bm = gmul(ba, gpow(m, ea, prec));
741
GEN SP = gmul(gdiv(bp, p), eval(E, gadd(bp, a)));
742
GEN SM = gmul(gdiv(bm, m), eval(E, gadd(bm, a)));
743
S = gadd(S, gmul(gel(tabwp,i), gadd(SP, SM)));
744
if ((i & 0x7f) == 1) S = gerepileupto(av, S);
745
S = gprec_wensure(S, prec);
746
}
747
return gerepileupto(ltop, gmul(gmul(S, TABh(tab)), ea));
748
}
749
750
static GEN id(GEN x) { return x; }
751
752
/* compute \int_a^oo f(t)dt if si>0 or \int_{-oo}^a f(t)dt if si<0$.
753
* Use exp(2sinh(t)) for slowly decreasing functions, exp(1+t-exp(-t)) for
754
* exponentially decreasing functions, and (pi/h)t/(1-exp(-sinh(t))) for
755
* oscillating functions. */
756
static GEN
757
intninfpm(void *E, GEN (*eval)(void*, GEN), GEN a, long sb, GEN tab)
758
{
759
GEN tabx0, tabw0, tabxp, tabwp, tabxm, tabwm;
760
GEN S;
761
long L, i, prec;
762
pari_sp av = avma;
763
764
if (!checktabdoub(tab)) pari_err_TYPE("intnum",tab);
765
tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0);
766
tabxp = TABxp(tab); tabwp = TABwp(tab); L = lg(tabxp);
767
tabxm = TABxm(tab); tabwm = TABwm(tab);
768
if (gequal0(a))
769
{
770
GEN (*NEG)(GEN) = sb > 0? id: gneg;
771
S = gmul(tabw0, eval(E, NEG(tabx0)));
772
for (i = 1; i < L; i++)
773
{
774
GEN SP = eval(E, NEG(gel(tabxp,i)));
775
GEN SM = eval(E, NEG(gel(tabxm,i)));
776
S = gadd(S, gadd(gmul(gel(tabwp,i), SP), gmul(gel(tabwm,i), SM)));
777
if ((i & 0x7f) == 1) S = gerepileupto(av, S);
778
S = gprec_wensure(S, prec);
779
}
780
}
781
else if (gexpo(a) <= 0 || is_osc(sb))
782
{ /* a small */
783
GEN (*ADD)(GEN,GEN) = sb > 0? gadd: gsub;
784
S = gmul(tabw0, eval(E, ADD(a, tabx0)));
785
for (i = 1; i < L; i++)
786
{
787
GEN SP = eval(E, ADD(a, gel(tabxp,i)));
788
GEN SM = eval(E, ADD(a, gel(tabxm,i)));
789
S = gadd(S, gadd(gmul(gel(tabwp,i), SP), gmul(gel(tabwm,i), SM)));
790
if ((i & 0x7f) == 1) S = gerepileupto(av, S);
791
S = gprec_wensure(S, prec);
792
}
793
}
794
else
795
{ /* a large, |a|*\int_sgn(a)^{oo} f(|a|*x)dx (sb > 0)*/
796
GEN (*ADD)(long,GEN) = sb > 0? addsr: subsr;
797
long sa = gsigne(a);
798
GEN A = sa > 0? a: gneg(a);
799
pari_sp av2 = avma;
800
S = gmul(tabw0, eval(E, gmul(A, ADD(sa, tabx0))));
801
for (i = 1; i < L; i++)
802
{
803
GEN SP = eval(E, gmul(A, ADD(sa, gel(tabxp,i))));
804
GEN SM = eval(E, gmul(A, ADD(sa, gel(tabxm,i))));
805
S = gadd(S, gadd(gmul(gel(tabwp,i), SP), gmul(gel(tabwm,i), SM)));
806
if ((i & 0x7f) == 1) S = gerepileupto(av2, S);
807
S = gprec_wensure(S, prec);
808
}
809
S = gmul(S,A);
810
}
811
return gerepileupto(av, gmul(S, TABh(tab)));
812
}
813
814
/* Compute \int_{-oo}^oo f(t)dt
815
* use sinh(sinh(t)) for slowly decreasing functions and sinh(t) for
816
* exponentially decreasing functions.
817
* HACK: in case TABwm(tab) contains something, assume function to be integrated
818
* satisfies f(-x) = conj(f(x)).
819
*/
820
static GEN
821
intninfinf(void *E, GEN (*eval)(void*, GEN), GEN tab)
822
{
823
GEN tabx0, tabw0, tabxp, tabwp, tabwm;
824
GEN S;
825
long L, i, prec, spf;
826
pari_sp ltop = avma;
827
828
if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab);
829
tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0);
830
tabxp = TABxp(tab); tabwp = TABwp(tab); L = lg(tabxp);
831
tabwm = TABwm(tab);
832
spf = (lg(tabwm) == lg(tabwp));
833
S = gmul(tabw0, eval(E, tabx0));
834
if (spf) S = gmul2n(real_i(S), -1);
835
for (i = L-1; i > 0; i--)
836
{
837
GEN SP = eval(E, gel(tabxp,i));
838
if (spf)
839
S = gadd(S, real_i(gmul(gel(tabwp,i), SP)));
840
else
841
{
842
GEN SM = eval(E, negr(gel(tabxp,i)));
843
S = gadd(S, gmul(gel(tabwp,i), gadd(SP,SM)));
844
}
845
if ((i & 0x7f) == 1) S = gerepileupto(ltop, S);
846
S = gprec_wensure(S, prec);
847
}
848
if (spf) S = gmul2n(S,1);
849
return gerepileupto(ltop, gmul(S, TABh(tab)));
850
}
851
852
/* general num integration routine int_a^b f(t)dt, where a and b are as follows:
853
- a scalar : the scalar, no singularity worse than logarithmic at a.
854
- [a, e] : the scalar a, singularity exponent -1 < e <= 0.
855
- +oo: slowly decreasing function (at least O(t^-2))
856
- [[+oo], a], a nonnegative real : +oo, function behaving like exp(-a|t|)
857
- [[+oo], e], e < -1 : +oo, function behaving like t^e
858
- [[+oo], a*I], a > 0 real : +oo, function behaving like cos(at)
859
- [[+oo], a*I], a < 0 real : +oo, function behaving like sin(at)
860
and similarly at -oo */
861
static GEN
862
f_getycplx(GEN a, long prec)
863
{
864
GEN a2R, a2I;
865
long s;
866
867
if (lg(a) == 2 || gequal0(gel(a,2))) return gen_1;
868
a2R = real_i(gel(a,2));
869
a2I = imag_i(gel(a,2));
870
s = gsigne(a2I); if (s < 0) a2I = gneg(a2I);
871
return ginv(gprec_wensure(s ? a2I : a2R, prec));
872
}
873
874
static void
875
err_code(GEN a, const char *name)
876
{
877
char *s = stack_sprintf("intnum [incorrect %s]", name);
878
pari_err_TYPE(s, a);
879
}
880
881
/* a = [[+/-oo], alpha]*/
882
static long
883
code_aux(GEN a, const char *name)
884
{
885
GEN re, im, alpha = gel(a,2);
886
long s;
887
if (!isinC(alpha)) err_code(a, name);
888
re = real_i(alpha);
889
im = imag_i(alpha);
890
s = gsigne(im);
891
if (s)
892
{
893
if (!gequal0(re)) err_code(a, name);
894
return s > 0 ? f_YOSCC : f_YOSCS;
895
}
896
if (gequal0(re) || gcmpgs(re, -2)<=0) return f_YSLOW;
897
if (gsigne(re) > 0) return f_YFAST;
898
if (gcmpgs(re, -1) >= 0) err_code(a, name);
899
return f_YVSLO;
900
}
901
902
static long
903
transcode(GEN a, const char *name)
904
{
905
GEN a1, a2;
906
switch(typ(a))
907
{
908
case t_VEC: break;
909
case t_INFINITY:
910
return inf_get_sign(a) == 1 ? f_YSLOW: -f_YSLOW;
911
case t_SER: case t_POL: case t_RFRAC:
912
return f_SER;
913
default: if (!isinC(a)) err_code(a,name);
914
return f_REG;
915
}
916
switch(lg(a))
917
{
918
case 2: return gsigne(gel(a,1)) > 0 ? f_YSLOW : -f_YSLOW;
919
case 3: break;
920
default: err_code(a,name);
921
}
922
a1 = gel(a,1);
923
a2 = gel(a,2);
924
switch(typ(a1))
925
{
926
case t_VEC:
927
if (lg(a1) != 2) err_code(a,name);
928
return gsigne(gel(a1,1)) * code_aux(a, name);
929
case t_INFINITY:
930
return inf_get_sign(a1) * code_aux(a, name);
931
case t_SER: case t_POL: case t_RFRAC:
932
if (!isinR(a2)) err_code(a,name);
933
if (gcmpgs(a2, -1) <= 0)
934
pari_err_IMPL("intnum with diverging non constant limit");
935
return gsigne(a2) < 0 ? f_SINGSER : f_SER;
936
default:
937
if (!isinC(a1) || !isinR(a2) || gcmpgs(a2, -1) <= 0) err_code(a,name);
938
return gsigne(a2) < 0 ? f_SING : f_REG;
939
}
940
}
941
942
/* computes the necessary tabs, knowing a, b and m */
943
static GEN
944
homtab(GEN tab, GEN k)
945
{
946
GEN z;
947
if (gequal0(k) || gequal(k, gen_1)) return tab;
948
if (gsigne(k) < 0) k = gneg(k);
949
z = cgetg(LGTAB, t_VEC);
950
TABx0(z) = gmul(TABx0(tab), k);
951
TABw0(z) = gmul(TABw0(tab), k);
952
TABxp(z) = gmul(TABxp(tab), k);
953
TABwp(z) = gmul(TABwp(tab), k);
954
TABxm(z) = gmul(TABxm(tab), k);
955
TABwm(z) = gmul(TABwm(tab), k);
956
TABh(z) = rcopy(TABh(tab)); return z;
957
}
958
959
static GEN
960
expvec(GEN v, GEN ea, long prec)
961
{
962
long lv = lg(v), i;
963
GEN z = cgetg(lv, t_VEC);
964
for (i = 1; i < lv; i++) gel(z,i) = gpow(gel(v,i),ea,prec);
965
return z;
966
}
967
968
static GEN
969
expscalpr(GEN vnew, GEN xold, GEN wold, GEN ea)
970
{
971
pari_sp av = avma;
972
return gerepileupto(av, gdiv(gmul(gmul(vnew, wold), ea), xold));
973
}
974
static GEN
975
expvecpr(GEN vnew, GEN xold, GEN wold, GEN ea)
976
{
977
long lv = lg(vnew), i;
978
GEN z = cgetg(lv, t_VEC);
979
for (i = 1; i < lv; i++)
980
gel(z,i) = expscalpr(gel(vnew,i), gel(xold,i), gel(wold,i), ea);
981
return z;
982
}
983
984
/* here k < -1 */
985
static GEN
986
exptab(GEN tab, GEN k, long prec)
987
{
988
GEN v, ea;
989
990
if (gcmpgs(k, -2) <= 0) return tab;
991
ea = ginv(gsubsg(-1, k));
992
v = cgetg(LGTAB, t_VEC);
993
TABx0(v) = gpow(TABx0(tab), ea, prec);
994
TABw0(v) = expscalpr(TABx0(v), TABx0(tab), TABw0(tab), ea);
995
TABxp(v) = expvec(TABxp(tab), ea, prec);
996
TABwp(v) = expvecpr(TABxp(v), TABxp(tab), TABwp(tab), ea);
997
TABxm(v) = expvec(TABxm(tab), ea, prec);
998
TABwm(v) = expvecpr(TABxm(v), TABxm(tab), TABwm(tab), ea);
999
TABh(v) = rcopy(TABh(tab));
1000
return v;
1001
}
1002
1003
static GEN
1004
init_fin(GEN b, long codeb, long m, long l, long prec)
1005
{
1006
switch(labs(codeb))
1007
{
1008
case f_REG:
1009
case f_SING: return inittanhsinh(m,l);
1010
case f_YSLOW: return initexpsinh(m,l);
1011
case f_YVSLO: return exptab(initexpsinh(m,l), gel(b,2), prec);
1012
case f_YFAST: return homtab(initexpexp(m,l), f_getycplx(b,l));
1013
/* f_YOSCS, f_YOSCC */
1014
default: return homtab(initnumsine(m,l),f_getycplx(b,l));
1015
}
1016
}
1017
1018
static GEN
1019
intnuminit_i(GEN a, GEN b, long m, long prec)
1020
{
1021
long codea, codeb, l;
1022
GEN T, kma, kmb, tmp;
1023
1024
if (m > 30) pari_err_OVERFLOW("intnuminit [m]");
1025
if (m < 0) pari_err_DOMAIN("intnuminit", "m", "<", gen_0, stoi(m));
1026
l = prec+EXTRAPREC64;
1027
codea = transcode(a, "a"); if (codea == f_SER) codea = f_REG;
1028
codeb = transcode(b, "b"); if (codeb == f_SER) codeb = f_REG;
1029
if (codea == f_SINGSER || codeb == f_SINGSER)
1030
pari_err_IMPL("intnuminit with singularity at non constant limit");
1031
if (labs(codea) > labs(codeb)) { swap(a, b); lswap(codea, codeb); }
1032
if (codea == f_REG)
1033
{
1034
T = init_fin(b, codeb, m,l,prec);
1035
switch(labs(codeb))
1036
{
1037
case f_YOSCS: if (gequal0(a)) break;
1038
case f_YOSCC: T = mkvec2(inittanhsinh(m,l), T);
1039
}
1040
return T;
1041
}
1042
if (codea == f_SING)
1043
{
1044
T = init_fin(b,codeb, m,l,prec);
1045
T = mkvec2(labs(codeb) == f_SING? T: inittanhsinh(m,l), T);
1046
return T;
1047
}
1048
/* now a and b are infinite */
1049
if (codea * codeb > 0) return gen_0;
1050
kma = f_getycplx(a,l); codea = labs(codea);
1051
kmb = f_getycplx(b,l); codeb = labs(codeb);
1052
if (codea == f_YSLOW && codeb == f_YSLOW) return initsinhsinh(m, l);
1053
if (codea == f_YFAST && codeb == f_YFAST && gequal(kma, kmb))
1054
return homtab(initsinh(m,l), kmb);
1055
T = cgetg(3, t_VEC);
1056
switch (codea)
1057
{
1058
case f_YSLOW:
1059
case f_YVSLO:
1060
tmp = initexpsinh(m,l);
1061
gel(T,1) = codea == f_YSLOW? tmp: exptab(tmp, gel(a,2), prec);
1062
switch (codeb)
1063
{
1064
case f_YVSLO: gel(T,2) = exptab(tmp, gel(b,2), prec); return T;
1065
case f_YFAST: gel(T,2) = homtab(initexpexp(m,l), kmb); return T;
1066
/* YOSC[CS] */
1067
default: gel(T,2) = homtab(initnumsine(m,l), kmb); return T;
1068
}
1069
break;
1070
case f_YFAST:
1071
tmp = initexpexp(m, l);
1072
gel(T,1) = homtab(tmp, kma);
1073
switch (codeb)
1074
{
1075
case f_YFAST: gel(T,2) = homtab(tmp, kmb); return T;
1076
/* YOSC[CS] */
1077
default: gel(T,2) = homtab(initnumsine(m, l), kmb); return T;
1078
}
1079
default: /* YOSC[CS] */
1080
tmp = initnumsine(m, l);
1081
gel(T,1) = homtab(tmp,kma);
1082
if (codea == f_YOSCC && codeb == f_YOSCC && !gequal(kma, kmb))
1083
gel(T,2) = mkvec2(inittanhsinh(m,l), homtab(tmp,kmb));
1084
else
1085
gel(T,2) = homtab(tmp,kmb);
1086
return T;
1087
}
1088
}
1089
GEN
1090
intnuminit(GEN a, GEN b, long m, long prec)
1091
{
1092
pari_sp av = avma;
1093
return gerepilecopy(av, intnuminit_i(a,b,m,prec));
1094
}
1095
1096
static GEN
1097
intnuminit0(GEN a, GEN b, GEN tab, long prec)
1098
{
1099
long m;
1100
if (!tab) m = 0;
1101
else if (typ(tab) != t_INT)
1102
{
1103
if (!checktab(tab)) pari_err_TYPE("intnuminit0",tab);
1104
return tab;
1105
}
1106
else
1107
m = itos(tab);
1108
return intnuminit(a, b, m, prec);
1109
}
1110
1111
/* Assigns the values of the function weighted by w[k] at quadrature points x[k]
1112
* [replacing the weights]. Return the index of the last nonzero coeff */
1113
static long
1114
weight(void *E, GEN (*eval)(void *, GEN), GEN x, GEN w)
1115
{
1116
long k, l = lg(x);
1117
for (k = 1; k < l; k++) gel(w,k) = gmul(gel(w,k), eval(E, gel(x,k)));
1118
k--; while (k >= 1) if (!gequal0(gel(w,k--))) break;
1119
return k;
1120
}
1121
/* compute the necessary tabs, weights multiplied by f(t) */
1122
static GEN
1123
intfuncinit_i(void *E, GEN (*eval)(void*, GEN), GEN tab)
1124
{
1125
GEN tabxp = TABxp(tab), tabwp = TABwp(tab);
1126
GEN tabxm = TABxm(tab), tabwm = TABwm(tab);
1127
long L, L0 = lg(tabxp);
1128
1129
TABw0(tab) = gmul(TABw0(tab), eval(E, TABx0(tab)));
1130
if (lg(tabxm) == 1)
1131
{
1132
TABxm(tab) = tabxm = gneg(tabxp);
1133
TABwm(tab) = tabwm = leafcopy(tabwp);
1134
}
1135
/* update wp and wm in place */
1136
L = minss(weight(E, eval, tabxp, tabwp), weight(E, eval, tabxm, tabwm));
1137
if (L < L0)
1138
{ /* catch up functions whose growth at oo was not adequately described */
1139
setlg(tabxp, L+1);
1140
setlg(tabwp, L+1);
1141
if (lg(tabxm) > 1) { setlg(tabxm, L+1); setlg(tabwm, L+1); }
1142
}
1143
return tab;
1144
}
1145
1146
GEN
1147
intfuncinit(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long m, long prec)
1148
{
1149
pari_sp av = avma;
1150
GEN tab = intnuminit_i(a, b, m, prec);
1151
1152
if (lg(tab) == 3)
1153
pari_err_IMPL("intfuncinit with hard endpoint behavior");
1154
if (is_fin_f(transcode(a,"intfuncinit")) ||
1155
is_fin_f(transcode(b,"intfuncinit")))
1156
pari_err_IMPL("intfuncinit with finite endpoints");
1157
return gerepilecopy(av, intfuncinit_i(E, eval, tab));
1158
}
1159
1160
static GEN
1161
intnum_i(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec)
1162
{
1163
GEN S = gen_0, kma, kmb;
1164
long sb, sgns = 1, codea = transcode(a, "a"), codeb = transcode(b, "b");
1165
1166
if (codea == f_REG && typ(a) == t_VEC) a = gel(a,1);
1167
if (codeb == f_REG && typ(b) == t_VEC) b = gel(b,1);
1168
if (codea == f_REG && codeb == f_REG) return intn(E, eval, a, b, tab);
1169
if (codea == f_SER || codeb == f_SER) return intlin(E, eval, a, b, tab, prec);
1170
if (labs(codea) > labs(codeb)) { swap(a,b); lswap(codea,codeb); sgns = -1; }
1171
/* now labs(codea) <= labs(codeb) */
1172
if (codeb == f_SING)
1173
{
1174
if (codea == f_REG)
1175
S = intnsing(E, eval, b, a, tab), sgns = -sgns;
1176
else
1177
{
1178
GEN c = gmul2n(gadd(gel(a,1), gel(b,1)), -1);
1179
S = gsub(intnsing(E, eval, a, c, gel(tab,1)),
1180
intnsing(E, eval, b, c, gel(tab,2)));
1181
}
1182
return (sgns < 0) ? gneg(S) : S;
1183
}
1184
/* now b is infinite */
1185
sb = codeb > 0 ? 1 : -1;
1186
codeb = labs(codeb);
1187
if (codea == f_REG && codeb != f_YOSCC
1188
&& (codeb != f_YOSCS || gequal0(a)))
1189
{
1190
S = intninfpm(E, eval, a, sb*codeb, tab);
1191
return sgns*sb < 0 ? gneg(S) : S;
1192
}
1193
if (is_fin_f(codea))
1194
{ /* either codea == f_SING or codea == f_REG and codeb = f_YOSCC
1195
* or (codeb == f_YOSCS and !gequal0(a)) */
1196
GEN S2, c = real_i(codea == f_SING? gel(a,1): a);
1197
switch(codeb)
1198
{
1199
case f_YOSCC: case f_YOSCS:
1200
{
1201
GEN pi2p = gmul(Pi2n(1,prec), f_getycplx(b, prec));
1202
GEN pis2p = gmul2n(pi2p, -2);
1203
if (codeb == f_YOSCC) c = gadd(c, pis2p);
1204
c = gdiv(c, pi2p);
1205
c = sb > 0? addiu(gceil(c), 1): subiu(gfloor(c), 1);
1206
c = gmul(pi2p, c);
1207
if (codeb == f_YOSCC) c = gsub(c, pis2p);
1208
break;
1209
}
1210
default:
1211
c = sb > 0? addiu(gceil(c), 1): subiu(gfloor(c), 1);
1212
break;
1213
}
1214
S = codea==f_SING? intnsing(E, eval, a, c, gel(tab,1))
1215
: intn (E, eval, a, c, gel(tab,1));
1216
S2 = intninfpm(E, eval, c, sb*codeb, gel(tab,2));
1217
if (sb < 0) S2 = gneg(S2);
1218
S = gadd(S, S2);
1219
return sgns < 0 ? gneg(S) : S;
1220
}
1221
/* now a and b are infinite */
1222
if (codea * sb > 0)
1223
{
1224
if (codea > 0) pari_warn(warner, "integral from oo to oo");
1225
if (codea < 0) pari_warn(warner, "integral from -oo to -oo");
1226
return gen_0;
1227
}
1228
if (sb < 0) sgns = -sgns;
1229
codea = labs(codea);
1230
kma = f_getycplx(a, prec);
1231
kmb = f_getycplx(b, prec);
1232
if ((codea == f_YSLOW && codeb == f_YSLOW)
1233
|| (codea == f_YFAST && codeb == f_YFAST && gequal(kma, kmb)))
1234
S = intninfinf(E, eval, tab);
1235
else
1236
{
1237
GEN pis2 = Pi2n(-1, prec);
1238
GEN ca = (codea == f_YOSCC)? gmul(pis2, kma): gen_0;
1239
GEN cb = (codeb == f_YOSCC)? gmul(pis2, kmb): gen_0;
1240
GEN c = codea == f_YOSCC ? ca : cb; /*signe(a)=-sb*/
1241
GEN SP, SN = intninfpm(E, eval, c, -sb*codea, gel(tab,1));
1242
if (codea != f_YOSCC)
1243
SP = intninfpm(E, eval, cb, sb*codeb, gel(tab,2));
1244
/* codea = codeb = f_YOSCC */
1245
else if (gequal(kma, kmb))
1246
SP = intninfpm(E, eval, cb, sb*codeb, gel(tab,2));
1247
else
1248
{
1249
tab = gel(tab,2);
1250
SP = intninfpm(E, eval, cb, sb*codeb, gel(tab,2));
1251
SP = gadd(SP, intn(E, eval, ca, cb, gel(tab,1)));
1252
}
1253
S = gadd(SN, SP);
1254
}
1255
if (sgns < 0) S = gneg(S);
1256
return S;
1257
}
1258
1259
GEN
1260
intnum(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec)
1261
{
1262
pari_sp ltop = avma;
1263
long l = prec+EXTRAPREC64;
1264
GEN na = NULL, nb = NULL, S;
1265
1266
if (transcode(a,"a") == f_SINGSER) {
1267
long v = gvar(gel(a,1));
1268
if (v != NO_VARIABLE) {
1269
na = cgetg(3,t_VEC);
1270
gel(na,1) = polcoef(gel(a,1),0,v);
1271
gel(na,2) = gel(a,2);
1272
}
1273
a = gel(a,1);
1274
}
1275
if (transcode(b,"b") == f_SINGSER) {
1276
long v = gvar(gel(b,1));
1277
if (v != NO_VARIABLE) {
1278
nb = cgetg(3,t_VEC);
1279
gel(nb,1) = polcoef(gel(b,1),0,v);
1280
gel(nb,2) = gel(b,2);
1281
}
1282
b = gel(b,1);
1283
}
1284
if (na || nb) {
1285
if (tab && typ(tab) != t_INT)
1286
pari_err_IMPL("non integer tab argument");
1287
S = intnum(E, eval, na ? na : a, nb ? nb : b, tab, prec);
1288
if (na) S = gsub(S, intnum(E, eval, na, a, tab, prec));
1289
if (nb) S = gsub(S, intnum(E, eval, b, nb, tab, prec));
1290
return gerepilecopy(ltop, S);
1291
}
1292
tab = intnuminit0(a, b, tab, prec);
1293
S = intnum_i(E, eval, gprec_wensure(a, l), gprec_wensure(b, l), tab, prec);
1294
return gerepilecopy(ltop, gprec_wtrunc(S, prec));
1295
}
1296
1297
typedef struct auxint_s {
1298
GEN a, R, mult;
1299
GEN (*f)(void*, GEN);
1300
GEN (*w)(GEN, long);
1301
long prec;
1302
void *E;
1303
} auxint_t;
1304
1305
static GEN
1306
auxcirc(void *E, GEN t)
1307
{
1308
auxint_t *D = (auxint_t*) E;
1309
GEN s, c, z;
1310
mpsincos(mulrr(t, D->mult), &s, &c); z = mkcomplex(c,s);
1311
return gmul(z, D->f(D->E, gadd(D->a, gmul(D->R, z))));
1312
}
1313
1314
GEN
1315
intcirc(void *E, GEN (*eval)(void*, GEN), GEN a, GEN R, GEN tab, long prec)
1316
{
1317
auxint_t D;
1318
GEN z;
1319
1320
D.a = a;
1321
D.R = R;
1322
D.mult = mppi(prec);
1323
D.f = eval;
1324
D.E = E;
1325
z = intnum(&D, &auxcirc, real_m1(prec), real_1(prec), tab, prec);
1326
return gmul2n(gmul(R, z), -1);
1327
}
1328
1329
static GEN
1330
auxlin(void *E, GEN t)
1331
{
1332
auxint_t *D = (auxint_t*) E;
1333
return D->f(D->E, gadd(D->a, gmul(D->mult, t)));
1334
}
1335
1336
static GEN
1337
intlin(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec)
1338
{
1339
auxint_t D;
1340
GEN z;
1341
1342
if (typ(a) == t_VEC) a = gel(a,1);
1343
if (typ(b) == t_VEC) b = gel(b,1);
1344
z = toser_i(a); if (z) a = z;
1345
z = toser_i(b); if (z) b = z;
1346
D.a = a;
1347
D.mult = gsub(b,a);
1348
D.f = eval;
1349
D.E = E;
1350
z = intnum(&D, &auxlin, real_0(prec), real_1(prec), tab, prec);
1351
return gmul(D.mult, z);
1352
}
1353
1354
GEN
1355
intnum0(GEN a, GEN b, GEN code, GEN tab, long prec)
1356
{ EXPR_WRAP(code, intnum(EXPR_ARG, a, b, tab, prec)); }
1357
GEN
1358
intcirc0(GEN a, GEN R, GEN code, GEN tab, long prec)
1359
{ EXPR_WRAP(code, intcirc(EXPR_ARG, a, R, tab, prec)); }
1360
GEN
1361
intfuncinit0(GEN a, GEN b, GEN code, long m, long prec)
1362
{ EXPR_WRAP(code, intfuncinit(EXPR_ARG, a, b, m, prec)); }
1363
1364
#if 0
1365
/* Two variable integration */
1366
1367
typedef struct auxf_s {
1368
GEN x;
1369
GEN (*f)(void *, GEN, GEN);
1370
void *E;
1371
} auxf_t;
1372
1373
typedef struct indi_s {
1374
GEN (*c)(void*, GEN);
1375
GEN (*d)(void*, GEN);
1376
GEN (*f)(void *, GEN, GEN);
1377
void *Ec;
1378
void *Ed;
1379
void *Ef;
1380
GEN tabintern;
1381
long prec;
1382
} indi_t;
1383
1384
static GEN
1385
auxf(GEN y, void *E)
1386
{
1387
auxf_t *D = (auxf_t*) E;
1388
return D->f(D->E, D->x, y);
1389
}
1390
1391
static GEN
1392
intnumdoubintern(GEN x, void *E)
1393
{
1394
indi_t *D = (indi_t*) E;
1395
GEN c = D->c(x, D->Ec), d = D->d(x, D->Ed);
1396
auxf_t A;
1397
1398
A.x = x;
1399
A.f = D->f;
1400
A.E = D->Ef;
1401
return intnum(&A, &auxf, c, d, D->tabintern, D->prec);
1402
}
1403
1404
GEN
1405
intnumdoub(void *Ef, GEN (*evalf)(void *, GEN, GEN), void *Ec, GEN (*evalc)(void*, GEN), void *Ed, GEN (*evald)(void*, GEN), GEN a, GEN b, GEN tabext, GEN tabint, long prec)
1406
{
1407
indi_t E;
1408
1409
E.c = evalc;
1410
E.d = evald;
1411
E.f = evalf;
1412
E.Ec = Ec;
1413
E.Ed = Ed;
1414
E.Ef = Ef;
1415
E.prec = prec;
1416
if (typ(tabint) == t_INT)
1417
{
1418
GEN C = evalc(a, Ec), D = evald(a, Ed);
1419
if (typ(C) != t_VEC && typ(D) != t_VEC) { C = gen_0; D = gen_1; }
1420
E.tabintern = intnuminit0(C, D, tabint, prec);
1421
}
1422
else E.tabintern = tabint;
1423
return intnum(&E, &intnumdoubintern, a, b, tabext, prec);
1424
}
1425
1426
GEN
1427
intnumdoub0(GEN a, GEN b, int nc, int nd, int nf, GEN tabext, GEN tabint, long prec)
1428
{
1429
GEN z;
1430
push_lex(NULL);
1431
push_lex(NULL);
1432
z = intnumdoub(chf, &gp_eval2, chc, &gp_eval, chd, &gp_eval, a, b, tabext, tabint, prec);
1433
pop_lex(1); pop_lex(1); return z;
1434
}
1435
#endif
1436
1437
/* Given a continued fraction C output by QD convert it into an Euler
1438
* continued fraction A(n), B(n), where
1439
* 1 / (1 + C[2]z / (1+C[3]z / (1+..C[lim]z)))
1440
* = 1 / (1+A[1]*z+B[1]*z^2/(1+A[2]*z+B[2]*z^2/(1+...1/(1+A[lim\2]*z)))). */
1441
static GEN
1442
contfrac_Euler(GEN C)
1443
{
1444
long i, n = lg(C) - 1, a = n/2, b = (n - 1)/2;
1445
GEN A = cgetg(a+1, t_VEC), B = cgetg(b+1, t_VEC);
1446
gel(A,1) = gel(C,2);
1447
if (!b) return mkvec2(A, B);
1448
gel(B,1) = gneg(gmul(gel(C,3), gel(C,2)));
1449
for (i = 2; i <= b; i++)
1450
{
1451
GEN u = gel(C,2*i);
1452
gel(A,i) = gadd(u, gel(C, 2*i-1));
1453
gel(B,i) = gneg(gmul(gel(C, 2*i+1), u));
1454
}
1455
if (a != b) gel(A,a) = gadd(gel(C, 2*a), gel(C, 2*a-1));
1456
return mkvec2(A, B);
1457
}
1458
1459
/* The quotient-difference algorithm. Given a vector M, convert the series
1460
* S = sum_{n >= 0} M[n+1] z^n into a continued fraction.
1461
* Compute the c[n] such that
1462
* S = c[1] / (1 + c[2]z / (1+c[3]z/(1+...c[lim]z))),
1463
* Assume lim <= #M. Does not work for certain M. */
1464
static GEN
1465
QD(GEN M, long lim)
1466
{
1467
pari_sp av;
1468
GEN e, q, c;
1469
long lim2, j, k;
1470
e = zerovec(lim);
1471
c = zerovec(lim+1); gel(c, 1) = gel(M, 1);
1472
q = cgetg(lim+1, t_VEC);
1473
for (k = 1; k <= lim; ++k) gel(q, k) = gdiv(gel(M, k+1), gel(M, k));
1474
lim2 = lim/2; av = avma;
1475
for (j = 1; j <= lim2; ++j)
1476
{
1477
long l = lim - 2*j;
1478
gel(c, 2*j) = gneg(gel(q, 1));
1479
for (k = 0; k <= l; ++k)
1480
gel(e, k+1) = gsub(gadd(gel(e, k+2), gel(q, k+2)), gel(q, k+1));
1481
for (k = 0; k < l; ++k)
1482
gel(q, k+1) = gdiv(gmul(gel(q, k+2), gel(e, k+2)), gel(e, k+1));
1483
gel(c, 2*j+1) = gneg(gel(e, 1));
1484
if (gc_needed(av, 3))
1485
{
1486
if (DEBUGMEM>1) pari_warn(warnmem,"contfracinit, %ld/%ld",j,lim2);
1487
gerepileall(av, 3, &e, &c, &q);
1488
}
1489
}
1490
if (odd(lim)) gel(c, lim+1) = gneg(gel(q, 1));
1491
return c;
1492
}
1493
1494
static GEN
1495
quodif_i(GEN M, long n)
1496
{
1497
switch(typ(M))
1498
{
1499
case t_RFRAC:
1500
if (n < 0) pari_err_TYPE("contfracinit",M);
1501
M = gtoser(M, varn(gel(M,2)), n+3); /*fall through*/
1502
case t_SER: M = gtovec(M); break;
1503
case t_POL: M = RgX_to_RgC(M, degpol(M)+1); break;
1504
case t_VEC: case t_COL: break;
1505
default: pari_err_TYPE("contfracinit", M);
1506
}
1507
if (n < 0)
1508
{
1509
n = lg(M)-2;
1510
if (n < 0) return cgetg(1,t_VEC);
1511
}
1512
else if (lg(M)-1 <= n)
1513
pari_err_COMPONENT("contfracinit", "<", stoi(lg(M)-1), stoi(n));
1514
return QD(M, n);
1515
}
1516
GEN
1517
quodif(GEN M, long n)
1518
{
1519
pari_sp av = avma;
1520
return gerepilecopy(av, quodif_i(M, n));
1521
}
1522
GEN
1523
contfracinit(GEN M, long n)
1524
{
1525
pari_sp av = avma;
1526
GEN C = quodif_i(M, n);
1527
if (lg(C) < 3) { set_avma(av); retmkvec2(cgetg(1,t_VEC), cgetg(1,t_VEC)); }
1528
return gerepilecopy(av, contfrac_Euler(C));
1529
}
1530
1531
/* Evaluate at 1/tinv the nlim first terms of the continued fraction output by
1532
* contfracinit. Shallow. */
1533
GEN
1534
contfraceval_inv(GEN CF, GEN tinv, long nlim)
1535
{
1536
pari_sp av;
1537
long j;
1538
GEN S = gen_0, S1, S2, A, B;
1539
if (typ(CF) != t_VEC || lg(CF) != 3) pari_err_TYPE("contfraceval", CF);
1540
A = gel(CF, 1); if (typ(A) != t_VEC) pari_err_TYPE("contfraceval", CF);
1541
B = gel(CF, 2); if (typ(B) != t_VEC) pari_err_TYPE("contfraceval", CF);
1542
if (nlim < 0)
1543
nlim = lg(A)-1;
1544
else if (lg(A) <= nlim)
1545
pari_err_COMPONENT("contfraceval", ">", stoi(lg(A)-1), stoi(nlim));
1546
if (lg(B)+1 <= nlim)
1547
pari_err_COMPONENT("contfraceval", ">", stoi(lg(B)), stoi(nlim));
1548
av = avma;
1549
if (nlim <= 1) return lg(A)==1? gen_0: gdiv(tinv, gadd(gel(A, 1), tinv));
1550
switch(nlim % 3)
1551
{
1552
case 2:
1553
S = gdiv(gel(B, nlim-1), gadd(gel(A, nlim), tinv));
1554
nlim--; break;
1555
1556
case 0:
1557
S1 = gadd(gel(A, nlim), tinv);
1558
S2 = gadd(gmul(gadd(gel(A, nlim-1), tinv), S1), gel(B, nlim-1));
1559
S = gdiv(gmul(gel(B, nlim-2), S1), S2);
1560
nlim -= 2; break;
1561
}
1562
/* nlim = 1 (mod 3) */
1563
for (j = nlim; j >= 4; j -= 3)
1564
{
1565
GEN S3;
1566
S1 = gadd(gadd(gel(A, j), tinv), S);
1567
S2 = gadd(gmul(gadd(gel(A, j-1), tinv), S1), gel(B, j-1));
1568
S3 = gadd(gmul(gadd(gel(A, j-2), tinv), S2), gmul(gel(B, j-2), S1));
1569
S = gdiv(gmul(gel(B, j-3), S2), S3);
1570
if (gc_needed(av, 3)) S = gerepilecopy(av, S);
1571
}
1572
return gdiv(tinv, gadd(gadd(gel(A, 1), tinv), S));
1573
}
1574
1575
GEN
1576
contfraceval(GEN CF, GEN t, long nlim)
1577
{
1578
pari_sp av = avma;
1579
return gerepileupto(av, contfraceval_inv(CF, ginv(t), nlim));
1580
}
1581
1582
/* MONIEN SUMMATION */
1583
1584
/* basic Newton, find x ~ z such that Q(x) = 0 */
1585
static GEN
1586
monrefine(GEN Q, GEN QP, GEN z, long prec)
1587
{
1588
pari_sp av = avma;
1589
GEN pr = poleval(Q, z);
1590
for(;;)
1591
{
1592
GEN prnew;
1593
z = gsub(z, gdiv(pr, poleval(QP, z)));
1594
prnew = poleval(Q, z);
1595
if (gcmp(gabs(prnew, prec), gabs(pr, prec)) >= 0) break;
1596
pr = prnew;
1597
}
1598
z = gprec_wensure(z, 2*prec-2);
1599
z = gsub(z, gdiv(poleval(Q, z), poleval(QP, z)));
1600
return gerepileupto(av, z);
1601
}
1602
1603
static GEN
1604
RX_realroots(GEN x, long prec)
1605
{ return realroots(gprec_wtrunc(x,prec), NULL, prec); }
1606
1607
/* (real) roots of Q, assuming QP = Q' and that half the roots are close to
1608
* k+1, ..., k+m, m = deg(Q)/2-1. N.B. All roots are real and >= 1 */
1609
static GEN
1610
monroots(GEN Q, GEN QP, long k, long prec)
1611
{
1612
long j, n = degpol(Q), m = n/2 - 1;
1613
GEN v2, v1 = cgetg(m+1, t_VEC);
1614
for (j = 1; j <= m; ++j) gel(v1, j) = monrefine(Q, QP, stoi(k+j), prec);
1615
Q = gdivent(Q, roots_to_pol(v1, varn(Q)));
1616
v2 = RX_realroots(Q, prec); settyp(v2, t_VEC);
1617
return shallowconcat(v1, v2);
1618
}
1619
1620
static void
1621
Pade(GEN M, GEN *pP, GEN *pQ)
1622
{
1623
pari_sp av = avma;
1624
long n = lg(M)-2, i;
1625
GEN v = QD(M, n), P = pol_0(0), Q = pol_1(0);
1626
/* evaluate continued fraction => Pade approximants */
1627
for (i = n-1; i >= 1; i--)
1628
{ /* S = P/Q: S -> v[i]*x / (1+S) */
1629
GEN R = RgX_shift_shallow(RgX_Rg_mul(Q,gel(v,i)), 1);
1630
Q = RgX_add(P,Q); P = R;
1631
if (gc_needed(av, 3))
1632
{
1633
if (DEBUGMEM>1) pari_warn(warnmem,"Pade, %ld/%ld",i,n-1);
1634
gerepileall(av, 3, &P, &Q, &v);
1635
}
1636
}
1637
/* S -> 1+S */
1638
*pP = RgX_add(P,Q);
1639
*pQ = Q;
1640
}
1641
1642
static GEN
1643
veczetaprime(GEN a, GEN b, long N, long prec)
1644
{
1645
long B = prec2nbits(prec) / 2;
1646
GEN v, h = mkcomplex(gen_0, real2n(-B, prec));
1647
v = veczeta(a, gadd(b, h), N, prec);
1648
return gmul2n(imag_i(v), B);
1649
}
1650
1651
struct mon_w {
1652
GEN w, a, b;
1653
long n, j, prec;
1654
};
1655
1656
/* w(x) / x^(a*(j+k)+b), k >= 1; w a t_CLOSURE or t_INT [encodes log(x)^w] */
1657
static GEN
1658
wrapmonw(void* E, GEN x)
1659
{
1660
struct mon_w *W = (struct mon_w*)E;
1661
long k, j = W->j, n = W->n, prec = W->prec, l = 2*n+4-j;
1662
GEN wx = typ(W->w) == t_CLOSURE? closure_callgen1prec(W->w, x, prec)
1663
: powgi(glog(x, prec), W->w);
1664
GEN v = cgetg(l, t_VEC);
1665
GEN xa = gpow(x, gneg(W->a), prec), w = gmul(wx, gpowgs(xa, j));
1666
w = gdiv(w, gpow(x,W->b,prec));
1667
for (k = 1; k < l; k++) { gel(v,k) = w; w = gmul(w, xa); }
1668
return v;
1669
}
1670
/* w(x) / x^(a*j+b) */
1671
static GEN
1672
wrapmonw2(void* E, GEN x)
1673
{
1674
struct mon_w *W = (struct mon_w*)E;
1675
GEN wnx = closure_callgen1prec(W->w, x, W->prec);
1676
return gdiv(wnx, gpow(x, gadd(gmulgs(W->a, W->j), W->b), W->prec));
1677
}
1678
static GEN
1679
M_from_wrapmon(struct mon_w *S, GEN wfast, GEN n0)
1680
{
1681
long j, N = 2*S->n+2;
1682
GEN M = cgetg(N+1, t_VEC), faj = gsub(wfast, S->b);
1683
for (j = 1; j <= N; j++)
1684
{
1685
faj = gsub(faj, S->a);
1686
if (gcmpgs(faj, -2) <= 0)
1687
{
1688
S->j = j; setlg(M,j);
1689
M = shallowconcat(M, sumnum((void*)S, wrapmonw, n0, NULL, S->prec));
1690
break;
1691
}
1692
S->j = j;
1693
gel(M,j) = sumnum((void*)S, wrapmonw2, mkvec2(n0,faj), NULL, S->prec);
1694
}
1695
return M;
1696
}
1697
1698
static void
1699
checkmonroots(GEN vr, long n)
1700
{
1701
if (lg(vr) != n+1)
1702
pari_err_IMPL("recovery when missing roots in sumnummonieninit");
1703
}
1704
1705
static GEN
1706
sumnummonieninit_i(GEN a, GEN b, GEN w, GEN n0, long prec)
1707
{
1708
GEN c, M, P, Q, Qp, vr, vabs, vwt, ga = gadd(a, b);
1709
double bit = 2*prec2nbits(prec) / gtodouble(ga), D = bit*M_LN2;
1710
double da = maxdd(1., gtodouble(a));
1711
long n = (long)ceil(D / (da*(log(D)-1)));
1712
long j, prec2, prec0 = prec + EXTRAPREC64;
1713
double bit0 = ceil((2*n+1)*LOG2_10);
1714
int neg = 1;
1715
struct mon_w S;
1716
1717
/* 2.05 is heuristic; with 2.03, sumnummonien(n=1,1/n^2) loses
1718
* 19 decimals at \p1500 */
1719
prec = nbits2prec(maxdd(2.05*da*bit, bit0));
1720
prec2 = nbits2prec(maxdd(1.3*da*bit, bit0));
1721
S.w = w;
1722
S.a = a = gprec_wensure(a, 2*prec-2);
1723
S.b = b = gprec_wensure(b, 2*prec-2);
1724
S.n = n;
1725
S.j = 1;
1726
S.prec = prec;
1727
if (typ(w) == t_INT)
1728
{ /* f(n) ~ \sum_{i > 0} f_i log(n)^k / n^(a*i + b); a > 0, a+b > 1 */
1729
long k = itos(w);
1730
if (k == 0)
1731
M = veczeta(a, ga, 2*n+2, prec);
1732
else if (k == 1)
1733
M = veczetaprime(a, ga, 2*n+2, prec);
1734
else
1735
M = M_from_wrapmon(&S, gen_0, gen_1);
1736
if (odd(k)) neg = 0;
1737
}
1738
else
1739
{
1740
GEN wfast = gen_0;
1741
if (typ(w) == t_VEC) { wfast = gel(w,2); w = gel(w,1); }
1742
M = M_from_wrapmon(&S, wfast, n0);
1743
}
1744
/* M[j] = sum(n >= n0, w(n) / n^(a*j+b) */
1745
Pade(M, &P,&Q);
1746
Qp = RgX_deriv(Q);
1747
if (gequal1(a)) a = NULL;
1748
if (!a && typ(w) == t_INT)
1749
{
1750
vabs = vr = monroots(Q, Qp, signe(w)? 1: 0, prec2);
1751
checkmonroots(vr, n);
1752
c = b;
1753
}
1754
else
1755
{
1756
vr = RX_realroots(Q, prec2); settyp(vr, t_VEC);
1757
checkmonroots(vr, n);
1758
if (!a) { vabs = vr; c = b; }
1759
else
1760
{
1761
GEN ai = ginv(a);
1762
vabs = cgetg(n+1, t_VEC);
1763
for (j = 1; j <= n; j++) gel(vabs,j) = gpow(gel(vr,j), ai, prec2);
1764
c = gdiv(b,a);
1765
}
1766
}
1767
1768
vwt = cgetg(n+1, t_VEC);
1769
c = gsubgs(c,1); if (gequal0(c)) c = NULL;
1770
for (j = 1; j <= n; j++)
1771
{
1772
GEN r = gel(vr,j), t = gdiv(poleval(P,r), poleval(Qp,r));
1773
if (c) t = gmul(t, gpow(r, c, prec));
1774
gel(vwt,j) = neg? gneg(t): t;
1775
}
1776
if (typ(w) == t_INT && !equali1(n0))
1777
{
1778
GEN h = subiu(n0,1);
1779
for (j = 1; j <= n; j++) gel(vabs,j) = gadd(gel(vabs,j), h);
1780
}
1781
return mkvec3(gprec_wtrunc(vabs,prec0), gprec_wtrunc(vwt,prec0), n0);
1782
}
1783
1784
GEN
1785
sumnummonieninit(GEN asymp, GEN w, GEN n0, long prec)
1786
{
1787
pari_sp av = avma;
1788
const char *fun = "sumnummonieninit";
1789
GEN a, b;
1790
if (!n0) n0 = gen_1; else if (typ(n0) != t_INT) pari_err_TYPE(fun, n0);
1791
if (!asymp) a = b = gen_1;
1792
else
1793
{
1794
if (typ(asymp) == t_VEC)
1795
{
1796
if (lg(asymp) != 3) pari_err_TYPE(fun, asymp);
1797
a = gel(asymp,1);
1798
b = gel(asymp,2);
1799
}
1800
else
1801
{
1802
a = gen_1;
1803
b = asymp;
1804
}
1805
if (gsigne(a) <= 0) pari_err_DOMAIN(fun, "a", "<=", gen_0, a);
1806
if (!isinR(b)) pari_err_TYPE(fun, b);
1807
if (gcmpgs(gadd(a,b), 1) <= 0)
1808
pari_err_DOMAIN(fun, "a+b", "<=", gen_1, mkvec2(a,b));
1809
}
1810
if (!w) w = gen_0;
1811
else switch(typ(w))
1812
{
1813
case t_INT:
1814
if (signe(w) < 0) pari_err_IMPL("log power < 0 in sumnummonieninit");
1815
case t_CLOSURE: break;
1816
case t_VEC:
1817
if (lg(w) == 3 && typ(gel(w,1)) == t_CLOSURE) break;
1818
default: pari_err_TYPE(fun, w);
1819
}
1820
return gerepilecopy(av, sumnummonieninit_i(a, b, w, n0, prec));
1821
}
1822
1823
GEN
1824
sumnummonien(void *E, GEN (*eval)(void*,GEN), GEN n0, GEN tab, long prec)
1825
{
1826
pari_sp av = avma;
1827
GEN vabs, vwt, S;
1828
long l, i;
1829
if (typ(n0) != t_INT) pari_err_TYPE("sumnummonien", n0);
1830
if (!tab)
1831
tab = sumnummonieninit_i(gen_1, gen_1, gen_0, n0, prec);
1832
else
1833
{
1834
if (lg(tab) != 4 || typ(tab) != t_VEC) pari_err_TYPE("sumnummonien", tab);
1835
if (!equalii(n0, gel(tab,3)))
1836
pari_err(e_MISC, "incompatible initial value %Ps != %Ps", gel(tab,3),n0);
1837
}
1838
vabs= gel(tab,1); l = lg(vabs);
1839
vwt = gel(tab,2);
1840
if (typ(vabs) != t_VEC || typ(vwt) != t_VEC || lg(vwt) != l)
1841
pari_err_TYPE("sumnummonien", tab);
1842
S = gen_0;
1843
for (i = 1; i < l; i++)
1844
{
1845
S = gadd(S, gmul(gel(vwt,i), eval(E, gel(vabs,i))));
1846
S = gprec_wensure(S, prec);
1847
}
1848
return gerepilecopy(av, gprec_wtrunc(S, prec));
1849
}
1850
1851
static GEN
1852
get_oo(GEN fast) { return mkvec2(mkoo(), fast); }
1853
1854
GEN
1855
sumnuminit(GEN fast, long prec)
1856
{
1857
pari_sp av;
1858
GEN s, v, d, C, res = cgetg(6, t_VEC);
1859
long bitprec = prec2nbits(prec), N, k, k2, m;
1860
double w;
1861
1862
gel(res, 1) = d = mkfrac(gen_1, utoipos(4)); /* 1/4 */
1863
av = avma;
1864
w = gtodouble(glambertW(ginv(d), 0, LOWDEFAULTPREC));
1865
N = (long)ceil(M_LN2*bitprec/(w*(1+w))+5);
1866
k = (long)ceil(N*w); if (k&1) k--;
1867
1868
prec += EXTRAPREC64;
1869
k2 = k/2;
1870
s = RgX_to_ser(monomial(real_1(prec),1,0), k+3);
1871
s = gmul2n(gasinh(s, prec), 2); /* asinh(x)/d, d = 1/4 */
1872
gel(s, 2) = utoipos(4);
1873
s = gsub(ser_inv(gexpm1(s,prec)), ser_inv(s));
1874
C = matpascal(k-1);
1875
v = cgetg(k2+1, t_VEC);
1876
for (m = 1; m <= k2; m++)
1877
{
1878
pari_sp av = avma;
1879
GEN S = real_0(prec);
1880
long j;
1881
for (j = m; j <= k2; j++)
1882
{ /* s[X^(2j-1)] * binomial(2*j-1, j-m) */
1883
GEN t = gmul(gel(s,2*j+1), gcoeff(C, 2*j,j-m+1));
1884
t = gmul2n(t, 1-2*j);
1885
S = odd(j)? gsub(S,t): gadd(S,t);
1886
}
1887
if (odd(m)) S = gneg(S);
1888
gel(v,m) = gerepileupto(av, S);
1889
}
1890
v = RgC_gtofp(v,prec); settyp(v, t_VEC);
1891
gel(res, 4) = gerepileupto(av, v);
1892
gel(res, 2) = utoi(N);
1893
gel(res, 3) = utoi(k);
1894
if (!fast) fast = get_oo(gen_0);
1895
gel(res, 5) = intnuminit(gel(res,2), fast, 0, prec - EXTRAPREC64);
1896
return res;
1897
}
1898
1899
static int
1900
checksumtab(GEN T)
1901
{
1902
if (typ(T) != t_VEC || lg(T) != 6) return 0;
1903
return typ(gel(T,2))==t_INT && typ(gel(T,3))==t_INT && typ(gel(T,4))==t_VEC;
1904
}
1905
GEN
1906
sumnum(void *E, GEN (*eval)(void*, GEN), GEN a, GEN tab, long prec)
1907
{
1908
pari_sp av = avma, av2;
1909
GEN v, tabint, S, d, fast;
1910
long as, N, k, m, prec2;
1911
if (!a) { a = gen_1; fast = get_oo(gen_0); }
1912
else switch(typ(a))
1913
{
1914
case t_VEC:
1915
if (lg(a) != 3) pari_err_TYPE("sumnum", a);
1916
fast = get_oo(gel(a,2));
1917
a = gel(a,1); break;
1918
default:
1919
fast = get_oo(gen_0);
1920
}
1921
if (typ(a) != t_INT) pari_err_TYPE("sumnum", a);
1922
if (!tab) tab = sumnuminit(fast, prec);
1923
else if (!checksumtab(tab)) pari_err_TYPE("sumnum",tab);
1924
as = itos(a);
1925
d = gel(tab,1);
1926
N = maxss(as, itos(gel(tab,2)));
1927
k = itos(gel(tab,3));
1928
v = gel(tab,4);
1929
tabint = gel(tab,5);
1930
prec2 = prec+EXTRAPREC64;
1931
av2 = avma;
1932
S = gmul(eval(E, stoi(N)), real2n(-1,prec2));
1933
for (m = as; m < N; m++)
1934
{
1935
S = gadd(S, eval(E, stoi(m)));
1936
if (gc_needed(av, 2))
1937
{
1938
if (DEBUGMEM>1) pari_warn(warnmem,"sumnum [1], %ld/%ld",m,N);
1939
S = gerepileupto(av2, S);
1940
}
1941
S = gprec_wensure(S, prec2);
1942
}
1943
for (m = 1; m <= k/2; m++)
1944
{
1945
GEN t = gmulsg(2*m-1, d);
1946
GEN s = gsub(eval(E, gsubsg(N,t)), eval(E, gaddsg(N,t)));
1947
S = gadd(S, gmul(gel(v,m), s));
1948
if (gc_needed(av2, 2))
1949
{
1950
if (DEBUGMEM>1) pari_warn(warnmem,"sumnum [2], %ld/%ld",m,k/2);
1951
S = gerepileupto(av2, S);
1952
}
1953
S = gprec_wensure(S, prec2);
1954
}
1955
S = gadd(S, intnum(E, eval,stoi(N), fast, tabint, prec2));
1956
return gerepilecopy(av, gprec_wtrunc(S, prec));
1957
}
1958
1959
GEN
1960
sumnummonien0(GEN a, GEN code, GEN tab, long prec)
1961
{ EXPR_WRAP(code, sumnummonien(EXPR_ARG, a, tab, prec)); }
1962
GEN
1963
sumnum0(GEN a, GEN code, GEN tab, long prec)
1964
{ EXPR_WRAP(code, sumnum(EXPR_ARG, a, tab, prec)); }
1965
1966
/* Abel-Plana summation */
1967
1968
static GEN
1969
intnumgauexpinit(long prec)
1970
{
1971
pari_sp ltop = avma;
1972
GEN V, N, E, P, Q, R, vabs, vwt;
1973
long l, n, k, j, prec2, prec0 = prec + EXTRAPREC64, bit = prec2nbits(prec);
1974
1975
n = (long)ceil(bit*0.226);
1976
n |= 1; /* make n odd */
1977
prec = nbits2prec(1.5*bit + 32);
1978
prec2 = maxss(prec0, nbits2prec(1.15*bit + 32));
1979
constbern(n+3);
1980
V = cgetg(n + 4, t_VEC);
1981
for (k = 1; k <= n + 3; ++k)
1982
gel(V, k) = gtofp(gdivgs(bernfrac(2*k), odd(k)? 2*k: -2*k), prec);
1983
Pade(V, &P, &Q);
1984
N = RgX_recip(gsub(P, Q));
1985
E = RgX_recip(Q);
1986
R = gdivgs(gdiv(N, RgX_deriv(E)), 2);
1987
vabs = RX_realroots(E,prec2);
1988
l = lg(vabs); settyp(vabs, t_VEC);
1989
vwt = cgetg(l, t_VEC);
1990
for (j = 1; j < l; ++j)
1991
{
1992
GEN a = gel(vabs,j);
1993
gel(vwt, j) = gprec_wtrunc(poleval(R, a), prec0);
1994
gel(vabs, j) = gprec_wtrunc(sqrtr_abs(a), prec0);
1995
}
1996
return gerepilecopy(ltop, mkvec2(vabs, vwt));
1997
}
1998
1999
/* Compute \int_{-oo}^oo w(x)f(x) dx, where w(x)=x/(exp(2pi x)-1)
2000
* for x>0 and w(-x)=w(x). For Abel-Plana (sumnumap). */
2001
static GEN
2002
intnumgauexp(void *E, GEN (*eval)(void*,GEN), GEN gN, GEN tab, long prec)
2003
{
2004
pari_sp av = avma;
2005
GEN U = mkcomplex(gN, NULL), V = mkcomplex(gN, NULL), S = gen_0;
2006
GEN vabs = gel(tab, 1), vwt = gel(tab, 2);
2007
long l = lg(vabs), i;
2008
if (lg(vwt) != l || typ(vabs) != t_VEC || typ(vwt) != t_VEC)
2009
pari_err_TYPE("sumnumap", tab);
2010
for (i = 1; i < l; i++)
2011
{ /* I * (w_i/a_i) * (f(N + I*a_i) - f(N - I*a_i)) */
2012
GEN x = gel(vabs,i), w = gel(vwt,i), t;
2013
gel(U,2) = x;
2014
gel(V,2) = gneg(x);
2015
t = mulcxI(gsub(eval(E,U), eval(E,V)));
2016
S = gadd(S, gmul(gdiv(w,x), cxtoreal(t)));
2017
S = gprec_wensure(S, prec);
2018
}
2019
return gerepilecopy(av, gprec_wtrunc(S, prec));
2020
}
2021
2022
GEN
2023
sumnumapinit(GEN fast, long prec)
2024
{
2025
if (!fast) fast = mkoo();
2026
retmkvec2(intnumgauexpinit(prec), intnuminit(gen_1, fast, 0, prec));
2027
}
2028
2029
typedef struct {
2030
GEN (*f)(void *E, GEN);
2031
void *E;
2032
long N;
2033
} expfn;
2034
2035
/* f(Nx) */
2036
static GEN
2037
_exfn(void *E, GEN x)
2038
{
2039
expfn *S = (expfn*)E;
2040
return S->f(S->E, gmulsg(S->N, x));
2041
}
2042
2043
GEN
2044
sumnumap(void *E, GEN (*eval)(void*,GEN), GEN a, GEN tab, long prec)
2045
{
2046
pari_sp av = avma;
2047
expfn T;
2048
GEN S, fast, gN;
2049
long as, m, N;
2050
if (!a) { a = gen_1; fast = get_oo(gen_0); }
2051
else switch(typ(a))
2052
{
2053
case t_VEC:
2054
if (lg(a) != 3) pari_err_TYPE("sumnumap", a);
2055
fast = get_oo(gel(a,2));
2056
a = gel(a,1); break;
2057
default:
2058
fast = get_oo(gen_0);
2059
}
2060
if (typ(a) != t_INT) pari_err_TYPE("sumnumap", a);
2061
if (!tab) tab = sumnumapinit(fast, prec);
2062
else if (typ(tab) != t_VEC || lg(tab) != 3) pari_err_TYPE("sumnumap",tab);
2063
as = itos(a);
2064
T.N = N = maxss(as + 1, (long)ceil(prec2nbits(prec)*0.327));
2065
T.E = E;
2066
T.f = eval;
2067
gN = stoi(N);
2068
S = gtofp(gmul2n(eval(E, gN), -1), prec);
2069
for (m = as; m < N; ++m)
2070
{
2071
S = gadd(S, eval(E, stoi(m)));
2072
S = gprec_wensure(S, prec);
2073
}
2074
S = gadd(S, gmulsg(N, intnum(&T, &_exfn, gen_1, fast, gel(tab, 2), prec)));
2075
S = gadd(S, intnumgauexp(E, eval, gN, gel(tab, 1), prec));
2076
return gerepileupto(av, S);
2077
}
2078
2079
GEN
2080
sumnumap0(GEN a, GEN code, GEN tab, long prec)
2081
{ EXPR_WRAP(code, sumnumap(EXPR_ARG, a, tab, prec)); }
2082
2083
/* max (1, |zeros|), P a t_POL or scalar */
2084
static double
2085
polmax(GEN P)
2086
{
2087
pari_sp av = avma;
2088
double r;
2089
if (typ(P) != t_POL || degpol(P) <= 0) return 1.0;
2090
r = gtodouble(polrootsbound(P, NULL));
2091
return gc_double(av, maxdd(r, 1.0));
2092
}
2093
2094
/* max (1, |poles|), F a t_POL or t_RFRAC or scalar */
2095
static double
2096
ratpolemax(GEN F)
2097
{
2098
if (typ(F) == t_POL) return 1.0;
2099
return polmax(gel(F,2));
2100
}
2101
/* max (1, |poles|, |zeros|)) */
2102
static double
2103
ratpolemax2(GEN F)
2104
{
2105
if (typ(F) == t_POL) return polmax(F);
2106
return maxdd(polmax(gel(F,1)), polmax(gel(F,2)));
2107
}
2108
2109
static GEN
2110
sercoeff(GEN x, long n)
2111
{
2112
long N = n - valp(x);
2113
return (N < 0)? gen_0: gel(x,N+2);
2114
}
2115
2116
/* Compute the integral from N to infinity of a rational function F, deg(F) < -1
2117
* We must have N > 2 * r, r = max(1, |poles F|). */
2118
static GEN
2119
intnumainfrat(GEN F, long N, double r, long prec)
2120
{
2121
long B = prec2nbits(prec), v, k, lim;
2122
GEN S, ser;
2123
pari_sp av = avma;
2124
2125
lim = (long)ceil(B/log2(N/r));
2126
ser = gmul(F, real_1(prec + EXTRAPREC64));
2127
ser = rfracrecip_to_ser_absolute(ser, lim+2);
2128
v = valp(ser);
2129
S = gdivgs(sercoeff(ser,lim+1), lim*N);
2130
/* goes down to 2, but coeffs are 0 in degree < v */
2131
for (k = lim; k >= v; k--) /* S <- (S + coeff(ser,k)/(k-1)) / N */
2132
S = gdivgs(gadd(S, gdivgs(sercoeff(ser,k), k-1)), N);
2133
if (v-2) S = gdiv(S, powuu(N, v-2));
2134
return gerepilecopy(av, gprec_wtrunc(S, prec));
2135
}
2136
2137
static GEN
2138
rfrac_eval0(GEN R)
2139
{
2140
GEN N, n, D = gel(R,2), d = constant_coeff(D);
2141
if (gequal0(d)) return NULL;
2142
N = gel(R,1);
2143
n = typ(N)==t_POL? constant_coeff(N): N;
2144
return gdiv(n, d);
2145
}
2146
static GEN
2147
rfrac_eval(GEN R, GEN a)
2148
{
2149
GEN D = gel(R,2), d = poleval(D,a);
2150
return gequal0(d)? NULL: gdiv(poleval(gel(R,1),a), d);
2151
}
2152
/* R = \sum_i vR[i], eval at a omitting poles */
2153
static GEN
2154
RFRAC_eval(GEN R, GEN vR, GEN a)
2155
{
2156
GEN S = rfrac_eval(R,a);
2157
if (!S && vR)
2158
{
2159
long i, l = lg(vR);
2160
for (i = 1; i < l; i++)
2161
{
2162
GEN z = rfrac_eval(gel(vR,i), a);
2163
if (z) S = S? gadd(S,z): z;
2164
}
2165
}
2166
return S;
2167
}
2168
static GEN
2169
add_RFRAC_eval(GEN S, GEN R, GEN vR, GEN a)
2170
{
2171
GEN z = RFRAC_eval(R, vR, a);
2172
return z? gadd(S, z): S;
2173
}
2174
static GEN
2175
add_sumrfrac(GEN S, GEN R, GEN vR, long b)
2176
{
2177
long m;
2178
for (m = b; m >= 1; m--) S = add_RFRAC_eval(S,R,vR,utoipos(m));
2179
return S;
2180
}
2181
static void
2182
get_kN(long r, long B, long *pk, long *pN)
2183
{
2184
long k = maxss(50, (long)ceil(0.241*B));
2185
GEN z;
2186
if (k&1L) k++;
2187
*pk = k; constbern(k >> 1);
2188
z = sqrtnr_abs(gmul2n(gtofp(bernfrac(k), LOWDEFAULTPREC), B), k);
2189
*pN = maxss(2*r, r + 1 + itos(gceil(z)));
2190
}
2191
/* F a t_RFRAC, F0 = F(0) or NULL [pole], vF a vector of t_RFRAC summing to F
2192
* or NULL [F atomic] */
2193
static GEN
2194
sumnumrat_i(GEN F, GEN F0, GEN vF, long prec)
2195
{
2196
long B = prec2nbits(prec), vx, j, k, N;
2197
GEN S, S1, S2, intf, _1;
2198
double r;
2199
if (poldegree(F, -1) > -2) pari_err(e_MISC, "sum diverges in sumnumrat");
2200
vx = varn(gel(F,2));
2201
r = ratpolemax(F);
2202
get_kN((long)ceil(r), B, &k,&N);
2203
intf = intnumainfrat(F, N, r, prec);
2204
/* N > ratpolemax(F) is not a pole */
2205
_1 = real_1(prec);
2206
S1 = gmul2n(gmul(_1, gsubst(F, vx, utoipos(N))), -1);
2207
S1 = add_sumrfrac(S1, F, vF, N-1);
2208
if (F0) S1 = gadd(S1, F0);
2209
S = gmul(_1, gsubst(F, vx, gaddgs(pol_x(vx), N)));
2210
S = rfrac_to_ser(S, k + 2);
2211
S2 = gen_0;
2212
for (j = 2; j <= k; j += 2)
2213
S2 = gadd(S2, gmul(gdivgs(bernfrac(j),j), sercoeff(S, j-1)));
2214
return gadd(intf, gsub(S1, S2));
2215
}
2216
/* sum_{n >= a} F(n) */
2217
GEN
2218
sumnumrat(GEN F, GEN a, long prec)
2219
{
2220
pari_sp av = avma;
2221
long vx;
2222
GEN vF, F0;
2223
2224
switch(typ(F))
2225
{
2226
case t_RFRAC: break;
2227
case t_INT: case t_REAL: case t_COMPLEX: case t_POL:
2228
if (gequal0(F)) return real_0(prec);
2229
default: pari_err_TYPE("sumnumrat",F);
2230
}
2231
vx = varn(gel(F,2));
2232
switch(typ(a))
2233
{
2234
case t_INT:
2235
if (signe(a)) F = gsubst(F, vx, deg1pol_shallow(gen_1,a,vx));
2236
F0 = rfrac_eval0(F);
2237
vF = NULL;
2238
break;
2239
case t_INFINITY:
2240
if (inf_get_sign(a) == -1)
2241
{ /* F(x) + F(-x). Could divide degree by 2, as G(x^2): pb with poles */
2242
GEN F2 = gsubst(F, vx, RgX_neg(pol_x(vx)));
2243
vF = mkvec2(F,F2);
2244
F = gadd(F, F2);
2245
if (gequal0(F)) { set_avma(av); return real_0(prec); }
2246
F0 = rfrac_eval0(gel(vF,1));
2247
break;
2248
}
2249
default:
2250
pari_err_TYPE("sumnumrat",a);
2251
return NULL; /* LCOV_EXCL_LINE */
2252
}
2253
return gerepileupto(av, sumnumrat_i(F, F0, vF, prec));
2254
}
2255
/* deg ((a / b) - 1), assuming b a t_POL of positive degree in main variable */
2256
static long
2257
rfracm1_degree(GEN a, GEN b)
2258
{
2259
long da, db;
2260
if (typ(a) != t_POL || varn(a) != varn(b)) return 0;
2261
da = degpol(a);
2262
db = degpol(b); if (da != db) return maxss(da - db, 0);
2263
return degpol(RgX_sub(a,b)) - db;
2264
}
2265
2266
/* prod_{n >= a} F(n) */
2267
GEN
2268
prodnumrat(GEN F, long a, long prec)
2269
{
2270
pari_sp ltop = avma;
2271
long B = prec2nbits(prec), j, k, m, N, vx;
2272
GEN S, S1, S2, intf, G;
2273
double r;
2274
2275
switch(typ(F))
2276
{
2277
case t_RFRAC: break;
2278
case t_INT: case t_REAL: case t_COMPLEX: case t_POL:
2279
if (gequal1(F)) return real_1(prec);
2280
default: pari_err_TYPE("prodnumrat",F);
2281
}
2282
if (rfracm1_degree(gel(F,1), gel(F,2)) > -2)
2283
pari_err(e_MISC, "product diverges in prodnumrat");
2284
vx = varn(gel(F,2));
2285
if (a) F = gsubst(F, vx, gaddgs(pol_x(vx), a));
2286
r = ratpolemax2(F);
2287
get_kN((long)ceil(r), B, &k,&N);
2288
G = gdiv(deriv(F, vx), F);
2289
intf = intnumainfrat(gmul(pol_x(vx),G), N, r, prec);
2290
intf = gneg(gadd(intf, gmulsg(N, glog(gsubst(F, vx, stoi(N)), prec))));
2291
S = gmul(real_1(prec), gsubst(G, vx, gaddgs(pol_x(vx), N)));
2292
S = rfrac_to_ser(S, k + 2);
2293
S1 = gsqrt(gsubst(F, vx, utoipos(N)), prec);
2294
for (m = 0; m < N; m++) S1 = gmul(S1, gsubst(F, vx, utoi(m)));
2295
S2 = gen_0;
2296
for (j = 2; j <= k; j += 2)
2297
S2 = gadd(S2, gmul(gdivgs(bernfrac(j),j*(j-1)), sercoeff(S, j-2)));
2298
return gerepileupto(ltop, gmul(S1, gexp(gsub(intf, S2), prec)));
2299
}
2300
2301
/* fan = factoru(n); sum_{d | n} mu(d)/d * s[n/d] */
2302
static GEN
2303
sdmob(GEN s, long n, GEN fan)
2304
{
2305
GEN D = divisorsu_moebius(gel(fan,1)), S = sercoeff(s, n); /* d = 1 */
2306
long i, l = lg(D);
2307
for (i = 2; i < l; i++)
2308
S = gadd(S, gdivgs(sercoeff(s, n/labs(D[i])), D[i]));
2309
return S;
2310
}
2311
/* log (zeta(s) * prod_i (1 - P[i]^-s) */
2312
static GEN
2313
logzetan(GEN s, GEN P, long prec)
2314
{
2315
GEN Z = gzeta(s, prec);
2316
long i, l = lg(P);
2317
for (i = 1; i < l; i++) Z = gsub(Z, gdiv(Z, gpow(gel(P,i), s, prec)));
2318
return glog(Z, prec);
2319
}
2320
static GEN
2321
sumlogzeta(GEN ser, GEN s, GEN P, double rs, double lN, long vF, long lim,
2322
long prec)
2323
{
2324
GEN z = gen_0, v = vecfactoru_i(vF,lim);
2325
pari_sp av = avma;
2326
long i, n;
2327
if (typ(s) == t_INT) constbern((itos(s) * lim + 1) >> 1);
2328
for (n = lim, i = lg(v)-1; n >= vF; n--, i--)
2329
{
2330
GEN t = sdmob(ser, n, gel(v,i));
2331
if (!gequal0(t))
2332
{ /* (n Re(s) - 1) log2(N) bits cancel in logzetan */
2333
long prec2 = prec + nbits2extraprec((n*rs-1) * lN);
2334
GEN L = logzetan(gmulsg(n,gprec_wensure(s,prec2)), P, prec2);
2335
z = gerepileupto(av, gadd(z, gmul(L, t)));
2336
z = gprec_wensure(z, prec);
2337
}
2338
}
2339
return gprec_wtrunc(z, prec);
2340
}
2341
2342
static GEN
2343
rfrac_evalfp(GEN F, GEN x, long prec)
2344
{
2345
GEN N = gel(F,1), D = gel(F,2), a, b = poleval(D, x);
2346
a = (typ(N) == t_POL && varn(N) == varn(D))? poleval(N, x): N;
2347
if (typ(a) != t_INT || typ(b) != t_INT ||
2348
(lgefint(a) <= prec && lgefint(b) <= prec)) return gdiv(a, b);
2349
return rdivii(a, b, prec + EXTRAPRECWORD);
2350
}
2351
2352
/* { F(p^s): p in P, p >= a }, F t_RFRAC */
2353
static GEN
2354
vFps(GEN P, long a, GEN F, GEN s, long prec)
2355
{
2356
long i, j, l = lg(P);
2357
GEN v = cgetg(l, t_VEC);
2358
for (i = j = 1; i < l; i++)
2359
{
2360
GEN p = gel(P,i); if (cmpiu(p, a) < 0) continue;
2361
gel(v, j++) = rfrac_evalfp(F, gpow(p, s, prec), prec);
2362
}
2363
setlg(v, j); return v;
2364
}
2365
2366
static void
2367
euler_set_Fs(GEN *F, GEN *s)
2368
{
2369
if (!*s) *s = gen_1;
2370
if (typ(*F) == t_RFRAC)
2371
{
2372
long m;
2373
*F = rfrac_deflate_max(*F, &m);
2374
if (m != 1) *s = gmulgs(*s, m);
2375
}
2376
}
2377
/* sum_{p prime, p >= a} F(p^s), F rational function */
2378
GEN
2379
sumeulerrat(GEN F, GEN s, long a, long prec)
2380
{
2381
pari_sp av = avma;
2382
GEN ser, z, P;
2383
double r, rs, RS, lN;
2384
long B = prec2nbits(prec), prec2 = prec + EXTRAPREC64, vF, N, lim;
2385
2386
euler_set_Fs(&F, &s);
2387
switch(typ(F))
2388
{
2389
case t_RFRAC: break;
2390
case t_INT: case t_REAL: case t_COMPLEX: case t_POL:
2391
if (gequal0(F)) return real_0(prec);
2392
default: pari_err_TYPE("sumeulerrat",F);
2393
}
2394
/* F t_RFRAC */
2395
if (a < 2) a = 2;
2396
vF = -poldegree(F, -1);
2397
rs = gtodouble(real_i(s));
2398
r = polmax(gel(F,2));
2399
N = maxss(30, a); lN = log2((double)N);
2400
RS = maxdd(1./vF, log2(r) / lN);
2401
if (rs <= RS)
2402
pari_err_DOMAIN("sumeulerrat", "real(s)", "<=", dbltor(RS), dbltor(rs));
2403
lim = (long)ceil(B / (rs*lN - log2(r)));
2404
ser = gmul(real_1(prec2), F);
2405
ser = rfracrecip_to_ser_absolute(ser, lim+1);
2406
P = primes_interval(gen_2, utoipos(N));
2407
z = sumlogzeta(ser, s, P, rs, lN, vF, lim, prec);
2408
z = gadd(z, vecsum(vFps(P, a, F, s, prec)));
2409
return gerepilecopy(av, gprec_wtrunc(z, prec));
2410
}
2411
2412
/* F = N/D; return F'/F. Assume D a t_POL */
2413
static GEN
2414
rfrac_logderiv(GEN N, GEN D)
2415
{
2416
if (typ(N) != t_POL || varn(N) != varn(D)) return gdiv(gneg(RgX_deriv(D)), D);
2417
if (!degpol(D)) return gdiv(RgX_deriv(N), N);
2418
return gdiv(RgX_sub(RgX_mul(RgX_deriv(N), D), RgX_mul(RgX_deriv(D), N)),
2419
RgX_mul(N, D));
2420
}
2421
2422
/* prod_{p prime, p >= a} F(p^s), F rational function */
2423
GEN
2424
prodeulerrat(GEN F, GEN s, long a, long prec)
2425
{
2426
pari_sp ltop = avma;
2427
GEN DF, NF, ser, P, z;
2428
double r, rs, RS, lN;
2429
long B = prec2nbits(prec), prec2 = prec + EXTRAPREC64, vF, N, lim;
2430
2431
euler_set_Fs(&F, &s);
2432
switch(typ(F))
2433
{
2434
case t_RFRAC: break;
2435
case t_INT: case t_REAL: case t_COMPLEX: case t_POL:
2436
if (gequal1(F)) return real_1(prec);
2437
default: pari_err_TYPE("prodeulerrat",F);
2438
} /* F t_RFRAC */
2439
NF = gel(F, 1);
2440
DF = gel(F, 2);
2441
rs = gtodouble(real_i(s));
2442
vF = - rfracm1_degree(NF, DF);
2443
if (rs * vF <= 1) pari_err(e_MISC, "product diverges in prodeulerrat");
2444
r = ratpolemax2(F);
2445
N = maxss(maxss(30, a), (long)ceil(2*r)); lN = log2((double)N);
2446
RS = maxdd(1./vF, log2(r) / lN);
2447
if (rs <= RS)
2448
pari_err_DOMAIN("prodeulerrat", "real(s)", "<=", dbltor(RS), dbltor(rs));
2449
lim = (long)ceil(B / (rs*lN - log2(r)));
2450
(void)rfracrecip(&NF, &DF); /* returned value is 0 */
2451
if (!RgX_is_ZX(DF) || !is_pm1(gel(DF,2))
2452
|| lim * log2(r) > 4 * B) NF = gmul(NF, real_1(prec2));
2453
ser = integser(rfrac_to_ser(rfrac_logderiv(NF,DF), lim+3));
2454
/* ser = log f, f = F(1/x) + O(x^(lim+1)) */
2455
P = primes_interval(gen_2, utoipos(N));
2456
z = gexp(sumlogzeta(ser, s, P, rs, lN, vF, lim, prec), prec);
2457
z = gmul(z, vecprod(vFps(P, a, F, s, prec)));
2458
return gerepilecopy(ltop, gprec_wtrunc(z, prec));
2459
}
2460
2461
/* Compute $\sum_{n\ge a}c(n)$ using Lagrange extrapolation.
2462
Assume that the $N$-th remainder term of the series has a
2463
regular asymptotic expansion in integral powers of $1/N$. */
2464
static GEN
2465
sumnumlagrange1init(GEN c1, long flag, long prec)
2466
{
2467
pari_sp av = avma;
2468
GEN V, W, T;
2469
double c1d;
2470
long B = prec2nbits(prec), prec2;
2471
ulong n, N;
2472
c1d = c1 ? gtodouble(c1) : 0.332;
2473
N = (ulong)ceil(c1d*B); if ((N&1L) == 0) N++;
2474
prec2 = nbits2prec(B+(long)ceil(1.8444*N) + 16);
2475
W = vecbinomial(N);
2476
T = vecpowuu(N, N);
2477
V = cgetg(N+1, t_VEC); gel(V,N) = gel(T,N);
2478
for (n = N-1; n >= 1; n--)
2479
{
2480
pari_sp av = avma;
2481
GEN t = mulii(gel(W, n+1), gel(T,n));
2482
if (!odd(n)) togglesign_safe(&t);
2483
if (flag) t = addii(gel(V, n+1), t);
2484
gel(V, n) = gerepileuptoint(av, t);
2485
}
2486
V = gdiv(RgV_gtofp(V, prec2), mpfact(N));
2487
return gerepilecopy(av, mkvec4(gen_1, stoi(prec2), gen_1, V));
2488
}
2489
2490
static GEN
2491
sumnumlagrange2init(GEN c1, long flag, long prec)
2492
{
2493
pari_sp av = avma;
2494
GEN V, W, T, told;
2495
double c1d = c1 ? gtodouble(c1) : 0.228;
2496
long B = prec2nbits(prec), prec2;
2497
ulong n, N;
2498
2499
N = (ulong)ceil(c1d*B); if ((N&1L) == 0) N++;
2500
prec2 = nbits2prec(B+(long)ceil(1.18696*N) + 16);
2501
W = vecbinomial(2*N);
2502
T = vecpowuu(N, 2*N);
2503
V = cgetg(N+1, t_VEC); gel(V, N) = told = gel(T,N);
2504
for (n = N-1; n >= 1; n--)
2505
{
2506
GEN tnew = mulii(gel(W, N-n+1), gel(T,n));
2507
if (!odd(n)) togglesign_safe(&tnew);
2508
told = addii(told, tnew);
2509
if (flag) told = addii(gel(V, n+1), told);
2510
gel(V, n) = told; told = tnew;
2511
}
2512
V = gdiv(RgV_gtofp(V, prec2), mpfact(2*N));
2513
return gerepilecopy(av, mkvec4(gen_2, stoi(prec2), gen_1, V));
2514
}
2515
2516
static GEN
2517
_mpmul(GEN x, GEN y)
2518
{
2519
if (!x) return y;
2520
return y? mpmul(x, y): x;
2521
}
2522
/* Used only for al = 2, 1, 1/2, 1/3, 1/4. */
2523
static GEN
2524
sumnumlagrangeinit_i(GEN al, GEN c1, long flag, long prec)
2525
{
2526
pari_sp av = avma;
2527
GEN V, W;
2528
double c1d = 0.0, c2;
2529
long B = prec2nbits(prec), B1, prec2, dal;
2530
ulong j, n, N;
2531
2532
if (typ(al) == t_INT)
2533
{
2534
switch(itos_or_0(al))
2535
{
2536
case 1: return sumnumlagrange1init(c1, flag, prec);
2537
case 2: return sumnumlagrange2init(c1, flag, prec);
2538
default: pari_err_IMPL("sumnumlagrange for this alpha");
2539
}
2540
}
2541
if (typ(al) != t_FRAC) pari_err_TYPE("sumnumlagrangeinit",al);
2542
dal = itos_or_0(gel(al,2));
2543
if (dal > 4 || !equali1(gel(al,1)))
2544
pari_err_IMPL("sumnumlagrange for this alpha");
2545
switch(dal)
2546
{
2547
case 2: c2 = 2.6441; c1d = 0.62; break;
2548
case 3: c2 = 3.1578; c1d = 1.18; break;
2549
case 4: c2 = 3.5364; c1d = 3.00; break;
2550
default: return NULL; /* LCOV_EXCL_LINE */
2551
}
2552
if (c1)
2553
{
2554
c1d = gtodouble(c1);
2555
if (c1d <= 0)
2556
pari_err_DOMAIN("sumnumlagrangeinit", "c1", "<=", gen_0, c1);
2557
}
2558
N = (ulong)ceil(c1d*B); if ((N&1L) == 0) N++;
2559
B1 = B + (long)ceil(c2*N) + 16;
2560
prec2 = nbits2prec(B1);
2561
V = vecpowug(N, al, prec2);
2562
W = cgetg(N+1, t_VEC);
2563
for (n = 1; n <= N; ++n)
2564
{
2565
pari_sp av2 = avma;
2566
GEN t = NULL, vn = gel(V, n);
2567
for (j = 1; j <= N; j++)
2568
if (j != n) t = _mpmul(t, mpsub(vn, gel(V, j)));
2569
gel(W, n) = gerepileuptoleaf(av2, mpdiv(gpowgs(vn, N-1), t));
2570
}
2571
if (flag)
2572
for (n = N-1; n >= 1; n--) gel(W, n) = gadd(gel(W, n+1), gel(W, n));
2573
return gerepilecopy(av, mkvec4(al, stoi(prec2), gen_1, W));
2574
}
2575
2576
GEN
2577
sumnumlagrangeinit(GEN al, GEN c1, long prec)
2578
{
2579
pari_sp ltop = avma;
2580
GEN V, W, S, be;
2581
long n, prec2, fl, N;
2582
2583
if (!al) return sumnumlagrange1init(c1, 1, prec);
2584
if (typ(al) != t_VEC) al = mkvec2(gen_1, al);
2585
else if (lg(al) != 3) pari_err_TYPE("sumnumlagrangeinit",al);
2586
be = gel(al,2);
2587
al = gel(al,1);
2588
if (gequal0(be)) return sumnumlagrangeinit_i(al, c1, 1, prec);
2589
V = sumnumlagrangeinit_i(al, c1, 0, prec);
2590
switch(typ(be))
2591
{
2592
case t_CLOSURE: fl = 1; break;
2593
case t_INT: case t_FRAC: case t_REAL: fl = 0; break;
2594
default: pari_err_TYPE("sumnumlagrangeinit", be);
2595
return NULL; /* LCOV_EXCL_LINE */
2596
}
2597
prec2 = itos(gel(V, 2));
2598
W = gel(V, 4);
2599
N = lg(W) - 1;
2600
S = gen_0; V = cgetg(N+1, t_VEC);
2601
for (n = N; n >= 1; n--)
2602
{
2603
GEN tmp, gn = stoi(n);
2604
tmp = fl ? closure_callgen1prec(be, gn, prec2) : gpow(gn, gneg(be), prec2);
2605
tmp = gdiv(gel(W, n), tmp);
2606
S = gadd(S, tmp);
2607
gel(V, n) = (n == N)? tmp: gadd(gel(V, n+1), tmp);
2608
}
2609
return gerepilecopy(ltop, mkvec4(al, stoi(prec2), S, V));
2610
}
2611
2612
/* - sum_{n=1}^{as-1} f(n) */
2613
static GEN
2614
sumaux(void *E, GEN (*eval)(void*,GEN,long), long as, long prec)
2615
{
2616
GEN S = gen_0;
2617
long n;
2618
if (as > 1)
2619
{
2620
for (n = 1; n < as; ++n)
2621
{
2622
S = gadd(S, eval(E, stoi(n), prec));
2623
S = gprec_wensure(S, prec);
2624
}
2625
S = gneg(S);
2626
}
2627
else
2628
for (n = as; n <= 0; ++n)
2629
{
2630
S = gadd(S, eval(E, stoi(n), prec));
2631
S = gprec_wensure(S, prec);
2632
}
2633
return S;
2634
}
2635
2636
GEN
2637
sumnumlagrange(void *E, GEN (*eval)(void*,GEN,long), GEN a, GEN tab, long prec)
2638
{
2639
pari_sp av = avma;
2640
GEN s, S, al, V;
2641
long as, prec2;
2642
ulong n, l;
2643
2644
if (typ(a) != t_INT) pari_err_TYPE("sumnumlagrange", a);
2645
if (!tab) tab = sumnumlagrangeinit(NULL, tab, prec);
2646
else if (lg(tab) != 5 || typ(gel(tab,2)) != t_INT || typ(gel(tab,4)) != t_VEC)
2647
pari_err_TYPE("sumnumlagrange", tab);
2648
2649
as = itos(a);
2650
al = gel(tab, 1);
2651
prec2 = itos(gel(tab, 2));
2652
S = gel(tab, 3);
2653
V = gel(tab, 4);
2654
l = lg(V);
2655
if (gequal(al, gen_2))
2656
{
2657
s = sumaux(E, eval, as, prec2);
2658
as = 1;
2659
}
2660
else
2661
s = gen_0;
2662
for (n = 1; n < l; n++)
2663
{
2664
s = gadd(s, gmul(gel(V, n), eval(E, stoi(n+as-1), prec2)));
2665
s = gprec_wensure(s, prec);
2666
}
2667
if (!gequal1(S)) s = gdiv(s,S);
2668
return gerepilecopy(av, gprec_wtrunc(s, prec));
2669
}
2670
2671
GEN
2672
sumnumlagrange0(GEN a, GEN code, GEN tab, long prec)
2673
{ EXPR_WRAP(code, sumnumlagrange(EXPR_ARGPREC, a, tab, prec)); }
2674
2675