Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2000 The PARI group.12This file is part of the PARI/GP package.34PARI/GP is free software; you can redistribute it and/or modify it under the5terms of the GNU General Public License as published by the Free Software6Foundation; either version 2 of the License, or (at your option) any later7version. It is distributed in the hope that it will be useful, but WITHOUT8ANY WARRANTY WHATSOEVER.910Check the License for details. You should have received a copy of it, along11with the package; see the file 'COPYING'. If not, write to the Free Software12Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */1314#include "pari.h"15#include "paripriv.h"1617#define DEBUGLEVEL DEBUGLEVEL_intnum1819static GEN20intlin(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec);2122/********************************************************************/23/** NUMERICAL INTEGRATION (Romberg) **/24/********************************************************************/25typedef struct {26void *E;27GEN (*f)(void *E, GEN);28} invfun;2930/* 1/x^2 f(1/x) */31static GEN32_invf(void *E, GEN x)33{34invfun *S = (invfun*)E;35GEN y = ginv(x);36return gmul(S->f(S->E, y), gsqr(y));37}3839/* h and s are arrays of the same length L > D. The h[i] are (decreasing)40* step sizes, s[i] is the computed Riemann sum for step size h[i].41* Interpolate the last D+1 values so that s ~ polynomial in h of degree D.42* Guess that limit_{h->0} = s(0) */43static GEN44interp(GEN h, GEN s, long L, long bit, long D)45{46pari_sp av = avma;47long e1,e2;48GEN ss = polintspec(h + L-D, s + L-D, gen_0, D+1, &e2);4950e1 = gexpo(ss);51if (DEBUGLEVEL>2)52{53err_printf("romb: iteration %ld, guess: %Ps\n", L,ss);54err_printf("romb: relative error < 2^-%ld [target %ld bits]\n",e1-e2,bit);55}56if (e1-e2 <= bit && (L <= 10 || e1 >= -bit)) return gc_NULL(av);57return cxtoreal(ss);58}5960static GEN61qrom3(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long bit)62{63const long JMAX = 25, KLOC = 4;64GEN ss,s,h,p1,p2,qlint,del,x,sum;65long j, j1, it, sig, prec = nbits2prec(bit);6667a = gtofp(a,prec);68b = gtofp(b,prec);69qlint = subrr(b,a); sig = signe(qlint);70if (!sig) return gen_0;71if (sig < 0) { setabssign(qlint); swap(a,b); }7273s = new_chunk(JMAX+KLOC-1);74h = new_chunk(JMAX+KLOC-1);75gel(h,0) = real_1(prec);7677p1 = eval(E, a); if (p1 == a) p1 = rcopy(p1);78p2 = eval(E, b);79gel(s,0) = gmul2n(gmul(qlint,gadd(p1,p2)),-1);80for (it=1,j=1; j<JMAX; j++, it<<=1) /* it = 2^(j-1) */81{82pari_sp av, av2;83gel(h,j) = real2n(-2*j, prec); /* 2^(-2j) */84av = avma; del = divru(qlint,it);85x = addrr(a, shiftr(del,-1));86av2 = avma;87for (sum = gen_0, j1 = 1; j1 <= it; j1++, x = addrr(x,del))88{89sum = gadd(sum, eval(E, x));90if ((j1 & 0x1ff) == 0) gerepileall(av2, 2, &sum,&x);91}92sum = gmul(sum,del);93gel(s,j) = gerepileupto(av, gmul2n(gadd(gel(s,j-1), sum), -1));94if (j >= KLOC && (ss = interp(h, s, j, bit-j-6, KLOC)))95return gmulsg(sig,ss);96}97pari_err_IMPL("intnumromb recovery [too many iterations]");98return NULL; /* LCOV_EXCL_LINE */99}100101static GEN102qrom2(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long bit)103{104const long JMAX = 16, KLOC = 4;105GEN ss,s,h,p1,qlint,del,ddel,x,sum;106long j, j1, it, sig, prec = nbits2prec(bit);107108a = gtofp(a, prec);109b = gtofp(b, prec);110qlint = subrr(b,a); sig = signe(qlint);111if (!sig) return gen_0;112if (sig < 0) { setabssign(qlint); swap(a,b); }113114s = new_chunk(JMAX+KLOC-1);115h = new_chunk(JMAX+KLOC-1);116gel(h,0) = real_1(prec);117118p1 = shiftr(addrr(a,b),-1);119gel(s,0) = gmul(qlint, eval(E, p1));120for (it=1, j=1; j<JMAX; j++, it*=3) /* it = 3^(j-1) */121{122pari_sp av, av2;123gel(h,j) = divru(gel(h,j-1), 9); /* 3^(-2j) */124av = avma; del = divru(qlint,3*it); ddel = shiftr(del,1);125x = addrr(a, shiftr(del,-1));126av2 = avma;127for (sum = gen_0, j1 = 1; j1 <= it; j1++)128{129sum = gadd(sum, eval(E, x)); x = addrr(x,ddel);130sum = gadd(sum, eval(E, x)); x = addrr(x,del);131if ((j1 & 0x1ff) == 0) gerepileall(av2, 2, &sum,&x);132}133sum = gmul(sum,del); p1 = gdivgs(gel(s,j-1),3);134gel(s,j) = gerepileupto(av, gadd(p1,sum));135if (j >= KLOC && (ss = interp(h, s, j, bit-(3*j/2)+3, KLOC)))136return gmulsg(sig, ss);137}138pari_err_IMPL("intnumromb recovery [too many iterations]");139return NULL; /* LCOV_EXCL_LINE */140}141142/* integrate after change of variables x --> 1/x */143static GEN144qromi(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long bit)145{146GEN A = ginv(b), B = ginv(a);147invfun S;148S.f = eval;149S.E = E; return qrom2(&S, &_invf, A, B, bit);150}151152/* a < b, assume b "small" (< 100 say) */153static GEN154rom_bsmall(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long bit)155{156if (gcmpgs(a,-100) >= 0) return qrom2(E,eval,a,b,bit);157if (gcmpgs(b, -1) < 0) return qromi(E,eval,a,b,bit); /* a<-100, b<-1 */158/* a<-100, b>=-1, split at -1 */159return gadd(qromi(E,eval,a,gen_m1,bit),160qrom2(E,eval,gen_m1,b,bit));161}162163static GEN164rombint(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long bit)165{166long l = gcmp(b,a);167GEN z;168169if (!l) return gen_0;170if (l < 0) swap(a,b);171if (gcmpgs(b,100) >= 0)172{173if (gcmpgs(a,1) >= 0)174z = qromi(E,eval,a,b,bit);175else /* split at 1 */176z = gadd(rom_bsmall(E,eval,a,gen_1,bit), qromi(E,eval,gen_1,b,bit));177}178else179z = rom_bsmall(E,eval,a,b,bit);180if (l < 0) z = gneg(z);181return z;182}183184GEN185intnumromb_bitprec(void *E, GEN (*f)(void *, GEN), GEN a,GEN b, long fl, long B)186{187pari_sp av = avma;188GEN z;189switch(fl)190{191case 0: z = qrom3 (E, f, a, b, B); break;192case 1: z = rombint(E, f, a, b, B); break;193case 2: z = qromi (E, f, a, b, B); break;194case 3: z = qrom2 (E, f, a, b, B); break;195default: pari_err_FLAG("intnumromb"); return NULL; /* LCOV_EXCL_LINE */196}197return gerepileupto(av, z);198}199GEN200intnumromb(void *E, GEN (*f)(void *, GEN), GEN a, GEN b, long flag, long prec)201{ return intnumromb_bitprec(E,f,a,b,flag,prec2nbits(prec));}202GEN203intnumromb0_bitprec(GEN a, GEN b, GEN code, long flag, long bit)204{ EXPR_WRAP(code, intnumromb_bitprec(EXPR_ARG, a, b, flag, bit)); }205206/********************************************************************/207/** NUMERICAL INTEGRATION (Gauss-Legendre) **/208/********************************************************************/209/* N > 1; S[n] = n^2. If !last, Newton step z - P_N(z) / P'_N(z),210* else [z, (N-1)!P_{N-1}(z)]. */211static GEN212Legendrenext(long N, GEN z, GEN S, int last)213{214GEN q, Z, a, b, z2 = sqrr(z);215long n, n0, u;216217q = subrs(mulur(3, z2), 1);218if (odd(N))219{220n0 = 3;221a = mulrr(z2, subrs(mulur(5, q), 4));222b = q;223}224else225{226n0 = 2;227a = mulrr(q, z);228b = z;229}230for (n = n0, u = 2*n0 + 1; n < N; n += 2, u += 4)231{232b = subrr(mulur(u, a), mulir(gel(S,n), b));233a = subrr(mulur(u + 2, mulrr(z2, b)), mulir(gel(S,n+1), a));234}235q = divrr(a, subrr(a, mulur(N, b)));236Z = subrr(z, divrr(mulrr(subrs(z2, 1), q), mulur(N, z)));237return last? mkvec2(Z, mulrr(b, addrs(q, 1))): Z;238}239/* root ~ dz of Legendre polynomial P_N */240static GEN241Legendreroot(long N, double dz, GEN S, long bit)242{243GEN z = dbltor(dz);244long e = - dblexpo(1 - dz*dz), n = expu(bit + 32 - e) - 2;245long j, pr = 1 + e + ((bit - e) >> n);246for (j = 1; j <= n; j++)247{248pr = 2 * pr - e;249z = Legendrenext(N, rtor(z, nbits2prec(pr)), S, j == n);250}251return z;252}253GEN254intnumgaussinit(long N, long prec)255{256pari_sp av;257long N2, j, k, l, bit;258GEN res, V, W, F, S;259double d;260261prec += EXTRAPREC64;262bit = prec2nbits(prec);263if (N <= 0) { N = bit >> 2; if (odd(N)) N++; }264if (N == 1) retmkvec2(mkvec(gen_0), mkvec(gen_2));265res = cgetg(3, t_VEC);266if (N == 2)267{268GEN z = cgetr(prec);269gel(res,1) = mkvec(z);270gel(res,2) = mkvec(gen_1);271av = avma; affrr(divru(sqrtr(utor(3,prec)), 3), z);272return gc_const(av, res);273}274N2 = N >> 1; l = (N+3)>> 1;275gel(res,1) = V = cgetg(l, t_VEC);276gel(res,2) = W = cgetg(l, t_VEC);277gel(V,1) = odd(N)? gen_0: cgetr(prec);278gel(W,1) = cgetr(prec);279for (k = 2; k < l; k++) { gel(V,k) = cgetr(prec); gel(W,k) = cgetr(prec); }280av = avma; S = vecpowuu(N, 2); F = sqrr(mpfactr(N-1, prec));281if (!odd(N)) k = 1;282else283{284GEN c = divrr(sqrr(sqrr(mpfactr(N2, prec))), mulri(F, gel(S,N)));285shiftr_inplace(c, 2*N-1);286affrr(c, gel(W,1)); k = 2;287}288F = divri(shiftr(F, 1), gel(S,N));289d = 1 - (N-1) / pow((double)(2*N),3);290for (j = 4*N2-1; j >= 3; k++, j -= 4)291{292pari_sp av2 = avma;293GEN zw = Legendreroot(N, d * cos(M_PI * j / (4*N+2)), S, bit);294GEN z = gel(zw,1), w = gel(zw,2);295affrr(z, gel(V,k));296w = mulrr(F, divrr(subsr(1, sqrr(z)), sqrr(w)));297affrr(w, gel(W,k)); set_avma(av2);298}299return gc_const(av, res);300}301302GEN303intnumgauss(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec)304{305pari_sp ltop = avma;306GEN R, W, bma, bpa, S;307long n, i, prec2 = prec + EXTRAPREC64;308if (!tab)309tab = intnumgaussinit(0,prec);310else if (typ(tab) != t_INT)311{312if (typ(tab) != t_VEC || lg(tab) != 3313|| typ(gel(tab,1)) != t_VEC314|| typ(gel(tab,2)) != t_VEC315|| lg(gel(tab,1)) != lg(gel(tab,2)))316pari_err_TYPE("intnumgauss",tab);317}318else319tab = intnumgaussinit(itos(tab),prec);320321R = gel(tab,1); n = lg(R)-1;322W = gel(tab,2);323a = gprec_wensure(a, prec2);324b = gprec_wensure(b, prec2);325bma = gmul2n(gsub(b,a), -1); /* (b-a)/2 */326bpa = gadd(bma, a); /* (b+a)/2 */327if (!signe(gel(R,1)))328{ /* R[1] = 0, use middle node only once */329S = gmul(gel(W,1), eval(E, bpa));330i = 2;331}332else333{334S = gen_0;335i = 1;336}337for (; i <= n; ++i)338{339GEN h = gmul(bma, gel(R,i)); /* != 0 */340GEN P = eval(E, gadd(bpa, h));341GEN M = eval(E, gsub(bpa, h));342S = gadd(S, gmul(gel(W,i), gadd(P,M)));343S = gprec_wensure(S, prec2);344}345return gerepilecopy(ltop, gprec_wtrunc(gmul(bma,S), prec));346}347348GEN349intnumgauss0(GEN a, GEN b, GEN code, GEN tab, long prec)350{ EXPR_WRAP(code, intnumgauss(EXPR_ARG, a, b, tab, prec)); }351352/********************************************************************/353/** DOUBLE EXPONENTIAL INTEGRATION **/354/********************************************************************/355356typedef struct _intdata {357long bit; /* bit accuracy of current precision */358long l; /* table lengths */359GEN tabx0; /* abscissa phi(0) for t = 0 */360GEN tabw0; /* weight phi'(0) for t = 0 */361GEN tabxp; /* table of abscissas phi(kh) for k > 0 */362GEN tabwp; /* table of weights phi'(kh) for k > 0 */363GEN tabxm; /* table of abscissas phi(kh) for k < 0, possibly empty */364GEN tabwm; /* table of weights phi'(kh) for k < 0, possibly empty */365GEN h; /* integration step */366} intdata;367368static const long LGTAB = 8;369#define TABh(v) gel(v,1)370#define TABx0(v) gel(v,2)371#define TABw0(v) gel(v,3)372#define TABxp(v) gel(v,4)373#define TABwp(v) gel(v,5)374#define TABxm(v) gel(v,6)375#define TABwm(v) gel(v,7)376377static int378isinR(GEN z) { return is_real_t(typ(z)); }379static int380isinC(GEN z)381{ return (typ(z) == t_COMPLEX)? isinR(gel(z,1)) && isinR(gel(z,2)): isinR(z); }382383static int384checktabsimp(GEN tab)385{386long L, LN, LW;387if (!tab || typ(tab) != t_VEC) return 0;388if (lg(tab) != LGTAB) return 0;389if (typ(TABxp(tab)) != t_VEC) return 0;390if (typ(TABwp(tab)) != t_VEC) return 0;391if (typ(TABxm(tab)) != t_VEC) return 0;392if (typ(TABwm(tab)) != t_VEC) return 0;393L = lg(TABxp(tab)); if (lg(TABwp(tab)) != L) return 0;394LN = lg(TABxm(tab)); if (LN != 1 && LN != L) return 0;395LW = lg(TABwm(tab)); if (LW != 1 && LW != L) return 0;396return 1;397}398399static int400checktabdoub(GEN tab)401{402long L;403if (typ(tab) != t_VEC) return 0;404if (lg(tab) != LGTAB) return 0;405L = lg(TABxp(tab));406if (lg(TABwp(tab)) != L) return 0;407if (lg(TABxm(tab)) != L) return 0;408if (lg(TABwm(tab)) != L) return 0;409return 1;410}411412static int413checktab(GEN tab)414{415if (typ(tab) != t_VEC) return 0;416if (lg(tab) != 3) return checktabsimp(tab);417return checktabsimp(gel(tab,1))418&& checktabsimp(gel(tab,2));419}420421/* the TUNE parameter is heuristic */422static void423intinit_start(intdata *D, long m, double TUNE, long prec)424{425long l, n, bitprec = prec2nbits(prec);426double d = bitprec*LOG10_2;427GEN h, nh, pi = mppi(prec);428429n = (long)ceil(d*log(d) / TUNE); /* heuristic */430/* nh ~ log(2npi/log(n)) */431nh = logr_abs(divrr(mulur(2*n, pi), logr_abs(utor(n,prec))));432h = divru(nh, n);433if (m > 0) { h = gmul2n(h,-m); n <<= m; }434D->h = h;435D->bit = bitprec;436D->l = l = n+1;437D->tabxp = cgetg(l, t_VEC);438D->tabwp = cgetg(l, t_VEC);439D->tabxm = cgetg(l, t_VEC);440D->tabwm = cgetg(l, t_VEC);441}442443static GEN444intinit_end(intdata *D, long pnt, long mnt)445{446GEN v = cgetg(LGTAB, t_VEC);447if (pnt < 0) pari_err_DOMAIN("intnuminit","table length","<",gen_0,stoi(pnt));448TABx0(v) = D->tabx0;449TABw0(v) = D->tabw0;450TABh(v) = D->h;451TABxp(v) = D->tabxp; setlg(D->tabxp, pnt+1);452TABwp(v) = D->tabwp; setlg(D->tabwp, pnt+1);453TABxm(v) = D->tabxm; setlg(D->tabxm, mnt+1);454TABwm(v) = D->tabwm; setlg(D->tabwm, mnt+1); return v;455}456457/* divide by 2 in place */458static GEN459divr2_ip(GEN x) { shiftr_inplace(x, -1); return x; }460461/* phi(t)=tanh((Pi/2)sinh(t)): from -1 to 1, hence also from a to b compact462* interval */463static GEN464inittanhsinh(long m, long prec)465{466GEN e, ei, ek, eik, pi = mppi(prec);467long k, nt = -1;468intdata D;469470intinit_start(&D, m, 1.86, prec);471D.tabx0 = real_0(prec);472D.tabw0 = Pi2n(-1,prec);473e = mpexp(D.h); ek = mulrr(pi, e);474ei = invr(e); eik = mulrr(pi, ei);475for (k = 1; k < D.l; k++)476{477GEN xp, wp, ct, st, z;478pari_sp av;479gel(D.tabxp,k) = cgetr(prec);480gel(D.tabwp,k) = cgetr(prec); av = avma;481ct = divr2_ip(addrr(ek, eik)); /* Pi ch(kh) */482st = subrr(ek, ct); /* Pi sh(kh) */483z = invr( addrs(mpexp(st), 1) );484shiftr_inplace(z, 1); if (expo(z) < -D.bit) { nt = k-1; break; }485xp = subsr(1, z);486wp = divr2_ip(mulrr(ct, subsr(1, sqrr(xp))));487affrr(xp, gel(D.tabxp,k)); mulrrz(ek, e, ek);488affrr(wp, gel(D.tabwp,k)); mulrrz(eik, ei, eik); set_avma(av);489}490return intinit_end(&D, nt, 0);491}492493/* phi(t)=sinh(sinh(t)): from -oo to oo, slowly decreasing, at least494* as 1/x^2. */495static GEN496initsinhsinh(long m, long prec)497{498pari_sp av;499GEN et, ct, st, ex;500long k, nt = -1;501intdata D;502503intinit_start(&D, m, 0.666, prec);504D.tabx0 = real_0(prec);505D.tabw0 = real_1(prec);506et = ex = mpexp(D.h);507for (k = 1; k < D.l; k++)508{509GEN xp, wp, ext, exu;510gel(D.tabxp,k) = cgetr(prec);511gel(D.tabwp,k) = cgetr(prec); av = avma;512ct = divr2_ip(addrr(et, invr(et)));513st = subrr(et, ct);514ext = mpexp(st);515exu = invr(ext);516xp = divr2_ip(subrr(ext, exu));517wp = divr2_ip(mulrr(ct, addrr(ext, exu)));518if (expo(wp) - 2*expo(xp) < -D.bit) { nt = k-1; break; }519affrr(xp, gel(D.tabxp,k));520affrr(wp, gel(D.tabwp,k)); et = gerepileuptoleaf(av, mulrr(et, ex));521}522return intinit_end(&D, nt, 0);523}524525/* phi(t)=2sinh(t): from -oo to oo, exponentially decreasing as exp(-x) */526static GEN527initsinh(long m, long prec)528{529pari_sp av;530GEN et, ex, eti, xp, wp;531long k, nt = -1;532intdata D;533534intinit_start(&D, m, 1.0, prec);535D.tabx0 = real_0(prec);536D.tabw0 = real2n(1, prec);537et = ex = mpexp(D.h);538for (k = 1; k < D.l; k++)539{540gel(D.tabxp,k) = cgetr(prec);541gel(D.tabwp,k) = cgetr(prec); av = avma;542eti = invr(et);543xp = subrr(et, eti);544wp = addrr(et, eti);545if (cmprs(xp, (long)(M_LN2*(expo(wp)+D.bit) + 1)) > 0) { nt = k-1; break; }546affrr(xp, gel(D.tabxp,k));547affrr(wp, gel(D.tabwp,k)); et = gerepileuptoleaf(av, mulrr(et, ex));548}549return intinit_end(&D, nt, 0);550}551552/* phi(t)=exp(2sinh(t)): from 0 to oo, slowly decreasing at least as 1/x^2 */553static GEN554initexpsinh(long m, long prec)555{556GEN et, ex;557long k, nt = -1;558intdata D;559560intinit_start(&D, m, 1.05, prec);561D.tabx0 = real_1(prec);562D.tabw0 = real2n(1, prec);563ex = mpexp(D.h);564et = real_1(prec);565for (k = 1; k < D.l; k++)566{567GEN t, eti, xp;568et = mulrr(et, ex);569eti = invr(et); t = addrr(et, eti);570xp = mpexp(subrr(et, eti));571gel(D.tabxp,k) = xp;572gel(D.tabwp,k) = mulrr(xp, t);573gel(D.tabxm,k) = invr(xp);574gel(D.tabwm,k) = mulrr(gel(D.tabxm,k), t);575if (expo(gel(D.tabxm,k)) < -D.bit) { nt = k-1; break; }576}577return intinit_end(&D, nt, nt);578}579580/* phi(t)=exp(t-exp(-t)) : from 0 to +oo, exponentially decreasing. */581static GEN582initexpexp(long m, long prec)583{584pari_sp av;585GEN et, ex;586long k, nt = -1;587intdata D;588589intinit_start(&D, m, 1.76, prec);590D.tabx0 = mpexp(real_m1(prec));591D.tabw0 = gmul2n(D.tabx0, 1);592et = ex = mpexp(negr(D.h));593for (k = 1; k < D.l; k++)594{595GEN xp, xm, wp, wm, eti, kh;596gel(D.tabxp,k) = cgetr(prec);597gel(D.tabwp,k) = cgetr(prec);598gel(D.tabxm,k) = cgetr(prec);599gel(D.tabwm,k) = cgetr(prec); av = avma;600eti = invr(et); kh = mulur(k,D.h);601xp = mpexp(subrr(kh, et));602xm = mpexp(negr(addrr(kh, eti)));603wp = mulrr(xp, addsr(1, et));604if (expo(xm) < -D.bit && cmprs(xp, (long)(M_LN2*(expo(wp)+D.bit) + 1)) > 0) { nt = k-1; break; }605wm = mulrr(xm, addsr(1, eti));606affrr(xp, gel(D.tabxp,k));607affrr(wp, gel(D.tabwp,k));608affrr(xm, gel(D.tabxm,k));609affrr(wm, gel(D.tabwm,k)); et = gerepileuptoleaf(av, mulrr(et, ex));610}611return intinit_end(&D, nt, nt);612}613614/* phi(t)=(Pi/h)*t/(1-exp(-sinh(t))) from 0 to oo, sine oscillation */615static GEN616initnumsine(long m, long prec)617{618pari_sp av;619GEN invh, et, eti, ex, pi = mppi(prec);620long exh, k, nt = -1;621intdata D;622623intinit_start(&D, m, 0.666, prec);624invh = invr(D.h);625D.tabx0 = mulrr(pi, invh);626D.tabw0 = gmul2n(D.tabx0,-1);627exh = expo(invh); /* expo(1/h) */628et = ex = mpexp(D.h);629for (k = 1; k < D.l; k++)630{631GEN xp,xm, wp,wm, ct,st, extp,extp1,extp2, extm,extm1,extm2, kct, kpi;632gel(D.tabxp,k) = cgetr(prec);633gel(D.tabwp,k) = cgetr(prec);634gel(D.tabxm,k) = cgetr(prec);635gel(D.tabwm,k) = cgetr(prec); av = avma;636eti = invr(et); /* exp(-kh) */637ct = divr2_ip(addrr(et, eti)); /* ch(kh) */638st = divr2_ip(subrr(et, eti)); /* sh(kh) */639extp = mpexp(st); extp1 = subsr(1, extp);640extp2 = invr(extp1); /* 1/(1-exp(sh(kh))) */641extm = invr(extp); extm1 = subsr(1, extm);642extm2 = invr(extm1);/* 1/(1-exp(sh(-kh))) */643kpi = mulur(k, pi);644kct = mulur(k, ct);645extm1 = mulrr(extm1, invh);646extp1 = mulrr(extp1, invh);647xp = mulrr(kpi, extm2); /* phi(kh) */648wp = mulrr(subrr(extm1, mulrr(kct, extm)), mulrr(pi, sqrr(extm2)));649xm = mulrr(negr(kpi), extp2); /* phi(-kh) */650wm = mulrr(addrr(extp1, mulrr(kct, extp)), mulrr(pi, sqrr(extp2)));651if (expo(wm) < -D.bit && expo(extm) + exh + expu(10 * k) < -D.bit) { nt = k-1; break; }652affrr(xp, gel(D.tabxp,k));653affrr(wp, gel(D.tabwp,k));654affrr(xm, gel(D.tabxm,k));655affrr(wm, gel(D.tabwm,k)); et = gerepileuptoleaf(av, mulrr(et, ex));656}657return intinit_end(&D, nt, nt);658}659660/* End of initialization functions. These functions can be executed once661* and for all for a given accuracy and type of integral ([a,b], [a,oo[ or662* ]-oo,a], ]-oo,oo[) */663664/* The numbers below can be changed, but NOT the ordering */665enum {666f_REG = 0, /* regular function */667f_SER = 1, /* power series */668f_SINGSER = 2, /* algebraic singularity, power series endpoint */669f_SING = 3, /* algebraic singularity */670f_YSLOW = 4, /* oo, slowly decreasing, at least x^(-2) */671f_YVSLO = 5, /* oo, very slowly decreasing, worse than x^(-2) */672f_YFAST = 6, /* oo, exponentially decreasing */673f_YOSCS = 7, /* oo, sine oscillating */674f_YOSCC = 8 /* oo, cosine oscillating */675};676/* is finite ? */677static int678is_fin_f(long c) { return c == f_REG || c == f_SER || c == f_SING; }679/* is oscillatory ? */680static int681is_osc(long c) { long a = labs(c); return a == f_YOSCC|| a == f_YOSCS; }682683/* All inner functions such as intn, etc... must be called with a684* valid 'tab' table. The wrapper intnum provides a higher level interface */685686/* compute \int_a^b f(t)dt with [a,b] compact and f nonsingular. */687static GEN688intn(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab)689{690GEN tabx0, tabw0, tabxp, tabwp;691GEN bpa, bma, bmb, S;692long i, prec;693pari_sp ltop = avma, av;694695if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab);696tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0);697tabxp = TABxp(tab); tabwp = TABwp(tab);698bpa = gmul2n(gadd(b, a), -1); /* (b+a)/2 */699bma = gsub(bpa, a); /* (b-a)/2 */700av = avma;701bmb = gmul(bma, tabx0); /* (b-a)/2 phi(0) */702/* phi'(0) f( (b+a)/2 + (b-a)/2 * phi(0) ) */703S = gmul(tabw0, eval(E, gadd(bpa, bmb)));704for (i = lg(tabxp)-1; i > 0; i--)705{706GEN SP, SM;707bmb = gmul(bma, gel(tabxp,i));708SP = eval(E, gsub(bpa, bmb));709SM = eval(E, gadd(bpa, bmb));710S = gadd(S, gmul(gel(tabwp,i), gadd(SP, SM)));711if ((i & 0x7f) == 1) S = gerepileupto(av, S);712S = gprec_wensure(S, prec);713}714return gerepileupto(ltop, gmul(S, gmul(bma, TABh(tab))));715}716717/* compute \int_a^b f(t)dt with [a,b] compact, possible singularity with718* exponent a[2] at lower extremity, b regular. Use tanh(sinh(t)). */719static GEN720intnsing(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab)721{722GEN tabx0, tabw0, tabxp, tabwp, ea, ba, S;723long i, prec;724pari_sp ltop = avma, av;725726if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab);727tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0);728tabxp = TABxp(tab); tabwp = TABwp(tab);729ea = ginv(gaddsg(1, gel(a,2)));730a = gel(a,1);731ba = gdiv(gsub(b, a), gpow(gen_2, ea, prec));732av = avma;733S = gmul(gmul(tabw0, ba), eval(E, gadd(gmul(ba, addsr(1, tabx0)), a)));734for (i = lg(tabxp)-1; i > 0; i--)735{736GEN p = addsr(1, gel(tabxp,i));737GEN m = subsr(1, gel(tabxp,i));738GEN bp = gmul(ba, gpow(p, ea, prec));739GEN bm = gmul(ba, gpow(m, ea, prec));740GEN SP = gmul(gdiv(bp, p), eval(E, gadd(bp, a)));741GEN SM = gmul(gdiv(bm, m), eval(E, gadd(bm, a)));742S = gadd(S, gmul(gel(tabwp,i), gadd(SP, SM)));743if ((i & 0x7f) == 1) S = gerepileupto(av, S);744S = gprec_wensure(S, prec);745}746return gerepileupto(ltop, gmul(gmul(S, TABh(tab)), ea));747}748749static GEN id(GEN x) { return x; }750751/* compute \int_a^oo f(t)dt if si>0 or \int_{-oo}^a f(t)dt if si<0$.752* Use exp(2sinh(t)) for slowly decreasing functions, exp(1+t-exp(-t)) for753* exponentially decreasing functions, and (pi/h)t/(1-exp(-sinh(t))) for754* oscillating functions. */755static GEN756intninfpm(void *E, GEN (*eval)(void*, GEN), GEN a, long sb, GEN tab)757{758GEN tabx0, tabw0, tabxp, tabwp, tabxm, tabwm;759GEN S;760long L, i, prec;761pari_sp av = avma;762763if (!checktabdoub(tab)) pari_err_TYPE("intnum",tab);764tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0);765tabxp = TABxp(tab); tabwp = TABwp(tab); L = lg(tabxp);766tabxm = TABxm(tab); tabwm = TABwm(tab);767if (gequal0(a))768{769GEN (*NEG)(GEN) = sb > 0? id: gneg;770S = gmul(tabw0, eval(E, NEG(tabx0)));771for (i = 1; i < L; i++)772{773GEN SP = eval(E, NEG(gel(tabxp,i)));774GEN SM = eval(E, NEG(gel(tabxm,i)));775S = gadd(S, gadd(gmul(gel(tabwp,i), SP), gmul(gel(tabwm,i), SM)));776if ((i & 0x7f) == 1) S = gerepileupto(av, S);777S = gprec_wensure(S, prec);778}779}780else if (gexpo(a) <= 0 || is_osc(sb))781{ /* a small */782GEN (*ADD)(GEN,GEN) = sb > 0? gadd: gsub;783S = gmul(tabw0, eval(E, ADD(a, tabx0)));784for (i = 1; i < L; i++)785{786GEN SP = eval(E, ADD(a, gel(tabxp,i)));787GEN SM = eval(E, ADD(a, gel(tabxm,i)));788S = gadd(S, gadd(gmul(gel(tabwp,i), SP), gmul(gel(tabwm,i), SM)));789if ((i & 0x7f) == 1) S = gerepileupto(av, S);790S = gprec_wensure(S, prec);791}792}793else794{ /* a large, |a|*\int_sgn(a)^{oo} f(|a|*x)dx (sb > 0)*/795GEN (*ADD)(long,GEN) = sb > 0? addsr: subsr;796long sa = gsigne(a);797GEN A = sa > 0? a: gneg(a);798pari_sp av2 = avma;799S = gmul(tabw0, eval(E, gmul(A, ADD(sa, tabx0))));800for (i = 1; i < L; i++)801{802GEN SP = eval(E, gmul(A, ADD(sa, gel(tabxp,i))));803GEN SM = eval(E, gmul(A, ADD(sa, gel(tabxm,i))));804S = gadd(S, gadd(gmul(gel(tabwp,i), SP), gmul(gel(tabwm,i), SM)));805if ((i & 0x7f) == 1) S = gerepileupto(av2, S);806S = gprec_wensure(S, prec);807}808S = gmul(S,A);809}810return gerepileupto(av, gmul(S, TABh(tab)));811}812813/* Compute \int_{-oo}^oo f(t)dt814* use sinh(sinh(t)) for slowly decreasing functions and sinh(t) for815* exponentially decreasing functions.816* HACK: in case TABwm(tab) contains something, assume function to be integrated817* satisfies f(-x) = conj(f(x)).818*/819static GEN820intninfinf(void *E, GEN (*eval)(void*, GEN), GEN tab)821{822GEN tabx0, tabw0, tabxp, tabwp, tabwm;823GEN S;824long L, i, prec, spf;825pari_sp ltop = avma;826827if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab);828tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0);829tabxp = TABxp(tab); tabwp = TABwp(tab); L = lg(tabxp);830tabwm = TABwm(tab);831spf = (lg(tabwm) == lg(tabwp));832S = gmul(tabw0, eval(E, tabx0));833if (spf) S = gmul2n(real_i(S), -1);834for (i = L-1; i > 0; i--)835{836GEN SP = eval(E, gel(tabxp,i));837if (spf)838S = gadd(S, real_i(gmul(gel(tabwp,i), SP)));839else840{841GEN SM = eval(E, negr(gel(tabxp,i)));842S = gadd(S, gmul(gel(tabwp,i), gadd(SP,SM)));843}844if ((i & 0x7f) == 1) S = gerepileupto(ltop, S);845S = gprec_wensure(S, prec);846}847if (spf) S = gmul2n(S,1);848return gerepileupto(ltop, gmul(S, TABh(tab)));849}850851/* general num integration routine int_a^b f(t)dt, where a and b are as follows:852- a scalar : the scalar, no singularity worse than logarithmic at a.853- [a, e] : the scalar a, singularity exponent -1 < e <= 0.854- +oo: slowly decreasing function (at least O(t^-2))855- [[+oo], a], a nonnegative real : +oo, function behaving like exp(-a|t|)856- [[+oo], e], e < -1 : +oo, function behaving like t^e857- [[+oo], a*I], a > 0 real : +oo, function behaving like cos(at)858- [[+oo], a*I], a < 0 real : +oo, function behaving like sin(at)859and similarly at -oo */860static GEN861f_getycplx(GEN a, long prec)862{863GEN a2R, a2I;864long s;865866if (lg(a) == 2 || gequal0(gel(a,2))) return gen_1;867a2R = real_i(gel(a,2));868a2I = imag_i(gel(a,2));869s = gsigne(a2I); if (s < 0) a2I = gneg(a2I);870return ginv(gprec_wensure(s ? a2I : a2R, prec));871}872873static void874err_code(GEN a, const char *name)875{876char *s = stack_sprintf("intnum [incorrect %s]", name);877pari_err_TYPE(s, a);878}879880/* a = [[+/-oo], alpha]*/881static long882code_aux(GEN a, const char *name)883{884GEN re, im, alpha = gel(a,2);885long s;886if (!isinC(alpha)) err_code(a, name);887re = real_i(alpha);888im = imag_i(alpha);889s = gsigne(im);890if (s)891{892if (!gequal0(re)) err_code(a, name);893return s > 0 ? f_YOSCC : f_YOSCS;894}895if (gequal0(re) || gcmpgs(re, -2)<=0) return f_YSLOW;896if (gsigne(re) > 0) return f_YFAST;897if (gcmpgs(re, -1) >= 0) err_code(a, name);898return f_YVSLO;899}900901static long902transcode(GEN a, const char *name)903{904GEN a1, a2;905switch(typ(a))906{907case t_VEC: break;908case t_INFINITY:909return inf_get_sign(a) == 1 ? f_YSLOW: -f_YSLOW;910case t_SER: case t_POL: case t_RFRAC:911return f_SER;912default: if (!isinC(a)) err_code(a,name);913return f_REG;914}915switch(lg(a))916{917case 2: return gsigne(gel(a,1)) > 0 ? f_YSLOW : -f_YSLOW;918case 3: break;919default: err_code(a,name);920}921a1 = gel(a,1);922a2 = gel(a,2);923switch(typ(a1))924{925case t_VEC:926if (lg(a1) != 2) err_code(a,name);927return gsigne(gel(a1,1)) * code_aux(a, name);928case t_INFINITY:929return inf_get_sign(a1) * code_aux(a, name);930case t_SER: case t_POL: case t_RFRAC:931if (!isinR(a2)) err_code(a,name);932if (gcmpgs(a2, -1) <= 0)933pari_err_IMPL("intnum with diverging non constant limit");934return gsigne(a2) < 0 ? f_SINGSER : f_SER;935default:936if (!isinC(a1) || !isinR(a2) || gcmpgs(a2, -1) <= 0) err_code(a,name);937return gsigne(a2) < 0 ? f_SING : f_REG;938}939}940941/* computes the necessary tabs, knowing a, b and m */942static GEN943homtab(GEN tab, GEN k)944{945GEN z;946if (gequal0(k) || gequal(k, gen_1)) return tab;947if (gsigne(k) < 0) k = gneg(k);948z = cgetg(LGTAB, t_VEC);949TABx0(z) = gmul(TABx0(tab), k);950TABw0(z) = gmul(TABw0(tab), k);951TABxp(z) = gmul(TABxp(tab), k);952TABwp(z) = gmul(TABwp(tab), k);953TABxm(z) = gmul(TABxm(tab), k);954TABwm(z) = gmul(TABwm(tab), k);955TABh(z) = rcopy(TABh(tab)); return z;956}957958static GEN959expvec(GEN v, GEN ea, long prec)960{961long lv = lg(v), i;962GEN z = cgetg(lv, t_VEC);963for (i = 1; i < lv; i++) gel(z,i) = gpow(gel(v,i),ea,prec);964return z;965}966967static GEN968expscalpr(GEN vnew, GEN xold, GEN wold, GEN ea)969{970pari_sp av = avma;971return gerepileupto(av, gdiv(gmul(gmul(vnew, wold), ea), xold));972}973static GEN974expvecpr(GEN vnew, GEN xold, GEN wold, GEN ea)975{976long lv = lg(vnew), i;977GEN z = cgetg(lv, t_VEC);978for (i = 1; i < lv; i++)979gel(z,i) = expscalpr(gel(vnew,i), gel(xold,i), gel(wold,i), ea);980return z;981}982983/* here k < -1 */984static GEN985exptab(GEN tab, GEN k, long prec)986{987GEN v, ea;988989if (gcmpgs(k, -2) <= 0) return tab;990ea = ginv(gsubsg(-1, k));991v = cgetg(LGTAB, t_VEC);992TABx0(v) = gpow(TABx0(tab), ea, prec);993TABw0(v) = expscalpr(TABx0(v), TABx0(tab), TABw0(tab), ea);994TABxp(v) = expvec(TABxp(tab), ea, prec);995TABwp(v) = expvecpr(TABxp(v), TABxp(tab), TABwp(tab), ea);996TABxm(v) = expvec(TABxm(tab), ea, prec);997TABwm(v) = expvecpr(TABxm(v), TABxm(tab), TABwm(tab), ea);998TABh(v) = rcopy(TABh(tab));999return v;1000}10011002static GEN1003init_fin(GEN b, long codeb, long m, long l, long prec)1004{1005switch(labs(codeb))1006{1007case f_REG:1008case f_SING: return inittanhsinh(m,l);1009case f_YSLOW: return initexpsinh(m,l);1010case f_YVSLO: return exptab(initexpsinh(m,l), gel(b,2), prec);1011case f_YFAST: return homtab(initexpexp(m,l), f_getycplx(b,l));1012/* f_YOSCS, f_YOSCC */1013default: return homtab(initnumsine(m,l),f_getycplx(b,l));1014}1015}10161017static GEN1018intnuminit_i(GEN a, GEN b, long m, long prec)1019{1020long codea, codeb, l;1021GEN T, kma, kmb, tmp;10221023if (m > 30) pari_err_OVERFLOW("intnuminit [m]");1024if (m < 0) pari_err_DOMAIN("intnuminit", "m", "<", gen_0, stoi(m));1025l = prec+EXTRAPREC64;1026codea = transcode(a, "a"); if (codea == f_SER) codea = f_REG;1027codeb = transcode(b, "b"); if (codeb == f_SER) codeb = f_REG;1028if (codea == f_SINGSER || codeb == f_SINGSER)1029pari_err_IMPL("intnuminit with singularity at non constant limit");1030if (labs(codea) > labs(codeb)) { swap(a, b); lswap(codea, codeb); }1031if (codea == f_REG)1032{1033T = init_fin(b, codeb, m,l,prec);1034switch(labs(codeb))1035{1036case f_YOSCS: if (gequal0(a)) break;1037case f_YOSCC: T = mkvec2(inittanhsinh(m,l), T);1038}1039return T;1040}1041if (codea == f_SING)1042{1043T = init_fin(b,codeb, m,l,prec);1044T = mkvec2(labs(codeb) == f_SING? T: inittanhsinh(m,l), T);1045return T;1046}1047/* now a and b are infinite */1048if (codea * codeb > 0) return gen_0;1049kma = f_getycplx(a,l); codea = labs(codea);1050kmb = f_getycplx(b,l); codeb = labs(codeb);1051if (codea == f_YSLOW && codeb == f_YSLOW) return initsinhsinh(m, l);1052if (codea == f_YFAST && codeb == f_YFAST && gequal(kma, kmb))1053return homtab(initsinh(m,l), kmb);1054T = cgetg(3, t_VEC);1055switch (codea)1056{1057case f_YSLOW:1058case f_YVSLO:1059tmp = initexpsinh(m,l);1060gel(T,1) = codea == f_YSLOW? tmp: exptab(tmp, gel(a,2), prec);1061switch (codeb)1062{1063case f_YVSLO: gel(T,2) = exptab(tmp, gel(b,2), prec); return T;1064case f_YFAST: gel(T,2) = homtab(initexpexp(m,l), kmb); return T;1065/* YOSC[CS] */1066default: gel(T,2) = homtab(initnumsine(m,l), kmb); return T;1067}1068break;1069case f_YFAST:1070tmp = initexpexp(m, l);1071gel(T,1) = homtab(tmp, kma);1072switch (codeb)1073{1074case f_YFAST: gel(T,2) = homtab(tmp, kmb); return T;1075/* YOSC[CS] */1076default: gel(T,2) = homtab(initnumsine(m, l), kmb); return T;1077}1078default: /* YOSC[CS] */1079tmp = initnumsine(m, l);1080gel(T,1) = homtab(tmp,kma);1081if (codea == f_YOSCC && codeb == f_YOSCC && !gequal(kma, kmb))1082gel(T,2) = mkvec2(inittanhsinh(m,l), homtab(tmp,kmb));1083else1084gel(T,2) = homtab(tmp,kmb);1085return T;1086}1087}1088GEN1089intnuminit(GEN a, GEN b, long m, long prec)1090{1091pari_sp av = avma;1092return gerepilecopy(av, intnuminit_i(a,b,m,prec));1093}10941095static GEN1096intnuminit0(GEN a, GEN b, GEN tab, long prec)1097{1098long m;1099if (!tab) m = 0;1100else if (typ(tab) != t_INT)1101{1102if (!checktab(tab)) pari_err_TYPE("intnuminit0",tab);1103return tab;1104}1105else1106m = itos(tab);1107return intnuminit(a, b, m, prec);1108}11091110/* Assigns the values of the function weighted by w[k] at quadrature points x[k]1111* [replacing the weights]. Return the index of the last nonzero coeff */1112static long1113weight(void *E, GEN (*eval)(void *, GEN), GEN x, GEN w)1114{1115long k, l = lg(x);1116for (k = 1; k < l; k++) gel(w,k) = gmul(gel(w,k), eval(E, gel(x,k)));1117k--; while (k >= 1) if (!gequal0(gel(w,k--))) break;1118return k;1119}1120/* compute the necessary tabs, weights multiplied by f(t) */1121static GEN1122intfuncinit_i(void *E, GEN (*eval)(void*, GEN), GEN tab)1123{1124GEN tabxp = TABxp(tab), tabwp = TABwp(tab);1125GEN tabxm = TABxm(tab), tabwm = TABwm(tab);1126long L, L0 = lg(tabxp);11271128TABw0(tab) = gmul(TABw0(tab), eval(E, TABx0(tab)));1129if (lg(tabxm) == 1)1130{1131TABxm(tab) = tabxm = gneg(tabxp);1132TABwm(tab) = tabwm = leafcopy(tabwp);1133}1134/* update wp and wm in place */1135L = minss(weight(E, eval, tabxp, tabwp), weight(E, eval, tabxm, tabwm));1136if (L < L0)1137{ /* catch up functions whose growth at oo was not adequately described */1138setlg(tabxp, L+1);1139setlg(tabwp, L+1);1140if (lg(tabxm) > 1) { setlg(tabxm, L+1); setlg(tabwm, L+1); }1141}1142return tab;1143}11441145GEN1146intfuncinit(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long m, long prec)1147{1148pari_sp av = avma;1149GEN tab = intnuminit_i(a, b, m, prec);11501151if (lg(tab) == 3)1152pari_err_IMPL("intfuncinit with hard endpoint behavior");1153if (is_fin_f(transcode(a,"intfuncinit")) ||1154is_fin_f(transcode(b,"intfuncinit")))1155pari_err_IMPL("intfuncinit with finite endpoints");1156return gerepilecopy(av, intfuncinit_i(E, eval, tab));1157}11581159static GEN1160intnum_i(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec)1161{1162GEN S = gen_0, kma, kmb;1163long sb, sgns = 1, codea = transcode(a, "a"), codeb = transcode(b, "b");11641165if (codea == f_REG && typ(a) == t_VEC) a = gel(a,1);1166if (codeb == f_REG && typ(b) == t_VEC) b = gel(b,1);1167if (codea == f_REG && codeb == f_REG) return intn(E, eval, a, b, tab);1168if (codea == f_SER || codeb == f_SER) return intlin(E, eval, a, b, tab, prec);1169if (labs(codea) > labs(codeb)) { swap(a,b); lswap(codea,codeb); sgns = -1; }1170/* now labs(codea) <= labs(codeb) */1171if (codeb == f_SING)1172{1173if (codea == f_REG)1174S = intnsing(E, eval, b, a, tab), sgns = -sgns;1175else1176{1177GEN c = gmul2n(gadd(gel(a,1), gel(b,1)), -1);1178S = gsub(intnsing(E, eval, a, c, gel(tab,1)),1179intnsing(E, eval, b, c, gel(tab,2)));1180}1181return (sgns < 0) ? gneg(S) : S;1182}1183/* now b is infinite */1184sb = codeb > 0 ? 1 : -1;1185codeb = labs(codeb);1186if (codea == f_REG && codeb != f_YOSCC1187&& (codeb != f_YOSCS || gequal0(a)))1188{1189S = intninfpm(E, eval, a, sb*codeb, tab);1190return sgns*sb < 0 ? gneg(S) : S;1191}1192if (is_fin_f(codea))1193{ /* either codea == f_SING or codea == f_REG and codeb = f_YOSCC1194* or (codeb == f_YOSCS and !gequal0(a)) */1195GEN S2, c = real_i(codea == f_SING? gel(a,1): a);1196switch(codeb)1197{1198case f_YOSCC: case f_YOSCS:1199{1200GEN pi2p = gmul(Pi2n(1,prec), f_getycplx(b, prec));1201GEN pis2p = gmul2n(pi2p, -2);1202if (codeb == f_YOSCC) c = gadd(c, pis2p);1203c = gdiv(c, pi2p);1204c = sb > 0? addiu(gceil(c), 1): subiu(gfloor(c), 1);1205c = gmul(pi2p, c);1206if (codeb == f_YOSCC) c = gsub(c, pis2p);1207break;1208}1209default:1210c = sb > 0? addiu(gceil(c), 1): subiu(gfloor(c), 1);1211break;1212}1213S = codea==f_SING? intnsing(E, eval, a, c, gel(tab,1))1214: intn (E, eval, a, c, gel(tab,1));1215S2 = intninfpm(E, eval, c, sb*codeb, gel(tab,2));1216if (sb < 0) S2 = gneg(S2);1217S = gadd(S, S2);1218return sgns < 0 ? gneg(S) : S;1219}1220/* now a and b are infinite */1221if (codea * sb > 0)1222{1223if (codea > 0) pari_warn(warner, "integral from oo to oo");1224if (codea < 0) pari_warn(warner, "integral from -oo to -oo");1225return gen_0;1226}1227if (sb < 0) sgns = -sgns;1228codea = labs(codea);1229kma = f_getycplx(a, prec);1230kmb = f_getycplx(b, prec);1231if ((codea == f_YSLOW && codeb == f_YSLOW)1232|| (codea == f_YFAST && codeb == f_YFAST && gequal(kma, kmb)))1233S = intninfinf(E, eval, tab);1234else1235{1236GEN pis2 = Pi2n(-1, prec);1237GEN ca = (codea == f_YOSCC)? gmul(pis2, kma): gen_0;1238GEN cb = (codeb == f_YOSCC)? gmul(pis2, kmb): gen_0;1239GEN c = codea == f_YOSCC ? ca : cb; /*signe(a)=-sb*/1240GEN SP, SN = intninfpm(E, eval, c, -sb*codea, gel(tab,1));1241if (codea != f_YOSCC)1242SP = intninfpm(E, eval, cb, sb*codeb, gel(tab,2));1243/* codea = codeb = f_YOSCC */1244else if (gequal(kma, kmb))1245SP = intninfpm(E, eval, cb, sb*codeb, gel(tab,2));1246else1247{1248tab = gel(tab,2);1249SP = intninfpm(E, eval, cb, sb*codeb, gel(tab,2));1250SP = gadd(SP, intn(E, eval, ca, cb, gel(tab,1)));1251}1252S = gadd(SN, SP);1253}1254if (sgns < 0) S = gneg(S);1255return S;1256}12571258GEN1259intnum(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec)1260{1261pari_sp ltop = avma;1262long l = prec+EXTRAPREC64;1263GEN na = NULL, nb = NULL, S;12641265if (transcode(a,"a") == f_SINGSER) {1266long v = gvar(gel(a,1));1267if (v != NO_VARIABLE) {1268na = cgetg(3,t_VEC);1269gel(na,1) = polcoef(gel(a,1),0,v);1270gel(na,2) = gel(a,2);1271}1272a = gel(a,1);1273}1274if (transcode(b,"b") == f_SINGSER) {1275long v = gvar(gel(b,1));1276if (v != NO_VARIABLE) {1277nb = cgetg(3,t_VEC);1278gel(nb,1) = polcoef(gel(b,1),0,v);1279gel(nb,2) = gel(b,2);1280}1281b = gel(b,1);1282}1283if (na || nb) {1284if (tab && typ(tab) != t_INT)1285pari_err_IMPL("non integer tab argument");1286S = intnum(E, eval, na ? na : a, nb ? nb : b, tab, prec);1287if (na) S = gsub(S, intnum(E, eval, na, a, tab, prec));1288if (nb) S = gsub(S, intnum(E, eval, b, nb, tab, prec));1289return gerepilecopy(ltop, S);1290}1291tab = intnuminit0(a, b, tab, prec);1292S = intnum_i(E, eval, gprec_wensure(a, l), gprec_wensure(b, l), tab, prec);1293return gerepilecopy(ltop, gprec_wtrunc(S, prec));1294}12951296typedef struct auxint_s {1297GEN a, R, mult;1298GEN (*f)(void*, GEN);1299GEN (*w)(GEN, long);1300long prec;1301void *E;1302} auxint_t;13031304static GEN1305auxcirc(void *E, GEN t)1306{1307auxint_t *D = (auxint_t*) E;1308GEN s, c, z;1309mpsincos(mulrr(t, D->mult), &s, &c); z = mkcomplex(c,s);1310return gmul(z, D->f(D->E, gadd(D->a, gmul(D->R, z))));1311}13121313GEN1314intcirc(void *E, GEN (*eval)(void*, GEN), GEN a, GEN R, GEN tab, long prec)1315{1316auxint_t D;1317GEN z;13181319D.a = a;1320D.R = R;1321D.mult = mppi(prec);1322D.f = eval;1323D.E = E;1324z = intnum(&D, &auxcirc, real_m1(prec), real_1(prec), tab, prec);1325return gmul2n(gmul(R, z), -1);1326}13271328static GEN1329auxlin(void *E, GEN t)1330{1331auxint_t *D = (auxint_t*) E;1332return D->f(D->E, gadd(D->a, gmul(D->mult, t)));1333}13341335static GEN1336intlin(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec)1337{1338auxint_t D;1339GEN z;13401341if (typ(a) == t_VEC) a = gel(a,1);1342if (typ(b) == t_VEC) b = gel(b,1);1343z = toser_i(a); if (z) a = z;1344z = toser_i(b); if (z) b = z;1345D.a = a;1346D.mult = gsub(b,a);1347D.f = eval;1348D.E = E;1349z = intnum(&D, &auxlin, real_0(prec), real_1(prec), tab, prec);1350return gmul(D.mult, z);1351}13521353GEN1354intnum0(GEN a, GEN b, GEN code, GEN tab, long prec)1355{ EXPR_WRAP(code, intnum(EXPR_ARG, a, b, tab, prec)); }1356GEN1357intcirc0(GEN a, GEN R, GEN code, GEN tab, long prec)1358{ EXPR_WRAP(code, intcirc(EXPR_ARG, a, R, tab, prec)); }1359GEN1360intfuncinit0(GEN a, GEN b, GEN code, long m, long prec)1361{ EXPR_WRAP(code, intfuncinit(EXPR_ARG, a, b, m, prec)); }13621363#if 01364/* Two variable integration */13651366typedef struct auxf_s {1367GEN x;1368GEN (*f)(void *, GEN, GEN);1369void *E;1370} auxf_t;13711372typedef struct indi_s {1373GEN (*c)(void*, GEN);1374GEN (*d)(void*, GEN);1375GEN (*f)(void *, GEN, GEN);1376void *Ec;1377void *Ed;1378void *Ef;1379GEN tabintern;1380long prec;1381} indi_t;13821383static GEN1384auxf(GEN y, void *E)1385{1386auxf_t *D = (auxf_t*) E;1387return D->f(D->E, D->x, y);1388}13891390static GEN1391intnumdoubintern(GEN x, void *E)1392{1393indi_t *D = (indi_t*) E;1394GEN c = D->c(x, D->Ec), d = D->d(x, D->Ed);1395auxf_t A;13961397A.x = x;1398A.f = D->f;1399A.E = D->Ef;1400return intnum(&A, &auxf, c, d, D->tabintern, D->prec);1401}14021403GEN1404intnumdoub(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)1405{1406indi_t E;14071408E.c = evalc;1409E.d = evald;1410E.f = evalf;1411E.Ec = Ec;1412E.Ed = Ed;1413E.Ef = Ef;1414E.prec = prec;1415if (typ(tabint) == t_INT)1416{1417GEN C = evalc(a, Ec), D = evald(a, Ed);1418if (typ(C) != t_VEC && typ(D) != t_VEC) { C = gen_0; D = gen_1; }1419E.tabintern = intnuminit0(C, D, tabint, prec);1420}1421else E.tabintern = tabint;1422return intnum(&E, &intnumdoubintern, a, b, tabext, prec);1423}14241425GEN1426intnumdoub0(GEN a, GEN b, int nc, int nd, int nf, GEN tabext, GEN tabint, long prec)1427{1428GEN z;1429push_lex(NULL);1430push_lex(NULL);1431z = intnumdoub(chf, &gp_eval2, chc, &gp_eval, chd, &gp_eval, a, b, tabext, tabint, prec);1432pop_lex(1); pop_lex(1); return z;1433}1434#endif14351436/* Given a continued fraction C output by QD convert it into an Euler1437* continued fraction A(n), B(n), where1438* 1 / (1 + C[2]z / (1+C[3]z / (1+..C[lim]z)))1439* = 1 / (1+A[1]*z+B[1]*z^2/(1+A[2]*z+B[2]*z^2/(1+...1/(1+A[lim\2]*z)))). */1440static GEN1441contfrac_Euler(GEN C)1442{1443long i, n = lg(C) - 1, a = n/2, b = (n - 1)/2;1444GEN A = cgetg(a+1, t_VEC), B = cgetg(b+1, t_VEC);1445gel(A,1) = gel(C,2);1446if (!b) return mkvec2(A, B);1447gel(B,1) = gneg(gmul(gel(C,3), gel(C,2)));1448for (i = 2; i <= b; i++)1449{1450GEN u = gel(C,2*i);1451gel(A,i) = gadd(u, gel(C, 2*i-1));1452gel(B,i) = gneg(gmul(gel(C, 2*i+1), u));1453}1454if (a != b) gel(A,a) = gadd(gel(C, 2*a), gel(C, 2*a-1));1455return mkvec2(A, B);1456}14571458/* The quotient-difference algorithm. Given a vector M, convert the series1459* S = sum_{n >= 0} M[n+1] z^n into a continued fraction.1460* Compute the c[n] such that1461* S = c[1] / (1 + c[2]z / (1+c[3]z/(1+...c[lim]z))),1462* Assume lim <= #M. Does not work for certain M. */1463static GEN1464QD(GEN M, long lim)1465{1466pari_sp av;1467GEN e, q, c;1468long lim2, j, k;1469e = zerovec(lim);1470c = zerovec(lim+1); gel(c, 1) = gel(M, 1);1471q = cgetg(lim+1, t_VEC);1472for (k = 1; k <= lim; ++k) gel(q, k) = gdiv(gel(M, k+1), gel(M, k));1473lim2 = lim/2; av = avma;1474for (j = 1; j <= lim2; ++j)1475{1476long l = lim - 2*j;1477gel(c, 2*j) = gneg(gel(q, 1));1478for (k = 0; k <= l; ++k)1479gel(e, k+1) = gsub(gadd(gel(e, k+2), gel(q, k+2)), gel(q, k+1));1480for (k = 0; k < l; ++k)1481gel(q, k+1) = gdiv(gmul(gel(q, k+2), gel(e, k+2)), gel(e, k+1));1482gel(c, 2*j+1) = gneg(gel(e, 1));1483if (gc_needed(av, 3))1484{1485if (DEBUGMEM>1) pari_warn(warnmem,"contfracinit, %ld/%ld",j,lim2);1486gerepileall(av, 3, &e, &c, &q);1487}1488}1489if (odd(lim)) gel(c, lim+1) = gneg(gel(q, 1));1490return c;1491}14921493static GEN1494quodif_i(GEN M, long n)1495{1496switch(typ(M))1497{1498case t_RFRAC:1499if (n < 0) pari_err_TYPE("contfracinit",M);1500M = gtoser(M, varn(gel(M,2)), n+3); /*fall through*/1501case t_SER: M = gtovec(M); break;1502case t_POL: M = RgX_to_RgC(M, degpol(M)+1); break;1503case t_VEC: case t_COL: break;1504default: pari_err_TYPE("contfracinit", M);1505}1506if (n < 0)1507{1508n = lg(M)-2;1509if (n < 0) return cgetg(1,t_VEC);1510}1511else if (lg(M)-1 <= n)1512pari_err_COMPONENT("contfracinit", "<", stoi(lg(M)-1), stoi(n));1513return QD(M, n);1514}1515GEN1516quodif(GEN M, long n)1517{1518pari_sp av = avma;1519return gerepilecopy(av, quodif_i(M, n));1520}1521GEN1522contfracinit(GEN M, long n)1523{1524pari_sp av = avma;1525GEN C = quodif_i(M, n);1526if (lg(C) < 3) { set_avma(av); retmkvec2(cgetg(1,t_VEC), cgetg(1,t_VEC)); }1527return gerepilecopy(av, contfrac_Euler(C));1528}15291530/* Evaluate at 1/tinv the nlim first terms of the continued fraction output by1531* contfracinit. Shallow. */1532GEN1533contfraceval_inv(GEN CF, GEN tinv, long nlim)1534{1535pari_sp av;1536long j;1537GEN S = gen_0, S1, S2, A, B;1538if (typ(CF) != t_VEC || lg(CF) != 3) pari_err_TYPE("contfraceval", CF);1539A = gel(CF, 1); if (typ(A) != t_VEC) pari_err_TYPE("contfraceval", CF);1540B = gel(CF, 2); if (typ(B) != t_VEC) pari_err_TYPE("contfraceval", CF);1541if (nlim < 0)1542nlim = lg(A)-1;1543else if (lg(A) <= nlim)1544pari_err_COMPONENT("contfraceval", ">", stoi(lg(A)-1), stoi(nlim));1545if (lg(B)+1 <= nlim)1546pari_err_COMPONENT("contfraceval", ">", stoi(lg(B)), stoi(nlim));1547av = avma;1548if (nlim <= 1) return lg(A)==1? gen_0: gdiv(tinv, gadd(gel(A, 1), tinv));1549switch(nlim % 3)1550{1551case 2:1552S = gdiv(gel(B, nlim-1), gadd(gel(A, nlim), tinv));1553nlim--; break;15541555case 0:1556S1 = gadd(gel(A, nlim), tinv);1557S2 = gadd(gmul(gadd(gel(A, nlim-1), tinv), S1), gel(B, nlim-1));1558S = gdiv(gmul(gel(B, nlim-2), S1), S2);1559nlim -= 2; break;1560}1561/* nlim = 1 (mod 3) */1562for (j = nlim; j >= 4; j -= 3)1563{1564GEN S3;1565S1 = gadd(gadd(gel(A, j), tinv), S);1566S2 = gadd(gmul(gadd(gel(A, j-1), tinv), S1), gel(B, j-1));1567S3 = gadd(gmul(gadd(gel(A, j-2), tinv), S2), gmul(gel(B, j-2), S1));1568S = gdiv(gmul(gel(B, j-3), S2), S3);1569if (gc_needed(av, 3)) S = gerepilecopy(av, S);1570}1571return gdiv(tinv, gadd(gadd(gel(A, 1), tinv), S));1572}15731574GEN1575contfraceval(GEN CF, GEN t, long nlim)1576{1577pari_sp av = avma;1578return gerepileupto(av, contfraceval_inv(CF, ginv(t), nlim));1579}15801581/* MONIEN SUMMATION */15821583/* basic Newton, find x ~ z such that Q(x) = 0 */1584static GEN1585monrefine(GEN Q, GEN QP, GEN z, long prec)1586{1587pari_sp av = avma;1588GEN pr = poleval(Q, z);1589for(;;)1590{1591GEN prnew;1592z = gsub(z, gdiv(pr, poleval(QP, z)));1593prnew = poleval(Q, z);1594if (gcmp(gabs(prnew, prec), gabs(pr, prec)) >= 0) break;1595pr = prnew;1596}1597z = gprec_wensure(z, 2*prec-2);1598z = gsub(z, gdiv(poleval(Q, z), poleval(QP, z)));1599return gerepileupto(av, z);1600}16011602static GEN1603RX_realroots(GEN x, long prec)1604{ return realroots(gprec_wtrunc(x,prec), NULL, prec); }16051606/* (real) roots of Q, assuming QP = Q' and that half the roots are close to1607* k+1, ..., k+m, m = deg(Q)/2-1. N.B. All roots are real and >= 1 */1608static GEN1609monroots(GEN Q, GEN QP, long k, long prec)1610{1611long j, n = degpol(Q), m = n/2 - 1;1612GEN v2, v1 = cgetg(m+1, t_VEC);1613for (j = 1; j <= m; ++j) gel(v1, j) = monrefine(Q, QP, stoi(k+j), prec);1614Q = gdivent(Q, roots_to_pol(v1, varn(Q)));1615v2 = RX_realroots(Q, prec); settyp(v2, t_VEC);1616return shallowconcat(v1, v2);1617}16181619static void1620Pade(GEN M, GEN *pP, GEN *pQ)1621{1622pari_sp av = avma;1623long n = lg(M)-2, i;1624GEN v = QD(M, n), P = pol_0(0), Q = pol_1(0);1625/* evaluate continued fraction => Pade approximants */1626for (i = n-1; i >= 1; i--)1627{ /* S = P/Q: S -> v[i]*x / (1+S) */1628GEN R = RgX_shift_shallow(RgX_Rg_mul(Q,gel(v,i)), 1);1629Q = RgX_add(P,Q); P = R;1630if (gc_needed(av, 3))1631{1632if (DEBUGMEM>1) pari_warn(warnmem,"Pade, %ld/%ld",i,n-1);1633gerepileall(av, 3, &P, &Q, &v);1634}1635}1636/* S -> 1+S */1637*pP = RgX_add(P,Q);1638*pQ = Q;1639}16401641static GEN1642veczetaprime(GEN a, GEN b, long N, long prec)1643{1644long B = prec2nbits(prec) / 2;1645GEN v, h = mkcomplex(gen_0, real2n(-B, prec));1646v = veczeta(a, gadd(b, h), N, prec);1647return gmul2n(imag_i(v), B);1648}16491650struct mon_w {1651GEN w, a, b;1652long n, j, prec;1653};16541655/* w(x) / x^(a*(j+k)+b), k >= 1; w a t_CLOSURE or t_INT [encodes log(x)^w] */1656static GEN1657wrapmonw(void* E, GEN x)1658{1659struct mon_w *W = (struct mon_w*)E;1660long k, j = W->j, n = W->n, prec = W->prec, l = 2*n+4-j;1661GEN wx = typ(W->w) == t_CLOSURE? closure_callgen1prec(W->w, x, prec)1662: powgi(glog(x, prec), W->w);1663GEN v = cgetg(l, t_VEC);1664GEN xa = gpow(x, gneg(W->a), prec), w = gmul(wx, gpowgs(xa, j));1665w = gdiv(w, gpow(x,W->b,prec));1666for (k = 1; k < l; k++) { gel(v,k) = w; w = gmul(w, xa); }1667return v;1668}1669/* w(x) / x^(a*j+b) */1670static GEN1671wrapmonw2(void* E, GEN x)1672{1673struct mon_w *W = (struct mon_w*)E;1674GEN wnx = closure_callgen1prec(W->w, x, W->prec);1675return gdiv(wnx, gpow(x, gadd(gmulgs(W->a, W->j), W->b), W->prec));1676}1677static GEN1678M_from_wrapmon(struct mon_w *S, GEN wfast, GEN n0)1679{1680long j, N = 2*S->n+2;1681GEN M = cgetg(N+1, t_VEC), faj = gsub(wfast, S->b);1682for (j = 1; j <= N; j++)1683{1684faj = gsub(faj, S->a);1685if (gcmpgs(faj, -2) <= 0)1686{1687S->j = j; setlg(M,j);1688M = shallowconcat(M, sumnum((void*)S, wrapmonw, n0, NULL, S->prec));1689break;1690}1691S->j = j;1692gel(M,j) = sumnum((void*)S, wrapmonw2, mkvec2(n0,faj), NULL, S->prec);1693}1694return M;1695}16961697static void1698checkmonroots(GEN vr, long n)1699{1700if (lg(vr) != n+1)1701pari_err_IMPL("recovery when missing roots in sumnummonieninit");1702}17031704static GEN1705sumnummonieninit_i(GEN a, GEN b, GEN w, GEN n0, long prec)1706{1707GEN c, M, P, Q, Qp, vr, vabs, vwt, ga = gadd(a, b);1708double bit = 2*prec2nbits(prec) / gtodouble(ga), D = bit*M_LN2;1709double da = maxdd(1., gtodouble(a));1710long n = (long)ceil(D / (da*(log(D)-1)));1711long j, prec2, prec0 = prec + EXTRAPREC64;1712double bit0 = ceil((2*n+1)*LOG2_10);1713int neg = 1;1714struct mon_w S;17151716/* 2.05 is heuristic; with 2.03, sumnummonien(n=1,1/n^2) loses1717* 19 decimals at \p1500 */1718prec = nbits2prec(maxdd(2.05*da*bit, bit0));1719prec2 = nbits2prec(maxdd(1.3*da*bit, bit0));1720S.w = w;1721S.a = a = gprec_wensure(a, 2*prec-2);1722S.b = b = gprec_wensure(b, 2*prec-2);1723S.n = n;1724S.j = 1;1725S.prec = prec;1726if (typ(w) == t_INT)1727{ /* f(n) ~ \sum_{i > 0} f_i log(n)^k / n^(a*i + b); a > 0, a+b > 1 */1728long k = itos(w);1729if (k == 0)1730M = veczeta(a, ga, 2*n+2, prec);1731else if (k == 1)1732M = veczetaprime(a, ga, 2*n+2, prec);1733else1734M = M_from_wrapmon(&S, gen_0, gen_1);1735if (odd(k)) neg = 0;1736}1737else1738{1739GEN wfast = gen_0;1740if (typ(w) == t_VEC) { wfast = gel(w,2); w = gel(w,1); }1741M = M_from_wrapmon(&S, wfast, n0);1742}1743/* M[j] = sum(n >= n0, w(n) / n^(a*j+b) */1744Pade(M, &P,&Q);1745Qp = RgX_deriv(Q);1746if (gequal1(a)) a = NULL;1747if (!a && typ(w) == t_INT)1748{1749vabs = vr = monroots(Q, Qp, signe(w)? 1: 0, prec2);1750checkmonroots(vr, n);1751c = b;1752}1753else1754{1755vr = RX_realroots(Q, prec2); settyp(vr, t_VEC);1756checkmonroots(vr, n);1757if (!a) { vabs = vr; c = b; }1758else1759{1760GEN ai = ginv(a);1761vabs = cgetg(n+1, t_VEC);1762for (j = 1; j <= n; j++) gel(vabs,j) = gpow(gel(vr,j), ai, prec2);1763c = gdiv(b,a);1764}1765}17661767vwt = cgetg(n+1, t_VEC);1768c = gsubgs(c,1); if (gequal0(c)) c = NULL;1769for (j = 1; j <= n; j++)1770{1771GEN r = gel(vr,j), t = gdiv(poleval(P,r), poleval(Qp,r));1772if (c) t = gmul(t, gpow(r, c, prec));1773gel(vwt,j) = neg? gneg(t): t;1774}1775if (typ(w) == t_INT && !equali1(n0))1776{1777GEN h = subiu(n0,1);1778for (j = 1; j <= n; j++) gel(vabs,j) = gadd(gel(vabs,j), h);1779}1780return mkvec3(gprec_wtrunc(vabs,prec0), gprec_wtrunc(vwt,prec0), n0);1781}17821783GEN1784sumnummonieninit(GEN asymp, GEN w, GEN n0, long prec)1785{1786pari_sp av = avma;1787const char *fun = "sumnummonieninit";1788GEN a, b;1789if (!n0) n0 = gen_1; else if (typ(n0) != t_INT) pari_err_TYPE(fun, n0);1790if (!asymp) a = b = gen_1;1791else1792{1793if (typ(asymp) == t_VEC)1794{1795if (lg(asymp) != 3) pari_err_TYPE(fun, asymp);1796a = gel(asymp,1);1797b = gel(asymp,2);1798}1799else1800{1801a = gen_1;1802b = asymp;1803}1804if (gsigne(a) <= 0) pari_err_DOMAIN(fun, "a", "<=", gen_0, a);1805if (!isinR(b)) pari_err_TYPE(fun, b);1806if (gcmpgs(gadd(a,b), 1) <= 0)1807pari_err_DOMAIN(fun, "a+b", "<=", gen_1, mkvec2(a,b));1808}1809if (!w) w = gen_0;1810else switch(typ(w))1811{1812case t_INT:1813if (signe(w) < 0) pari_err_IMPL("log power < 0 in sumnummonieninit");1814case t_CLOSURE: break;1815case t_VEC:1816if (lg(w) == 3 && typ(gel(w,1)) == t_CLOSURE) break;1817default: pari_err_TYPE(fun, w);1818}1819return gerepilecopy(av, sumnummonieninit_i(a, b, w, n0, prec));1820}18211822GEN1823sumnummonien(void *E, GEN (*eval)(void*,GEN), GEN n0, GEN tab, long prec)1824{1825pari_sp av = avma;1826GEN vabs, vwt, S;1827long l, i;1828if (typ(n0) != t_INT) pari_err_TYPE("sumnummonien", n0);1829if (!tab)1830tab = sumnummonieninit_i(gen_1, gen_1, gen_0, n0, prec);1831else1832{1833if (lg(tab) != 4 || typ(tab) != t_VEC) pari_err_TYPE("sumnummonien", tab);1834if (!equalii(n0, gel(tab,3)))1835pari_err(e_MISC, "incompatible initial value %Ps != %Ps", gel(tab,3),n0);1836}1837vabs= gel(tab,1); l = lg(vabs);1838vwt = gel(tab,2);1839if (typ(vabs) != t_VEC || typ(vwt) != t_VEC || lg(vwt) != l)1840pari_err_TYPE("sumnummonien", tab);1841S = gen_0;1842for (i = 1; i < l; i++)1843{1844S = gadd(S, gmul(gel(vwt,i), eval(E, gel(vabs,i))));1845S = gprec_wensure(S, prec);1846}1847return gerepilecopy(av, gprec_wtrunc(S, prec));1848}18491850static GEN1851get_oo(GEN fast) { return mkvec2(mkoo(), fast); }18521853GEN1854sumnuminit(GEN fast, long prec)1855{1856pari_sp av;1857GEN s, v, d, C, res = cgetg(6, t_VEC);1858long bitprec = prec2nbits(prec), N, k, k2, m;1859double w;18601861gel(res, 1) = d = mkfrac(gen_1, utoipos(4)); /* 1/4 */1862av = avma;1863w = gtodouble(glambertW(ginv(d), 0, LOWDEFAULTPREC));1864N = (long)ceil(M_LN2*bitprec/(w*(1+w))+5);1865k = (long)ceil(N*w); if (k&1) k--;18661867prec += EXTRAPREC64;1868k2 = k/2;1869s = RgX_to_ser(monomial(real_1(prec),1,0), k+3);1870s = gmul2n(gasinh(s, prec), 2); /* asinh(x)/d, d = 1/4 */1871gel(s, 2) = utoipos(4);1872s = gsub(ser_inv(gexpm1(s,prec)), ser_inv(s));1873C = matpascal(k-1);1874v = cgetg(k2+1, t_VEC);1875for (m = 1; m <= k2; m++)1876{1877pari_sp av = avma;1878GEN S = real_0(prec);1879long j;1880for (j = m; j <= k2; j++)1881{ /* s[X^(2j-1)] * binomial(2*j-1, j-m) */1882GEN t = gmul(gel(s,2*j+1), gcoeff(C, 2*j,j-m+1));1883t = gmul2n(t, 1-2*j);1884S = odd(j)? gsub(S,t): gadd(S,t);1885}1886if (odd(m)) S = gneg(S);1887gel(v,m) = gerepileupto(av, S);1888}1889v = RgC_gtofp(v,prec); settyp(v, t_VEC);1890gel(res, 4) = gerepileupto(av, v);1891gel(res, 2) = utoi(N);1892gel(res, 3) = utoi(k);1893if (!fast) fast = get_oo(gen_0);1894gel(res, 5) = intnuminit(gel(res,2), fast, 0, prec - EXTRAPREC64);1895return res;1896}18971898static int1899checksumtab(GEN T)1900{1901if (typ(T) != t_VEC || lg(T) != 6) return 0;1902return typ(gel(T,2))==t_INT && typ(gel(T,3))==t_INT && typ(gel(T,4))==t_VEC;1903}1904GEN1905sumnum(void *E, GEN (*eval)(void*, GEN), GEN a, GEN tab, long prec)1906{1907pari_sp av = avma, av2;1908GEN v, tabint, S, d, fast;1909long as, N, k, m, prec2;1910if (!a) { a = gen_1; fast = get_oo(gen_0); }1911else switch(typ(a))1912{1913case t_VEC:1914if (lg(a) != 3) pari_err_TYPE("sumnum", a);1915fast = get_oo(gel(a,2));1916a = gel(a,1); break;1917default:1918fast = get_oo(gen_0);1919}1920if (typ(a) != t_INT) pari_err_TYPE("sumnum", a);1921if (!tab) tab = sumnuminit(fast, prec);1922else if (!checksumtab(tab)) pari_err_TYPE("sumnum",tab);1923as = itos(a);1924d = gel(tab,1);1925N = maxss(as, itos(gel(tab,2)));1926k = itos(gel(tab,3));1927v = gel(tab,4);1928tabint = gel(tab,5);1929prec2 = prec+EXTRAPREC64;1930av2 = avma;1931S = gmul(eval(E, stoi(N)), real2n(-1,prec2));1932for (m = as; m < N; m++)1933{1934S = gadd(S, eval(E, stoi(m)));1935if (gc_needed(av, 2))1936{1937if (DEBUGMEM>1) pari_warn(warnmem,"sumnum [1], %ld/%ld",m,N);1938S = gerepileupto(av2, S);1939}1940S = gprec_wensure(S, prec2);1941}1942for (m = 1; m <= k/2; m++)1943{1944GEN t = gmulsg(2*m-1, d);1945GEN s = gsub(eval(E, gsubsg(N,t)), eval(E, gaddsg(N,t)));1946S = gadd(S, gmul(gel(v,m), s));1947if (gc_needed(av2, 2))1948{1949if (DEBUGMEM>1) pari_warn(warnmem,"sumnum [2], %ld/%ld",m,k/2);1950S = gerepileupto(av2, S);1951}1952S = gprec_wensure(S, prec2);1953}1954S = gadd(S, intnum(E, eval,stoi(N), fast, tabint, prec2));1955return gerepilecopy(av, gprec_wtrunc(S, prec));1956}19571958GEN1959sumnummonien0(GEN a, GEN code, GEN tab, long prec)1960{ EXPR_WRAP(code, sumnummonien(EXPR_ARG, a, tab, prec)); }1961GEN1962sumnum0(GEN a, GEN code, GEN tab, long prec)1963{ EXPR_WRAP(code, sumnum(EXPR_ARG, a, tab, prec)); }19641965/* Abel-Plana summation */19661967static GEN1968intnumgauexpinit(long prec)1969{1970pari_sp ltop = avma;1971GEN V, N, E, P, Q, R, vabs, vwt;1972long l, n, k, j, prec2, prec0 = prec + EXTRAPREC64, bit = prec2nbits(prec);19731974n = (long)ceil(bit*0.226);1975n |= 1; /* make n odd */1976prec = nbits2prec(1.5*bit + 32);1977prec2 = maxss(prec0, nbits2prec(1.15*bit + 32));1978constbern(n+3);1979V = cgetg(n + 4, t_VEC);1980for (k = 1; k <= n + 3; ++k)1981gel(V, k) = gtofp(gdivgs(bernfrac(2*k), odd(k)? 2*k: -2*k), prec);1982Pade(V, &P, &Q);1983N = RgX_recip(gsub(P, Q));1984E = RgX_recip(Q);1985R = gdivgs(gdiv(N, RgX_deriv(E)), 2);1986vabs = RX_realroots(E,prec2);1987l = lg(vabs); settyp(vabs, t_VEC);1988vwt = cgetg(l, t_VEC);1989for (j = 1; j < l; ++j)1990{1991GEN a = gel(vabs,j);1992gel(vwt, j) = gprec_wtrunc(poleval(R, a), prec0);1993gel(vabs, j) = gprec_wtrunc(sqrtr_abs(a), prec0);1994}1995return gerepilecopy(ltop, mkvec2(vabs, vwt));1996}19971998/* Compute \int_{-oo}^oo w(x)f(x) dx, where w(x)=x/(exp(2pi x)-1)1999* for x>0 and w(-x)=w(x). For Abel-Plana (sumnumap). */2000static GEN2001intnumgauexp(void *E, GEN (*eval)(void*,GEN), GEN gN, GEN tab, long prec)2002{2003pari_sp av = avma;2004GEN U = mkcomplex(gN, NULL), V = mkcomplex(gN, NULL), S = gen_0;2005GEN vabs = gel(tab, 1), vwt = gel(tab, 2);2006long l = lg(vabs), i;2007if (lg(vwt) != l || typ(vabs) != t_VEC || typ(vwt) != t_VEC)2008pari_err_TYPE("sumnumap", tab);2009for (i = 1; i < l; i++)2010{ /* I * (w_i/a_i) * (f(N + I*a_i) - f(N - I*a_i)) */2011GEN x = gel(vabs,i), w = gel(vwt,i), t;2012gel(U,2) = x;2013gel(V,2) = gneg(x);2014t = mulcxI(gsub(eval(E,U), eval(E,V)));2015S = gadd(S, gmul(gdiv(w,x), cxtoreal(t)));2016S = gprec_wensure(S, prec);2017}2018return gerepilecopy(av, gprec_wtrunc(S, prec));2019}20202021GEN2022sumnumapinit(GEN fast, long prec)2023{2024if (!fast) fast = mkoo();2025retmkvec2(intnumgauexpinit(prec), intnuminit(gen_1, fast, 0, prec));2026}20272028typedef struct {2029GEN (*f)(void *E, GEN);2030void *E;2031long N;2032} expfn;20332034/* f(Nx) */2035static GEN2036_exfn(void *E, GEN x)2037{2038expfn *S = (expfn*)E;2039return S->f(S->E, gmulsg(S->N, x));2040}20412042GEN2043sumnumap(void *E, GEN (*eval)(void*,GEN), GEN a, GEN tab, long prec)2044{2045pari_sp av = avma;2046expfn T;2047GEN S, fast, gN;2048long as, m, N;2049if (!a) { a = gen_1; fast = get_oo(gen_0); }2050else switch(typ(a))2051{2052case t_VEC:2053if (lg(a) != 3) pari_err_TYPE("sumnumap", a);2054fast = get_oo(gel(a,2));2055a = gel(a,1); break;2056default:2057fast = get_oo(gen_0);2058}2059if (typ(a) != t_INT) pari_err_TYPE("sumnumap", a);2060if (!tab) tab = sumnumapinit(fast, prec);2061else if (typ(tab) != t_VEC || lg(tab) != 3) pari_err_TYPE("sumnumap",tab);2062as = itos(a);2063T.N = N = maxss(as + 1, (long)ceil(prec2nbits(prec)*0.327));2064T.E = E;2065T.f = eval;2066gN = stoi(N);2067S = gtofp(gmul2n(eval(E, gN), -1), prec);2068for (m = as; m < N; ++m)2069{2070S = gadd(S, eval(E, stoi(m)));2071S = gprec_wensure(S, prec);2072}2073S = gadd(S, gmulsg(N, intnum(&T, &_exfn, gen_1, fast, gel(tab, 2), prec)));2074S = gadd(S, intnumgauexp(E, eval, gN, gel(tab, 1), prec));2075return gerepileupto(av, S);2076}20772078GEN2079sumnumap0(GEN a, GEN code, GEN tab, long prec)2080{ EXPR_WRAP(code, sumnumap(EXPR_ARG, a, tab, prec)); }20812082/* max (1, |zeros|), P a t_POL or scalar */2083static double2084polmax(GEN P)2085{2086pari_sp av = avma;2087double r;2088if (typ(P) != t_POL || degpol(P) <= 0) return 1.0;2089r = gtodouble(polrootsbound(P, NULL));2090return gc_double(av, maxdd(r, 1.0));2091}20922093/* max (1, |poles|), F a t_POL or t_RFRAC or scalar */2094static double2095ratpolemax(GEN F)2096{2097if (typ(F) == t_POL) return 1.0;2098return polmax(gel(F,2));2099}2100/* max (1, |poles|, |zeros|)) */2101static double2102ratpolemax2(GEN F)2103{2104if (typ(F) == t_POL) return polmax(F);2105return maxdd(polmax(gel(F,1)), polmax(gel(F,2)));2106}21072108static GEN2109sercoeff(GEN x, long n)2110{2111long N = n - valp(x);2112return (N < 0)? gen_0: gel(x,N+2);2113}21142115/* Compute the integral from N to infinity of a rational function F, deg(F) < -12116* We must have N > 2 * r, r = max(1, |poles F|). */2117static GEN2118intnumainfrat(GEN F, long N, double r, long prec)2119{2120long B = prec2nbits(prec), v, k, lim;2121GEN S, ser;2122pari_sp av = avma;21232124lim = (long)ceil(B/log2(N/r));2125ser = gmul(F, real_1(prec + EXTRAPREC64));2126ser = rfracrecip_to_ser_absolute(ser, lim+2);2127v = valp(ser);2128S = gdivgs(sercoeff(ser,lim+1), lim*N);2129/* goes down to 2, but coeffs are 0 in degree < v */2130for (k = lim; k >= v; k--) /* S <- (S + coeff(ser,k)/(k-1)) / N */2131S = gdivgs(gadd(S, gdivgs(sercoeff(ser,k), k-1)), N);2132if (v-2) S = gdiv(S, powuu(N, v-2));2133return gerepilecopy(av, gprec_wtrunc(S, prec));2134}21352136static GEN2137rfrac_eval0(GEN R)2138{2139GEN N, n, D = gel(R,2), d = constant_coeff(D);2140if (gequal0(d)) return NULL;2141N = gel(R,1);2142n = typ(N)==t_POL? constant_coeff(N): N;2143return gdiv(n, d);2144}2145static GEN2146rfrac_eval(GEN R, GEN a)2147{2148GEN D = gel(R,2), d = poleval(D,a);2149return gequal0(d)? NULL: gdiv(poleval(gel(R,1),a), d);2150}2151/* R = \sum_i vR[i], eval at a omitting poles */2152static GEN2153RFRAC_eval(GEN R, GEN vR, GEN a)2154{2155GEN S = rfrac_eval(R,a);2156if (!S && vR)2157{2158long i, l = lg(vR);2159for (i = 1; i < l; i++)2160{2161GEN z = rfrac_eval(gel(vR,i), a);2162if (z) S = S? gadd(S,z): z;2163}2164}2165return S;2166}2167static GEN2168add_RFRAC_eval(GEN S, GEN R, GEN vR, GEN a)2169{2170GEN z = RFRAC_eval(R, vR, a);2171return z? gadd(S, z): S;2172}2173static GEN2174add_sumrfrac(GEN S, GEN R, GEN vR, long b)2175{2176long m;2177for (m = b; m >= 1; m--) S = add_RFRAC_eval(S,R,vR,utoipos(m));2178return S;2179}2180static void2181get_kN(long r, long B, long *pk, long *pN)2182{2183long k = maxss(50, (long)ceil(0.241*B));2184GEN z;2185if (k&1L) k++;2186*pk = k; constbern(k >> 1);2187z = sqrtnr_abs(gmul2n(gtofp(bernfrac(k), LOWDEFAULTPREC), B), k);2188*pN = maxss(2*r, r + 1 + itos(gceil(z)));2189}2190/* F a t_RFRAC, F0 = F(0) or NULL [pole], vF a vector of t_RFRAC summing to F2191* or NULL [F atomic] */2192static GEN2193sumnumrat_i(GEN F, GEN F0, GEN vF, long prec)2194{2195long B = prec2nbits(prec), vx, j, k, N;2196GEN S, S1, S2, intf, _1;2197double r;2198if (poldegree(F, -1) > -2) pari_err(e_MISC, "sum diverges in sumnumrat");2199vx = varn(gel(F,2));2200r = ratpolemax(F);2201get_kN((long)ceil(r), B, &k,&N);2202intf = intnumainfrat(F, N, r, prec);2203/* N > ratpolemax(F) is not a pole */2204_1 = real_1(prec);2205S1 = gmul2n(gmul(_1, gsubst(F, vx, utoipos(N))), -1);2206S1 = add_sumrfrac(S1, F, vF, N-1);2207if (F0) S1 = gadd(S1, F0);2208S = gmul(_1, gsubst(F, vx, gaddgs(pol_x(vx), N)));2209S = rfrac_to_ser(S, k + 2);2210S2 = gen_0;2211for (j = 2; j <= k; j += 2)2212S2 = gadd(S2, gmul(gdivgs(bernfrac(j),j), sercoeff(S, j-1)));2213return gadd(intf, gsub(S1, S2));2214}2215/* sum_{n >= a} F(n) */2216GEN2217sumnumrat(GEN F, GEN a, long prec)2218{2219pari_sp av = avma;2220long vx;2221GEN vF, F0;22222223switch(typ(F))2224{2225case t_RFRAC: break;2226case t_INT: case t_REAL: case t_COMPLEX: case t_POL:2227if (gequal0(F)) return real_0(prec);2228default: pari_err_TYPE("sumnumrat",F);2229}2230vx = varn(gel(F,2));2231switch(typ(a))2232{2233case t_INT:2234if (signe(a)) F = gsubst(F, vx, deg1pol_shallow(gen_1,a,vx));2235F0 = rfrac_eval0(F);2236vF = NULL;2237break;2238case t_INFINITY:2239if (inf_get_sign(a) == -1)2240{ /* F(x) + F(-x). Could divide degree by 2, as G(x^2): pb with poles */2241GEN F2 = gsubst(F, vx, RgX_neg(pol_x(vx)));2242vF = mkvec2(F,F2);2243F = gadd(F, F2);2244if (gequal0(F)) { set_avma(av); return real_0(prec); }2245F0 = rfrac_eval0(gel(vF,1));2246break;2247}2248default:2249pari_err_TYPE("sumnumrat",a);2250return NULL; /* LCOV_EXCL_LINE */2251}2252return gerepileupto(av, sumnumrat_i(F, F0, vF, prec));2253}2254/* deg ((a / b) - 1), assuming b a t_POL of positive degree in main variable */2255static long2256rfracm1_degree(GEN a, GEN b)2257{2258long da, db;2259if (typ(a) != t_POL || varn(a) != varn(b)) return 0;2260da = degpol(a);2261db = degpol(b); if (da != db) return maxss(da - db, 0);2262return degpol(RgX_sub(a,b)) - db;2263}22642265/* prod_{n >= a} F(n) */2266GEN2267prodnumrat(GEN F, long a, long prec)2268{2269pari_sp ltop = avma;2270long B = prec2nbits(prec), j, k, m, N, vx;2271GEN S, S1, S2, intf, G;2272double r;22732274switch(typ(F))2275{2276case t_RFRAC: break;2277case t_INT: case t_REAL: case t_COMPLEX: case t_POL:2278if (gequal1(F)) return real_1(prec);2279default: pari_err_TYPE("prodnumrat",F);2280}2281if (rfracm1_degree(gel(F,1), gel(F,2)) > -2)2282pari_err(e_MISC, "product diverges in prodnumrat");2283vx = varn(gel(F,2));2284if (a) F = gsubst(F, vx, gaddgs(pol_x(vx), a));2285r = ratpolemax2(F);2286get_kN((long)ceil(r), B, &k,&N);2287G = gdiv(deriv(F, vx), F);2288intf = intnumainfrat(gmul(pol_x(vx),G), N, r, prec);2289intf = gneg(gadd(intf, gmulsg(N, glog(gsubst(F, vx, stoi(N)), prec))));2290S = gmul(real_1(prec), gsubst(G, vx, gaddgs(pol_x(vx), N)));2291S = rfrac_to_ser(S, k + 2);2292S1 = gsqrt(gsubst(F, vx, utoipos(N)), prec);2293for (m = 0; m < N; m++) S1 = gmul(S1, gsubst(F, vx, utoi(m)));2294S2 = gen_0;2295for (j = 2; j <= k; j += 2)2296S2 = gadd(S2, gmul(gdivgs(bernfrac(j),j*(j-1)), sercoeff(S, j-2)));2297return gerepileupto(ltop, gmul(S1, gexp(gsub(intf, S2), prec)));2298}22992300/* fan = factoru(n); sum_{d | n} mu(d)/d * s[n/d] */2301static GEN2302sdmob(GEN s, long n, GEN fan)2303{2304GEN D = divisorsu_moebius(gel(fan,1)), S = sercoeff(s, n); /* d = 1 */2305long i, l = lg(D);2306for (i = 2; i < l; i++)2307S = gadd(S, gdivgs(sercoeff(s, n/labs(D[i])), D[i]));2308return S;2309}2310/* log (zeta(s) * prod_i (1 - P[i]^-s) */2311static GEN2312logzetan(GEN s, GEN P, long prec)2313{2314GEN Z = gzeta(s, prec);2315long i, l = lg(P);2316for (i = 1; i < l; i++) Z = gsub(Z, gdiv(Z, gpow(gel(P,i), s, prec)));2317return glog(Z, prec);2318}2319static GEN2320sumlogzeta(GEN ser, GEN s, GEN P, double rs, double lN, long vF, long lim,2321long prec)2322{2323GEN z = gen_0, v = vecfactoru_i(vF,lim);2324pari_sp av = avma;2325long i, n;2326if (typ(s) == t_INT) constbern((itos(s) * lim + 1) >> 1);2327for (n = lim, i = lg(v)-1; n >= vF; n--, i--)2328{2329GEN t = sdmob(ser, n, gel(v,i));2330if (!gequal0(t))2331{ /* (n Re(s) - 1) log2(N) bits cancel in logzetan */2332long prec2 = prec + nbits2extraprec((n*rs-1) * lN);2333GEN L = logzetan(gmulsg(n,gprec_wensure(s,prec2)), P, prec2);2334z = gerepileupto(av, gadd(z, gmul(L, t)));2335z = gprec_wensure(z, prec);2336}2337}2338return gprec_wtrunc(z, prec);2339}23402341static GEN2342rfrac_evalfp(GEN F, GEN x, long prec)2343{2344GEN N = gel(F,1), D = gel(F,2), a, b = poleval(D, x);2345a = (typ(N) == t_POL && varn(N) == varn(D))? poleval(N, x): N;2346if (typ(a) != t_INT || typ(b) != t_INT ||2347(lgefint(a) <= prec && lgefint(b) <= prec)) return gdiv(a, b);2348return rdivii(a, b, prec + EXTRAPRECWORD);2349}23502351/* { F(p^s): p in P, p >= a }, F t_RFRAC */2352static GEN2353vFps(GEN P, long a, GEN F, GEN s, long prec)2354{2355long i, j, l = lg(P);2356GEN v = cgetg(l, t_VEC);2357for (i = j = 1; i < l; i++)2358{2359GEN p = gel(P,i); if (cmpiu(p, a) < 0) continue;2360gel(v, j++) = rfrac_evalfp(F, gpow(p, s, prec), prec);2361}2362setlg(v, j); return v;2363}23642365static void2366euler_set_Fs(GEN *F, GEN *s)2367{2368if (!*s) *s = gen_1;2369if (typ(*F) == t_RFRAC)2370{2371long m;2372*F = rfrac_deflate_max(*F, &m);2373if (m != 1) *s = gmulgs(*s, m);2374}2375}2376/* sum_{p prime, p >= a} F(p^s), F rational function */2377GEN2378sumeulerrat(GEN F, GEN s, long a, long prec)2379{2380pari_sp av = avma;2381GEN ser, z, P;2382double r, rs, RS, lN;2383long B = prec2nbits(prec), prec2 = prec + EXTRAPREC64, vF, N, lim;23842385euler_set_Fs(&F, &s);2386switch(typ(F))2387{2388case t_RFRAC: break;2389case t_INT: case t_REAL: case t_COMPLEX: case t_POL:2390if (gequal0(F)) return real_0(prec);2391default: pari_err_TYPE("sumeulerrat",F);2392}2393/* F t_RFRAC */2394if (a < 2) a = 2;2395vF = -poldegree(F, -1);2396rs = gtodouble(real_i(s));2397r = polmax(gel(F,2));2398N = maxss(30, a); lN = log2((double)N);2399RS = maxdd(1./vF, log2(r) / lN);2400if (rs <= RS)2401pari_err_DOMAIN("sumeulerrat", "real(s)", "<=", dbltor(RS), dbltor(rs));2402lim = (long)ceil(B / (rs*lN - log2(r)));2403ser = gmul(real_1(prec2), F);2404ser = rfracrecip_to_ser_absolute(ser, lim+1);2405P = primes_interval(gen_2, utoipos(N));2406z = sumlogzeta(ser, s, P, rs, lN, vF, lim, prec);2407z = gadd(z, vecsum(vFps(P, a, F, s, prec)));2408return gerepilecopy(av, gprec_wtrunc(z, prec));2409}24102411/* F = N/D; return F'/F. Assume D a t_POL */2412static GEN2413rfrac_logderiv(GEN N, GEN D)2414{2415if (typ(N) != t_POL || varn(N) != varn(D)) return gdiv(gneg(RgX_deriv(D)), D);2416if (!degpol(D)) return gdiv(RgX_deriv(N), N);2417return gdiv(RgX_sub(RgX_mul(RgX_deriv(N), D), RgX_mul(RgX_deriv(D), N)),2418RgX_mul(N, D));2419}24202421/* prod_{p prime, p >= a} F(p^s), F rational function */2422GEN2423prodeulerrat(GEN F, GEN s, long a, long prec)2424{2425pari_sp ltop = avma;2426GEN DF, NF, ser, P, z;2427double r, rs, RS, lN;2428long B = prec2nbits(prec), prec2 = prec + EXTRAPREC64, vF, N, lim;24292430euler_set_Fs(&F, &s);2431switch(typ(F))2432{2433case t_RFRAC: break;2434case t_INT: case t_REAL: case t_COMPLEX: case t_POL:2435if (gequal1(F)) return real_1(prec);2436default: pari_err_TYPE("prodeulerrat",F);2437} /* F t_RFRAC */2438NF = gel(F, 1);2439DF = gel(F, 2);2440rs = gtodouble(real_i(s));2441vF = - rfracm1_degree(NF, DF);2442if (rs * vF <= 1) pari_err(e_MISC, "product diverges in prodeulerrat");2443r = ratpolemax2(F);2444N = maxss(maxss(30, a), (long)ceil(2*r)); lN = log2((double)N);2445RS = maxdd(1./vF, log2(r) / lN);2446if (rs <= RS)2447pari_err_DOMAIN("prodeulerrat", "real(s)", "<=", dbltor(RS), dbltor(rs));2448lim = (long)ceil(B / (rs*lN - log2(r)));2449(void)rfracrecip(&NF, &DF); /* returned value is 0 */2450if (!RgX_is_ZX(DF) || !is_pm1(gel(DF,2))2451|| lim * log2(r) > 4 * B) NF = gmul(NF, real_1(prec2));2452ser = integser(rfrac_to_ser(rfrac_logderiv(NF,DF), lim+3));2453/* ser = log f, f = F(1/x) + O(x^(lim+1)) */2454P = primes_interval(gen_2, utoipos(N));2455z = gexp(sumlogzeta(ser, s, P, rs, lN, vF, lim, prec), prec);2456z = gmul(z, vecprod(vFps(P, a, F, s, prec)));2457return gerepilecopy(ltop, gprec_wtrunc(z, prec));2458}24592460/* Compute $\sum_{n\ge a}c(n)$ using Lagrange extrapolation.2461Assume that the $N$-th remainder term of the series has a2462regular asymptotic expansion in integral powers of $1/N$. */2463static GEN2464sumnumlagrange1init(GEN c1, long flag, long prec)2465{2466pari_sp av = avma;2467GEN V, W, T;2468double c1d;2469long B = prec2nbits(prec), prec2;2470ulong n, N;2471c1d = c1 ? gtodouble(c1) : 0.332;2472N = (ulong)ceil(c1d*B); if ((N&1L) == 0) N++;2473prec2 = nbits2prec(B+(long)ceil(1.8444*N) + 16);2474W = vecbinomial(N);2475T = vecpowuu(N, N);2476V = cgetg(N+1, t_VEC); gel(V,N) = gel(T,N);2477for (n = N-1; n >= 1; n--)2478{2479pari_sp av = avma;2480GEN t = mulii(gel(W, n+1), gel(T,n));2481if (!odd(n)) togglesign_safe(&t);2482if (flag) t = addii(gel(V, n+1), t);2483gel(V, n) = gerepileuptoint(av, t);2484}2485V = gdiv(RgV_gtofp(V, prec2), mpfact(N));2486return gerepilecopy(av, mkvec4(gen_1, stoi(prec2), gen_1, V));2487}24882489static GEN2490sumnumlagrange2init(GEN c1, long flag, long prec)2491{2492pari_sp av = avma;2493GEN V, W, T, told;2494double c1d = c1 ? gtodouble(c1) : 0.228;2495long B = prec2nbits(prec), prec2;2496ulong n, N;24972498N = (ulong)ceil(c1d*B); if ((N&1L) == 0) N++;2499prec2 = nbits2prec(B+(long)ceil(1.18696*N) + 16);2500W = vecbinomial(2*N);2501T = vecpowuu(N, 2*N);2502V = cgetg(N+1, t_VEC); gel(V, N) = told = gel(T,N);2503for (n = N-1; n >= 1; n--)2504{2505GEN tnew = mulii(gel(W, N-n+1), gel(T,n));2506if (!odd(n)) togglesign_safe(&tnew);2507told = addii(told, tnew);2508if (flag) told = addii(gel(V, n+1), told);2509gel(V, n) = told; told = tnew;2510}2511V = gdiv(RgV_gtofp(V, prec2), mpfact(2*N));2512return gerepilecopy(av, mkvec4(gen_2, stoi(prec2), gen_1, V));2513}25142515static GEN2516_mpmul(GEN x, GEN y)2517{2518if (!x) return y;2519return y? mpmul(x, y): x;2520}2521/* Used only for al = 2, 1, 1/2, 1/3, 1/4. */2522static GEN2523sumnumlagrangeinit_i(GEN al, GEN c1, long flag, long prec)2524{2525pari_sp av = avma;2526GEN V, W;2527double c1d = 0.0, c2;2528long B = prec2nbits(prec), B1, prec2, dal;2529ulong j, n, N;25302531if (typ(al) == t_INT)2532{2533switch(itos_or_0(al))2534{2535case 1: return sumnumlagrange1init(c1, flag, prec);2536case 2: return sumnumlagrange2init(c1, flag, prec);2537default: pari_err_IMPL("sumnumlagrange for this alpha");2538}2539}2540if (typ(al) != t_FRAC) pari_err_TYPE("sumnumlagrangeinit",al);2541dal = itos_or_0(gel(al,2));2542if (dal > 4 || !equali1(gel(al,1)))2543pari_err_IMPL("sumnumlagrange for this alpha");2544switch(dal)2545{2546case 2: c2 = 2.6441; c1d = 0.62; break;2547case 3: c2 = 3.1578; c1d = 1.18; break;2548case 4: c2 = 3.5364; c1d = 3.00; break;2549default: return NULL; /* LCOV_EXCL_LINE */2550}2551if (c1)2552{2553c1d = gtodouble(c1);2554if (c1d <= 0)2555pari_err_DOMAIN("sumnumlagrangeinit", "c1", "<=", gen_0, c1);2556}2557N = (ulong)ceil(c1d*B); if ((N&1L) == 0) N++;2558B1 = B + (long)ceil(c2*N) + 16;2559prec2 = nbits2prec(B1);2560V = vecpowug(N, al, prec2);2561W = cgetg(N+1, t_VEC);2562for (n = 1; n <= N; ++n)2563{2564pari_sp av2 = avma;2565GEN t = NULL, vn = gel(V, n);2566for (j = 1; j <= N; j++)2567if (j != n) t = _mpmul(t, mpsub(vn, gel(V, j)));2568gel(W, n) = gerepileuptoleaf(av2, mpdiv(gpowgs(vn, N-1), t));2569}2570if (flag)2571for (n = N-1; n >= 1; n--) gel(W, n) = gadd(gel(W, n+1), gel(W, n));2572return gerepilecopy(av, mkvec4(al, stoi(prec2), gen_1, W));2573}25742575GEN2576sumnumlagrangeinit(GEN al, GEN c1, long prec)2577{2578pari_sp ltop = avma;2579GEN V, W, S, be;2580long n, prec2, fl, N;25812582if (!al) return sumnumlagrange1init(c1, 1, prec);2583if (typ(al) != t_VEC) al = mkvec2(gen_1, al);2584else if (lg(al) != 3) pari_err_TYPE("sumnumlagrangeinit",al);2585be = gel(al,2);2586al = gel(al,1);2587if (gequal0(be)) return sumnumlagrangeinit_i(al, c1, 1, prec);2588V = sumnumlagrangeinit_i(al, c1, 0, prec);2589switch(typ(be))2590{2591case t_CLOSURE: fl = 1; break;2592case t_INT: case t_FRAC: case t_REAL: fl = 0; break;2593default: pari_err_TYPE("sumnumlagrangeinit", be);2594return NULL; /* LCOV_EXCL_LINE */2595}2596prec2 = itos(gel(V, 2));2597W = gel(V, 4);2598N = lg(W) - 1;2599S = gen_0; V = cgetg(N+1, t_VEC);2600for (n = N; n >= 1; n--)2601{2602GEN tmp, gn = stoi(n);2603tmp = fl ? closure_callgen1prec(be, gn, prec2) : gpow(gn, gneg(be), prec2);2604tmp = gdiv(gel(W, n), tmp);2605S = gadd(S, tmp);2606gel(V, n) = (n == N)? tmp: gadd(gel(V, n+1), tmp);2607}2608return gerepilecopy(ltop, mkvec4(al, stoi(prec2), S, V));2609}26102611/* - sum_{n=1}^{as-1} f(n) */2612static GEN2613sumaux(void *E, GEN (*eval)(void*,GEN,long), long as, long prec)2614{2615GEN S = gen_0;2616long n;2617if (as > 1)2618{2619for (n = 1; n < as; ++n)2620{2621S = gadd(S, eval(E, stoi(n), prec));2622S = gprec_wensure(S, prec);2623}2624S = gneg(S);2625}2626else2627for (n = as; n <= 0; ++n)2628{2629S = gadd(S, eval(E, stoi(n), prec));2630S = gprec_wensure(S, prec);2631}2632return S;2633}26342635GEN2636sumnumlagrange(void *E, GEN (*eval)(void*,GEN,long), GEN a, GEN tab, long prec)2637{2638pari_sp av = avma;2639GEN s, S, al, V;2640long as, prec2;2641ulong n, l;26422643if (typ(a) != t_INT) pari_err_TYPE("sumnumlagrange", a);2644if (!tab) tab = sumnumlagrangeinit(NULL, tab, prec);2645else if (lg(tab) != 5 || typ(gel(tab,2)) != t_INT || typ(gel(tab,4)) != t_VEC)2646pari_err_TYPE("sumnumlagrange", tab);26472648as = itos(a);2649al = gel(tab, 1);2650prec2 = itos(gel(tab, 2));2651S = gel(tab, 3);2652V = gel(tab, 4);2653l = lg(V);2654if (gequal(al, gen_2))2655{2656s = sumaux(E, eval, as, prec2);2657as = 1;2658}2659else2660s = gen_0;2661for (n = 1; n < l; n++)2662{2663s = gadd(s, gmul(gel(V, n), eval(E, stoi(n+as-1), prec2)));2664s = gprec_wensure(s, prec);2665}2666if (!gequal1(S)) s = gdiv(s,S);2667return gerepilecopy(av, gprec_wtrunc(s, prec));2668}26692670GEN2671sumnumlagrange0(GEN a, GEN code, GEN tab, long prec)2672{ EXPR_WRAP(code, sumnumlagrange(EXPR_ARGPREC, a, tab, prec)); }267326742675