Code coverage tests

This page documents the degree to which the PARI/GP source code is tested by our public test suite, distributed with the source distribution in directory src/test/. This is measured by the gcov utility; we then process gcov output using the lcov frond-end.

We test a few variants depending on Configure flags on the pari.math.u-bordeaux.fr machine (x86_64 architecture), and agregate them in the final report:

The target is to exceed 90% coverage for all mathematical modules (given that branches depending on DEBUGLEVEL or DEBUGMEM are not covered). This script is run to produce the results below.

LCOV - code coverage report
Current view: top level - language - intnum.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.12.1 lcov report (development 24038-ebe36f6c4) Lines: 1433 1468 97.6 %
Date: 2019-07-23 05:53:17 Functions: 118 119 99.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13