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 - basemath - dirichlet.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31041-bd73e9fcdd) Lines: 95.5 % 506 483
Test Date: 2026-07-22 22:45:42 Functions: 93.3 % 45 42
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copyright (C) 2015  The PARI group.
       2              : 
       3              : This file is part of the PARI/GP package.
       4              : 
       5              : PARI/GP is free software; you can redistribute it and/or modify it under the
       6              : terms of the GNU General Public License as published by the Free Software
       7              : Foundation; either version 2 of the License, or (at your option) any later
       8              : version. It is distributed in the hope that it will be useful, but WITHOUT
       9              : ANY WARRANTY WHATSOEVER.
      10              : 
      11              : Check the License for details. You should have received a copy of it, along
      12              : with the package; see the file 'COPYING'. If not, write to the Free Software
      13              : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      14              : 
      15              : /********************************************************************/
      16              : /**                                                                **/
      17              : /**           Dirichlet series through Euler product               **/
      18              : /**                                                                **/
      19              : /********************************************************************/
      20              : #include "pari.h"
      21              : #include "paripriv.h"
      22              : 
      23              : static void
      24           28 : err_direuler(GEN x)
      25           28 : { pari_err_DOMAIN("direuler","constant term","!=", gen_1,x); }
      26              : 
      27              : /* s = t_POL (tolerate t_SER of valuation 0) of constant term = 1
      28              :  * d = minimal such that p^d > X
      29              :  * V indexed by 1..X will contain the a_n
      30              :  * v[1..n] contains the indices nj such that V[nj] != 0 */
      31              : static long
      32        33460 : dirmuleuler_small(GEN V, GEN v, long n, ulong p, GEN s, long d)
      33              : {
      34        33460 :   long i, j, m = n, D = minss(d+2, lg(s));
      35        33460 :   ulong q = 1, X = lg(V)-1;
      36              : 
      37       114002 :   for (i = 3, q = p; i < D; i++, q *= p) /* q*p does not overflow */
      38              :   {
      39        80542 :     GEN aq = gel(s,i);
      40        80542 :     if (gequal0(aq)) continue;
      41              :     /* j = 1 */
      42        66787 :     gel(V,q) = aq;
      43        66787 :     v[++n] = q;
      44      5092633 :     for (j = 2; j <= m; j++)
      45              :     {
      46      5025846 :       ulong nj = umuluu_le(uel(v,j), q, X);
      47      5025846 :       if (!nj) continue;
      48       335888 :       gel(V,nj) = gmul(aq, gel(V,v[j]));
      49       335888 :       v[++n] = nj;
      50              :     }
      51              :   }
      52        33460 :   return n;
      53              : }
      54              : 
      55              : /* ap != 0 for efficiency, p > sqrt(X) */
      56              : static void
      57       395598 : dirmuleuler_large(GEN V, ulong p, GEN ap)
      58              : {
      59       395598 :   long j, jp, X = lg(V)-1;
      60       395598 :   gel(V,p) = ap;
      61      1845382 :   for (j = 2, jp = 2*p; jp <= X; j++, jp += p) gel(V,jp) = gmul(ap, gel(V,j));
      62       395598 : }
      63              : 
      64              : static ulong
      65        10941 : direulertou(GEN a, GEN fl(GEN))
      66              : {
      67        10941 :   if (typ(a) != t_INT)
      68              :   {
      69           49 :     a = fl(a);
      70           28 :     if (typ(a) != t_INT) pari_err_TYPE("direuler", a);
      71              :   }
      72        10920 :   return signe(a)<=0 ? 0: itou(a);
      73              : }
      74              : 
      75              : static GEN
      76         4081 : direuler_Sbad(GEN V, GEN v, GEN Sbad, ulong *n)
      77              : {
      78         4081 :   long i, l = lg(Sbad);
      79         4081 :   ulong X = lg(V)-1;
      80         4081 :   GEN pbad = gen_1;
      81        10857 :   for (i = 1; i < l; i++)
      82              :   {
      83         6811 :     GEN ai = gel(Sbad,i), gq;
      84              :     ulong q;
      85         6811 :     if (typ(ai) != t_VEC || lg(ai) != 3)
      86           14 :       pari_err_TYPE("direuler [bad primes]",ai);
      87         6797 :     gq = gel(ai,1);
      88         6797 :     if (typ(gq) != t_INT || signe(gq) <= 0)
      89            7 :       pari_err_TYPE("direuler [prime expected]",gq);
      90         6790 :     if (lgefint(gq) == 3 && (q = uel(gq,2)) <= X)
      91              :     {
      92         5656 :       long d = ulogint(X, q) + 1;
      93         5656 :       GEN s = direuler_factor(gel(ai,2), d);
      94         5642 :       *n = dirmuleuler_small(V, v, *n, q, s, d);
      95         5642 :       pbad = muliu(pbad, q);
      96              :     }
      97              :   }
      98         4046 :   return pbad;
      99              : }
     100              : 
     101              : GEN
     102          658 : direuler_bad(void *E, GEN (*eval)(void *,GEN,long), GEN a,GEN b,GEN c, GEN Sbad)
     103              : {
     104              :   ulong au, bu, X, sqrtX, n, p;
     105          658 :   pari_sp av0 = avma;
     106              :   GEN gp, v, V;
     107              :   forprime_t T;
     108          658 :   au = direulertou(a, gceil);
     109          651 :   bu = direulertou(b, gfloor);
     110          644 :   X = c ? direulertou(c, gfloor): bu;
     111          637 :   if (X == 0) return cgetg(1,t_VEC);
     112          630 :   if (bu > X) bu = X;
     113          630 :   if (!u_forprime_init(&T, au, bu)) { set_avma(av0); return mkvec(gen_1); }
     114          616 :   v = vecsmall_ei(X, 1);
     115          616 :   V = vec_ei(X, 1);
     116          616 :   n = 1;
     117          616 :   if (Sbad) Sbad = direuler_Sbad(V, v, Sbad, &n);
     118          581 :   p = 1; gp = cgetipos(3); sqrtX = usqrt(X);
     119         8274 :   while (p <= sqrtX && (p = u_forprime_next(&T)))
     120         7714 :     if (!Sbad || umodiu(Sbad, p))
     121              :     {
     122         7609 :       long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */
     123              :       GEN s;
     124         7609 :       gp[2] = p; s = eval(E, gp, d);
     125         7588 :       n = dirmuleuler_small(V, v, n, p, s, d);
     126              :     }
     127       740173 :   while ((p = u_forprime_next(&T))) /* sqrt(X) < p <= X */
     128       739613 :     if (!Sbad || umodiu(Sbad, p))
     129              :     {
     130              :       GEN s;
     131       739606 :       gp[2] = p; s = eval(E, gp, 2); /* s either t_POL or t_SER of val 0 */
     132       739606 :       if (lg(s) > 3 && !gequal0(gel(s,3)))
     133       139139 :         dirmuleuler_large(V, p, gel(s,3));
     134              :     }
     135          560 :   return gc_GEN(av0,V);
     136              : }
     137              : 
     138              : /* return a t_SER or a truncated t_POL to precision n */
     139              : GEN
     140       752871 : direuler_factor(GEN s, long n)
     141              : {
     142       752871 :   long t = typ(s);
     143       752871 :   if (is_scalar_t(t))
     144              :   {
     145        33194 :     if (!gequal1(s)) err_direuler(s);
     146        33180 :     return scalarpol_shallow(s,0);
     147              :   }
     148       719677 :   switch(t)
     149              :   {
     150         5740 :     case t_POL: break; /* no need to RgXn_red */
     151       713622 :     case t_RFRAC:
     152              :     {
     153       713622 :       GEN p = gel(s,1), q = gel(s,2);
     154       713622 :       q = RgXn_red_shallow(q,n);
     155       713622 :       s = RgXn_inv(q, n);
     156       713622 :       if (typ(p) == t_POL && varn(p) == varn(q))
     157              :       {
     158           28 :         p = RgXn_red_shallow(p, n);
     159           28 :         s = RgXn_mul(s, p, n);
     160              :       }
     161              :       else
     162       713594 :         if (!gequal1(p)) s = RgX_Rg_mul(s, p);
     163       713622 :       if (!signe(s) || !gequal1(gel(s,2))) err_direuler(s);
     164       713608 :       break;
     165              :     }
     166          308 :     case t_SER:
     167          308 :       if (!signe(s) || valser(s) || !gequal1(gel(s,2))) err_direuler(s);
     168          308 :       break;
     169            7 :     default: pari_err_TYPE("direuler", s);
     170              :   }
     171       719656 :   return s;
     172              : }
     173              : 
     174              : struct eval_bad
     175              : {
     176              :   void *E;
     177              :   GEN (*eval)(void *, GEN);
     178              : };
     179              : static GEN
     180       688303 : eval_bad(void *E, GEN p, long n)
     181              : {
     182       688303 :   struct eval_bad *d = (struct eval_bad*) E;
     183       688303 :   return direuler_factor(d->eval(d->E, p), n);
     184              : }
     185              : GEN
     186          301 : direuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, GEN c)
     187              : {
     188              :   struct eval_bad d;
     189          301 :   d.E= E; d.eval = eval;
     190          301 :   return direuler_bad((void*)&d, eval_bad, a, b, c, NULL);
     191              : }
     192              : 
     193              : static GEN
     194        38731 : primelist(forprime_t *T, GEN Sbad, long n, long *running)
     195              : {
     196        38731 :   GEN P = cgetg(n+1, t_VECSMALL);
     197              :   long i, j;
     198       406945 :   for (i = 1, j = 1; i <= n; i++)
     199              :   {
     200       372645 :     ulong p = u_forprime_next(T);
     201       372645 :     if (!p) { *running = 0; break; }
     202       368214 :     if (Sbad && umodiu(Sbad, p)==0) continue;
     203       362684 :     uel(P,j++) = p;
     204              :   }
     205        38731 :   setlg(P, j);
     206        38731 :   return P;
     207              : }
     208              : 
     209              : GEN
     210         4438 : pardireuler(GEN worker, GEN a, GEN b, GEN c, GEN Sbad)
     211              : {
     212              :   ulong au, bu, X, sqrtX, n, snX, nX;
     213         4438 :   pari_sp av0 = avma;
     214              :   GEN v, V;
     215              :   forprime_t T;
     216              :   struct pari_mt pt;
     217         4438 :   long running = 1, pending = 0;
     218         4438 :   au = direulertou(a, gceil);
     219         4438 :   bu = direulertou(b, gfloor);
     220         4438 :   X = c ? direulertou(c, gfloor): bu;
     221         4438 :   if (X == 0) return cgetg(1,t_VEC);
     222         4438 :   if (bu > X) bu = X;
     223         4438 :   if (!u_forprime_init(&T, au, bu)) { set_avma(av0); return mkvec(gen_1); }
     224         4431 :   v = vecsmall_ei(X, 1);
     225         4431 :   V = vec_ei(X, 1);
     226         4431 :   n = 1;
     227         4431 :   if (Sbad) Sbad = direuler_Sbad(V, v, Sbad, &n);
     228         4431 :   sqrtX = usqrt(X); snX = uprimepi(sqrtX); nX = uprimepi(X);
     229         4431 :   if (snX)
     230              :   {
     231         4417 :     GEN P = primelist(&T, Sbad, snX, &running);
     232         4417 :     GEN R = gel(closure_callgenvec(worker, mkvec2(P, utoi(X))), 2);
     233         4417 :     long i, l = lg(P);
     234        24647 :     for (i = 1; i < l; i++)
     235              :     {
     236        20230 :       GEN s = gel(R,i);
     237        20230 :       n = dirmuleuler_small(V, v, n, uel(P,i), s, lg(s));
     238              :     }
     239           14 :   } else snX = 1;
     240         4431 :   mt_queue_start_lim(&pt, worker, (nX+snX-1)/snX);
     241        42542 :   while (running || pending)
     242              :   {
     243              :     GEN done;
     244        38111 :     GEN P = running? primelist(&T, Sbad, snX, &running): NULL;
     245        38111 :     mt_queue_submit(&pt, 0, P ? mkvec2(P, utoi(X)): NULL);
     246        38111 :     done = mt_queue_get(&pt, NULL, &pending);
     247        38111 :     if (done)
     248              :     {
     249        34314 :       GEN P = gel(done,1), R = gel(done,2);
     250        34314 :       long j, l = lg(P);
     251       376768 :       for (j=1; j<l; j++)
     252              :       {
     253       342454 :         GEN F = gel(R,j);
     254       342454 :         if (degpol(F) && !gequal0(gel(F,3)))
     255       256459 :           dirmuleuler_large(V, uel(P,j), gel(F,3));
     256              :       }
     257              :     }
     258              :   }
     259         4431 :   mt_queue_end(&pt);
     260         4431 :   return gc_GEN(av0,V);
     261              : }
     262              : 
     263              : /********************************************************************/
     264              : /**                                                                **/
     265              : /**                 DIRPOWERS and DIRPOWERSSUM                     **/
     266              : /**                                                                **/
     267              : /********************************************************************/
     268              : 
     269              : /* [1^B,...,N^B] */
     270              : GEN
     271          686 : vecpowuu(long N, ulong B)
     272              : {
     273              :   GEN v;
     274              :   long p, i;
     275              :   forprime_t T;
     276              : 
     277          686 :   if (B <= 8000)
     278              :   {
     279          686 :     if (!B) return const_vec(N,gen_1);
     280          679 :     v = cgetg(N+1, t_VEC); if (N == 0) return v;
     281          679 :     gel(v,1) = gen_1;
     282          679 :     if (B == 1)
     283        92736 :       for (i = 2; i <= N; i++) gel(v,i) = utoipos(i);
     284          469 :     else if (B == 2)
     285              :     {
     286              :       ulong o, s;
     287          273 :       if (N & HIGHMASK)
     288            0 :         for (i = 2, o = 3; i <= N; i++, o += 2)
     289            0 :           gel(v,i) = addiu(gel(v,i-1), o);
     290              :       else
     291        31073 :         for (i = 2, s = 1, o = 3; i <= N; i++, s += o, o += 2)
     292        30800 :           gel(v,i) = utoipos(s + o);
     293              :     }
     294          196 :     else if (B == 3)
     295          840 :       for (i = 2; i <= N; i++) gel(v,i) = powuu(i, B);
     296              :     else
     297              :     {
     298          182 :       long k, Bk, e = expu(N);
     299         7553 :       for (i = 3; i <= N; i += 2) gel(v,i) = powuu(i, B);
     300         1239 :       for (k = 1; k <= e; k++)
     301              :       {
     302         1057 :         N >>= 1; Bk = B * k;
     303         8498 :         for (i = 1; i <= N; i += 2) gel(v, i << k) = shifti(gel(v, i), Bk);
     304              :       }
     305              :     }
     306          679 :     return v;
     307              :   }
     308            0 :   v = const_vec(N, NULL);
     309            0 :   u_forprime_init(&T, 3, N);
     310            0 :   while ((p = u_forprime_next(&T)))
     311              :   {
     312              :     long m, pk, oldpk;
     313            0 :     gel(v,p) = powuu(p, B);
     314            0 :     for (pk = p, oldpk = p; pk; oldpk = pk, pk = umuluu_le(pk,p,N))
     315              :     {
     316            0 :       if (pk != p) gel(v,pk) = mulii(gel(v,oldpk), gel(v,p));
     317            0 :       for (m = N/pk; m > 1; m--)
     318            0 :         if (gel(v,m) && m%p) gel(v, m*pk) = mulii(gel(v,m), gel(v,pk));
     319              :     }
     320              :   }
     321            0 :   gel(v,1) = gen_1;
     322            0 :   for (i = 2; i <= N; i+=2)
     323              :   {
     324            0 :     long vi = vals(i);
     325            0 :     gel(v,i) = shifti(gel(v,i >> vi), B * vi);
     326              :   }
     327            0 :   return v;
     328              : }
     329              : 
     330              : /* does x^s require log(x) ? */
     331              : static long
     332        23133 : get_needlog(GEN s)
     333              : {
     334        23133 :   switch(typ(s))
     335              :   {
     336        10493 :     case t_REAL: return 2; /* yes but not powcx */
     337         9492 :     case t_COMPLEX: return 1; /* yes using powcx */
     338         3148 :     default: return 0; /* no */
     339              :   }
     340              : }
     341              : /* [1^B,...,N^B] */
     342              : GEN
     343        22272 : vecpowug(long N, GEN B, long prec)
     344              : {
     345        22272 :   GEN v, logp = NULL;
     346        22272 :   long gp[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0};
     347        22272 :   long p, precp = 2, prec0, prec1, needlog;
     348              :   forprime_t T;
     349        22272 :   if (N == 1) return mkvec(gen_1);
     350        22251 :   if (typ(B) == t_INT && lgefint(B) <= 3 && signe(B) >= 0)
     351          168 :     return vecpowuu(N, itou(B));
     352        22083 :   needlog = get_needlog(B);
     353        22083 :   prec1 = prec0 = prec;
     354        22083 :   if (needlog == 1) prec1 = powcx_prec(log2((double)N), B, prec);
     355        22083 :   u_forprime_init(&T, 2, N);
     356        22083 :   v = const_vec(N, NULL);
     357        22083 :   gel(v,1) = gen_1;
     358      1691007 :   while ((p = u_forprime_next(&T)))
     359              :   {
     360              :     long m, pk, oldpk;
     361              :     GEN u;
     362      1668924 :     gp[2] = p;
     363      1668924 :     if (needlog)
     364              :     {
     365       208601 :       if (!logp)
     366        37912 :         logp = logr_abs(utor(p, prec1));
     367              :       else
     368              :       { /* Assuming p and precp are odd,
     369              :          * log p = log(precp) + 2 atanh((p - precp) / (p + precp)) */
     370       170689 :         ulong a = p >> 1, b = precp >> 1; /* p = 2a + 1, precp = 2b + 1 */
     371       170689 :         GEN z = atanhuu(a - b, a + b + 1, prec1); /* avoid overflow */
     372       170689 :         shiftr_inplace(z, 1); logp = addrr(logp, z);
     373              :       }
     374        92822 :       u = needlog == 1? powcx(gp, logp, B, prec0)
     375       208601 :                       : mpexp(gmul(B, logp));
     376       208601 :       if (p == 2) logp = NULL; /* reset: precp must be odd */
     377              :     }
     378              :     else
     379      1460323 :       u = gpow(gp, B, prec0);
     380      1668924 :     precp = p;
     381      1668924 :     gel(v,p) = u; /* p^B */
     382      1668924 :     if (prec0 != prec) gel(v,p) = gprec_wtrunc(gel(v,p), prec);
     383      3503841 :     for (pk = p, oldpk = p; pk; oldpk = pk, pk = umuluu_le(pk,p,N))
     384              :     {
     385      1834917 :       if (pk != p) gel(v,pk) = gmul(gel(v,oldpk), gel(v,p));
     386     47186659 :       for (m = N/pk; m > 1; m--)
     387     45351742 :         if (gel(v,m) && m%p) gel(v, m*pk) = gmul(gel(v,m), gel(v,pk));
     388              :     }
     389              :   }
     390        22083 :   return v;
     391              : }
     392              : 
     393              : GEN
     394          903 : dirpowers(long n, GEN x, long prec)
     395              : {
     396              :   pari_sp av;
     397              :   GEN v;
     398          903 :   if (n <= 0) return cgetg(1, t_VEC);
     399          889 :   av = avma; v = vecpowug(n, x, prec);
     400          889 :   if (typ(x) == t_INT && lgefint(x) <= 3 && signe(x) >= 0 && cmpiu(x, 2) <= 0)
     401          133 :     return v;
     402          756 :   return gc_GEN(av, v);
     403              : }
     404              : 
     405              : /* f is a totally multiplicative function of modulus 0 or 1
     406              :  * (essentially a Dirichlet character). Compute simultaneously
     407              :  * sum_{0 < n <= N} f(n)n^s and sum_{0 < n <= N} f(n)n^{-1-conj(s)}
     408              :  * Warning: s is conjugated, but not f. Main application for Riemann-Siegel,
     409              :  * where we need R(chi,s) and conj(R(chi,1-conj(s))). */
     410              : 
     411              : static GEN
     412         3234 : vecmulsqlv(GEN Q, GEN V)
     413              : {
     414              :   long l, i;
     415              :   GEN W;
     416         3234 :   if (typ(V) != t_VEC) return RgV_Rg_mul(Q, V);
     417         1239 :   l = lg(Q); W = cgetg(l, t_VEC);
     418        62244 :   for (i = 1; i < l; i++) gel(W, i) = vecmul(gel(Q, i), V);
     419         1239 :   return W;
     420              : }
     421              : 
     422              : /* P = prime divisors of (squarefree) n, V[i] = i^s for i <= sq.
     423              :  * Return NULL if n is not sq-smooth, else f(n)n^s */
     424              : static GEN
     425     18262659 : smallfact(ulong n, GEN P, ulong sq, GEN V)
     426              : {
     427              :   long i, l;
     428              :   ulong p, m, o;
     429              :   GEN c;
     430     18262659 :   if (n <= sq) return gel(V,n);
     431     18213680 :   l = lg(P); m = p = uel(P, l-1); if (p > sq) return NULL;
     432      3864669 :   for (i = l-2; i > 1; i--, m = o) { p = uel(P,i); o = m*p; if (o > sq) break; }
     433      3831353 :   c = gel(V,m); n /= m; /* m <= sq, o = m * p > sq */
     434      3831353 :   if (n > sq) { c = vecmul(c, gel(V,p)); n /= p; }
     435      3825336 :   return vecmul(c, gel(V,n));
     436              : }
     437              : 
     438              : static GEN
     439          973 : _Qtor(GEN x, long prec)
     440          973 : { return typ(x) == t_FRAC? fractor(x, prec): x; }
     441              : static GEN
     442         2457 : Qtor(GEN x, long prec)
     443              : {
     444         2457 :   long tx = typ(x);
     445         3430 :   if (tx == t_VEC || tx == t_COL) pari_APPLY_same(_Qtor(gel(x, i), prec));
     446         1589 :   return tx == t_FRAC? fractor(x, prec): x;
     447              : }
     448              : 
     449              : static GEN
     450          238 : vecf(long N, void *E, GEN (*f)(void *, ulong, long), long prec)
     451              : {
     452              :   GEN v;
     453              :   long n;
     454          238 :   if (!f) return NULL;
     455          140 :   v = cgetg(N + 1, t_VEC);
     456        33481 :   for (n = 1; n <= N; n++) gel(v,n) = f(E, n, prec);
     457          140 :   return v;
     458              : }
     459              : 
     460              : /* Here #V = #F > 0 is small. Analogous to dotproduct, with following
     461              :  * semantic differences: uses V[1] = 1; V has scalar values but F may have
     462              :  * vector values */
     463              : static GEN
     464          301 : naivedirpowerssum(GEN V, GEN F, long prec)
     465              : {
     466              :   GEN S;
     467          301 :   if (!F) S = RgV_sum(V);
     468              :   else
     469              :   {
     470          189 :     long n, l = lg(V);
     471          189 :     S = gel(F,1); /* V[1] = 1 */
     472        34447 :     for (n = 2; n < l; n++) S = gadd(S, gmul(gel(V, n), gel(F, n)));
     473              :   }
     474          301 :   return Qtor(S, prec);
     475              : }
     476              : 
     477              : /* set *p0 and *p1 to 0 and 1 in the algebra where f takes its values */
     478              : static int
     479         1092 : mk01(void *E, GEN (*f)(void*,ulong,long), long prec, GEN *p0, GEN *p1)
     480              : {
     481         1092 :   *p0 = gen_0; *p1 = gen_1;
     482         1092 :   if (!f) return 1;
     483         1057 :   *p1 = f(E, 1, prec);
     484         1057 :   if (is_vec_t(typ(*p1)))
     485              :   {
     486          406 :     long l = lg(*p1);
     487          406 :     if (l == 1) { *p0 = *p1 = NULL; return 0; }
     488          406 :     *p0 = const_vec(l-1, gen_0);
     489              :   }
     490         1057 :   return 1;
     491              : }
     492              : static GEN
     493            0 : mktrivial(long both)
     494              : {
     495            0 :   if (!both) return cgetg(1, t_VEC);
     496            0 :   return mkvec2(cgetg(1,t_VEC), cgetg(1,t_VEC));
     497              : }
     498              : 
     499              : static GEN
     500          280 : smalldirpowerssum(long N, GEN s, void *E, GEN (*f)(void *, ulong, long),
     501              :                   long both, long prec)
     502              : {
     503              :   GEN F, V, S, SB;
     504          280 :   if (!N)
     505              :   {
     506              :     GEN zerf, onef;
     507           42 :     if (!mk01(E, f, prec, &zerf, &onef)) return mktrivial(both);
     508           42 :     return zerf;
     509              :   }
     510          238 :   V = vecpowug(N, s, prec);
     511          238 :   F = vecf(N, E, f, prec);
     512          238 :   S = naivedirpowerssum(V, F, prec);
     513          238 :   if (!both) return S;
     514           84 :   if ((both==2 || !f) && gequalm1(gmul2n(real_i(s), 1)))
     515           21 :     SB = S;
     516              :   else
     517              :   {
     518           63 :     GEN FB = (both == 1 && F)? conj_i(F): F;
     519              :     long n;
     520         1876 :     for (n = 2; n <= N; n++) gel(V, n) = ginv(gmulsg(n, gel(V, n)));
     521           63 :     SB = naivedirpowerssum(V, FB, prec);
     522              :   }
     523           84 :   return mkvec2(S, SB);
     524              : }
     525              : 
     526              : static void
     527        68568 : v2unpack(GEN v, GEN *pV, GEN *pVB)
     528              : {
     529        68568 :   if (typ(v) == t_COL) { *pV = gel(v,1); *pVB = gel(v,2); }
     530        68437 :   else { *pV = v; *pVB = NULL; }
     531        68568 : }
     532              : static GEN
     533        69544 : v2pack(GEN V, GEN VB) { return VB? mkcol2(V,VB): V; }
     534              : 
     535              : static GEN
     536         1050 : dirpowsuminit(GEN s, GEN onef, GEN zerf, void *E, GEN (*f)(void *, ulong, long),              GEN data, long both)
     537              : {
     538         1050 :   long needlog = data[1], prec0 = data[2], prec1 = data[3];
     539         1050 :   ulong a, b, c, e, q, n, sq = usqrt(data[4]);
     540         1050 :   GEN V = cgetg(sq+1, t_VEC), W = cgetg(sq+1, t_VEC), VB = NULL, WB = NULL;
     541         1050 :   GEN Q = cgetg(sq+1, t_VEC), Z = cgetg(sq+1, t_VEC), QB = NULL, ZB = NULL;
     542         1050 :   GEN logp, c2, Q2, Q3, Q6, c2B = NULL, Q2B = NULL, Q3B = NULL, Q6B = NULL;
     543         1050 :   long gp[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0};
     544              : 
     545         1050 :   if (both == 1 || (both == 2 && !gequal(real_i(s), gneg(ghalf))))
     546           28 :   { VB = cgetg(sq+1, t_VEC); WB = cgetg(sq+1, t_VEC); QB = cgetg(sq+1, t_VEC);}
     547         1050 :   gel(V, 1) = gel(W, 1) = gel(Q, 1) = onef;
     548         1050 :   if (VB) { gel(VB, 1) = gel(WB, 1) = gel(QB, 1) = onef; }
     549         1050 :   c2 = gpow(gen_2, s, prec0); if (VB) c2B = ginv(gmul2n(conj_i(c2), 1));
     550         1050 :   if (f)
     551              :   {
     552         1029 :     GEN tmp2 = f(E, 2, prec0);
     553         1029 :     c2 = gmul(c2, tmp2); if (VB) c2B = gmul(c2B, tmp2);
     554              :   }
     555         1050 :   gel(V,2) = c2; /* f(2) 2^s */
     556         1050 :   gel(W,2) = Qtor(gadd(c2, onef), prec0);
     557         1050 :   gel(Q,2) = Qtor(gadd(vecsqr(c2), onef), prec0);
     558         1050 :   if (VB)
     559              :   {
     560           28 :     gel(VB, 2) = c2B; gel(WB, 2) = Qtor(gadd(c2B, onef), prec0);
     561           28 :     gel(QB, 2) = Qtor(gadd(vecsqr(c2B), onef), prec0);
     562              :   }
     563         1050 :   logp = NULL;
     564       158795 :   for (n = 3; n <= sq; n++)
     565              :   {
     566       157745 :     GEN u = NULL, uB = NULL, ks = f ? f(E, n, prec0) : gen_1;
     567       157745 :     if (gequal0(ks)) ks = NULL;
     568       157745 :     if (odd(n))
     569              :     {
     570        79352 :       gp[2] = n;
     571        79352 :       if (needlog)
     572              :       {
     573        77805 :         if (!logp)
     574         1029 :           logp = logr_abs(utor(n, prec1));
     575              :         else
     576              :         { /* log n = log(n-2) + 2 atanh(1 / (n - 1)) */
     577        76776 :           GEN z = atanhuu(1, n - 1, prec1);
     578        76776 :           shiftr_inplace(z, 1); logp = addrr(logp, z);
     579              :         }
     580        77805 :         if (ks)
     581        76230 :           u = needlog == 1? powcx(gp, logp, s, prec0) : mpexp(gmul(s, logp));
     582              :       }
     583         1547 :       else if (ks) u = gpow(gp, s, prec0);
     584        79352 :       if (ks)
     585              :       {
     586        77763 :         if (VB) uB = gmul(ginv(gmulsg(n, conj_i(u))), ks);
     587        77763 :         u = gmul(u, ks); /* f(n) n^s */
     588              :       }
     589              :     }
     590              :     else
     591              :     {
     592        78393 :       u = vecmul(c2, gel(V, n >> 1));
     593        78393 :       if (VB) uB = vecmul(c2B, gel(VB, n >> 1));
     594              :     }
     595       157745 :     if (ks)
     596              :     {
     597       154693 :       gel(V,n) = u; /* f(n) n^s */
     598       154693 :       gel(W,n) = gadd(gel(W, n-1), gel(V,n));        /*= sum_{i<=n} f(i)i^s */
     599       154693 :       gel(Q,n) = gadd(gel(Q, n-1), vecsqr(gel(V,n)));/*= sum_{i<=n} f(i^2)i^2s*/
     600       154693 :       if (VB)
     601              :       {
     602          483 :         gel(VB,n) = uB;
     603          483 :         gel(WB,n) = gadd(gel(WB,n-1), gel(VB,n));
     604          483 :         gel(QB,n) = gadd(gel(QB,n-1), vecsqr(gel(VB,n)));
     605              :       }
     606              :     }
     607              :     else
     608              :     {
     609         3052 :       gel(V,n) = zerf; gel(W,n) = gel(W, n-1); gel(Q,n) = gel(Q, n-1);
     610         3052 :       if (VB)
     611           21 :       { gel(VB,n) = zerf; gel(WB,n) = gel(WB, n-1); gel(QB,n) = gel(QB, n-1); }
     612              :     }
     613              :   }
     614         1050 :   Q2 = vecmulsqlv(Q, gel(V,2));
     615         1050 :   Q3 = vecmulsqlv(Q, gel(V,3));
     616         1050 :   Q6 = vecmulsqlv(Q, gel(V,6));
     617         1050 :   if (VB)
     618              :   {
     619           28 :     Q2B = vecmulsqlv(QB, gel(VB,2));
     620           28 :     Q3B = vecmulsqlv(QB, gel(VB,3));
     621           28 :     Q6B = vecmulsqlv(QB, gel(VB,6));
     622              :   }
     623              :   /* a,b,c,e = sqrt(q), sqrt(q/2), sqrt(q/3), sqrt(q/6)
     624              :    * Z[q] = Q[a] + 2^s Q[b] + 3^s Q[c] + 6^s Q[e], with Q[0] = 0 */
     625         1050 :   gel(Z, 1) = onef;
     626         1050 :   gel(Z, 2) = gel(W, 2);
     627         1050 :   gel(Z, 3) = gel(W, 3);
     628         1050 :   gel(Z, 4) = gel(Z, 5) = gel(W, 4);
     629         1050 :   gel(Z, 6) = gel(Z, 7) = gadd(gel(W, 4), gel(V, 6));
     630         1050 :   if (VB)
     631              :   {
     632           28 :     ZB = cgetg(sq+1, t_VEC);
     633           28 :     gel(ZB, 1) = onef;
     634           28 :     gel(ZB, 2) = gel(WB, 2);
     635           28 :     gel(ZB, 3) = gel(WB, 3);
     636           28 :     gel(ZB, 4) = gel(ZB, 5) = gel(WB, 4);
     637           28 :     gel(ZB, 6) = gel(ZB, 7) = gadd(gel(WB, 4), gel(VB, 6));
     638              :   }
     639         1050 :   a = 2; b = c = e = 1;
     640       153545 :   for (q = 8; q <= sq; q++)
     641              :   { /* Gray code: at most one of a,b,c,d differs (by 1) from previous value */
     642       152495 :     GEN z = gel(Z, q - 1), zB = NULL;
     643              :     ulong na, nb, nc, ne, na2, nb2, nc2, ne2;
     644       152495 :     if (VB) zB = gel(ZB, q - 1);
     645       152495 :     if ((na = usqrt(q)) != a)
     646         9191 :     { a = na; na2 = na * na; z = gadd(z, gel(V, na2));
     647         9191 :       if (VB) zB = gadd(zB, gel(VB, na2)); }
     648       143304 :     else if ((nb = usqrt(q / 2)) != b)
     649         6216 :     { b = nb; nb2 = 2 * nb * nb; z = gadd(z, gel(V, nb2));
     650         6216 :       if (VB) zB = gadd(zB, gel(VB, nb2)); }
     651       137088 :     else if ((nc = usqrt(q / 3)) != c)
     652         5418 :     { c = nc; nc2 = 3 * nc * nc; z = gadd(z, gel(V, nc2));
     653         5418 :       if (VB) zB = gadd(zB, gel(VB, nc2)); }
     654       131670 :     else if ((ne = usqrt(q / 6)) != e)
     655         3108 :     { e = ne; ne2 = 6 * ne * ne; z = gadd(z, gel(V, ne2));
     656         3108 :       if (VB) zB = gadd(zB, gel(VB, ne2)); }
     657       152495 :     gel(Z, q) = z; if (VB) gel(ZB, q) = zB;
     658              :   }
     659         1078 :   return v2pack(mkvecn(7, V, W, Q, Q2, Q3, Q6, Z),
     660           28 :                 VB? mkvecn(7, VB, WB, QB, Q2B, Q3B, Q6B, ZB): NULL);
     661              : }
     662              : 
     663              : static GEN
     664        38342 : sumprimeloop(forprime_t *pT, GEN s, long N, GEN data, GEN S, GEN W, GEN WB,
     665              :              void *E, GEN (*f)(void *, ulong, long))
     666              : {
     667        38342 :   pari_sp av = avma;
     668        38342 :   long needlog = data[1], prec0 = data[2], prec1 = data[3];
     669        38342 :   long gp[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0};
     670        38342 :   ulong p, precp = 0;
     671        38342 :   GEN logp = NULL, SB = WB? S: NULL;
     672              : 
     673      5282383 :   while ((p = u_forprime_next(pT)))
     674              :   {
     675      5243670 :     GEN u = NULL, ks;
     676      5243670 :     if (!f) ks = gen_1;
     677              :     else
     678              :     {
     679      5174783 :       ks = f(E, p, prec1);
     680      5174597 :       if (gequal0(ks)) ks = NULL;
     681      5174986 :       if (ks && gequal1(ks)) ks = gen_1;
     682              :     }
     683      5244058 :     gp[2] = p;
     684      5244058 :     if (needlog)
     685              :     {
     686      5167842 :       if (!logp)
     687        30424 :         logp = logr_abs(utor(p, prec1));
     688              :       else
     689              :       { /* Assuming p and precp are odd,
     690              :          * log p = log(precp) + 2 atanh((p - precp) / (p + precp)) */
     691      5137418 :         ulong a = p >> 1, b = precp >> 1; /* p = 2a + 1, precp = 2b + 1 */
     692      5137418 :         GEN z = atanhuu(a - b, a + b + 1, prec1); /* avoid overflow */
     693      5139340 :         shiftr_inplace(z, 1); logp = addrr(logp, z);
     694              :       }
     695     10333833 :       if (ks) u = needlog == 1? powcx(gp, logp, s, prec0)
     696      5166799 :                               : mpexp(gmul(s, logp));
     697              :     }
     698        76216 :     else if (ks) u = gpow(gp, s, prec0);
     699      5246135 :     if (ks)
     700              :     {
     701      5246107 :       S = gadd(S, vecmul(gel(W, N / p), ks == gen_1? u: gmul(ks, u)));
     702      5244013 :       if (WB)
     703              :       {
     704         2457 :         GEN w = gel(WB, N / p);
     705         2457 :         if (ks != gen_1) w = vecmul(ks, w);
     706         2457 :         SB = gadd(SB, gdiv(w, gmulsg(p, conj_i(u))));
     707              :       }
     708              :     }
     709      5244041 :     precp = p;
     710      5244041 :     if ((p & 0x1ff) == 1)
     711              :     {
     712        19565 :       if (!logp) (void)gc_all(av, SB? 2: 1, &S, &SB);
     713        19285 :       else (void)gc_all(av, SB? 3: 2, &S, &logp, &SB);
     714              :     }
     715              :   }
     716        38149 :   return v2pack(S, SB);
     717              : }
     718              : 
     719              : static GEN
     720        48475 : add4(GEN a, GEN b, GEN c, GEN d) { return gadd(gadd(a,b), gadd(c,d)); }
     721              : 
     722              : static const long step = 2048;
     723              : static int
     724        29561 : mksqfloop(long N, long x1, GEN R, GEN RB, GEN *pS, GEN *pSB)
     725              : {
     726        29561 :   GEN V = gel(R,1), Q = gel(R,3), Q2 = gel(R,4);
     727        29561 :   GEN Q3 = gel(R,5), Q6 = gel(R,6), Z = gel(R,7);
     728        29561 :   GEN v, VB = NULL, QB = NULL, Q2B = NULL, Q3B = NULL, Q6B = NULL, ZB = NULL;
     729        29561 :   long x2, j, lv, sq = lg(V)-1;
     730              : 
     731        29561 :   if (RB)
     732           28 :   { VB = gel(RB,1); QB = gel(RB,3); Q2B = gel(RB,4);
     733           28 :     Q3B = gel(RB,5), Q6B = gel(RB,6); ZB = gel(RB,7); }
     734              :   /* beware overflow, fuse last two bins (avoid a tiny remainder) */
     735        29561 :   x2 = (N >= 2*step && N - 2*step >= x1)? x1-1 + step: N;
     736        29561 :   v = vecfactorsquarefreeu_coprime(x1, x2, mkvecsmall2(2, 3));
     737        35395 :   lv = lg(v);
     738     60124192 :   for (j = 1; j < lv; j++)
     739     60094631 :     if (gel(v,j))
     740              :     {
     741     18264476 :       ulong d = x1 - 1 + j; /* squarefree, coprime to 6 */
     742     18264476 :       GEN t = smallfact(d, gel(v,j), sq, V), u;
     743     18249114 :       GEN tB = NULL, uB = NULL; /* = f(d) d^s */
     744              :       long a, b, c, e, q;
     745     18249114 :       if (!t || gequal0(t)) continue;
     746      3820904 :       if (VB) tB = vecinv(gmulsg(d, conj_i(t)));
     747              :       /* warning: gives 1/conj(f(d)) d^(-1-conj(s)), equal to
     748              :          f(d) d^(-1-conj(s)) only if |f(d)|=1. */
     749              :       /* S += f(d) * d^s * Z[q] */
     750      3876683 :       q = N / d;
     751      3876683 :       if (q == 1)
     752              :       {
     753      1478442 :         *pS = gadd(*pS, t); if (VB) *pSB = gadd(*pSB, tB);
     754      1479584 :         continue;
     755              :       }
     756      2398241 :       if (q <= sq) { u = gel(Z, q); if (VB) uB = gel(ZB, q); }
     757              :       else
     758              :       {
     759        48225 :         a = usqrt(q); b = usqrt(q / 2); c = usqrt(q / 3); e = usqrt(q / 6);
     760        48293 :         u = add4(gel(Q,a), gel(Q2,b), gel(Q3,c), gel(Q6,e));
     761        48293 :         if (VB) uB = add4(gel(QB,a), gel(Q2B,b), gel(Q3B,c), gel(Q6B,e));
     762              :       }
     763      2398309 :       *pS = gadd(*pS, vecmul(t, u)); if (VB) *pSB = gadd(*pSB, vecmul(tB, uB));
     764              :     }
     765        29561 :   return x2 == N;
     766              : }
     767              : 
     768              : static GEN
     769         1050 : mkdata(long N, GEN s, long prec)
     770              : {
     771         1050 :   long needlog, prec0, prec1, m = mt_nbthreads(), STEP = maxss(N / (m * m), 1);
     772         1050 :   prec1 = prec0 = prec + EXTRAPRECWORD;
     773         1050 :   needlog = get_needlog(s);
     774         1050 :   if (needlog == 1) prec1 = powcx_prec(log2((double)N), s, prec);
     775         1050 :   return mkvecsmalln(5, needlog, prec0, prec1, N, STEP);
     776              : }
     777              : 
     778              : static GEN
     779        13748 : gp_callUp(void *E, ulong x, long prec)
     780              : {
     781        13748 :   long n[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0};
     782        13748 :   n[2] = x; return gp_callprec(E, n, prec);
     783              : }
     784              : 
     785              : /* both is
     786              :  * 0: sum_{n<=N}f(n)n^s
     787              :  * 1: sum for (f,s) and (conj(f),-1-s)
     788              :  * 2: sum for (f,s) and (f,-1-s), assuming |f(n)| in {0,1} */
     789              : static GEN
     790          203 : dirpowerssumfun_i(ulong N, GEN s, void *E, GEN (*f)(void *, ulong, long),
     791              :                   long both, long prec)
     792              : {
     793              :   forprime_t T;
     794              :   pari_sp av;
     795              :   GEN onef, zerf, R, RB, W, WB, S, SB, data;
     796              :   ulong x1;
     797              : 
     798          203 :   if ((f && N < 49) || (!f && N < 1000))
     799          140 :     return smalldirpowerssum(N, s, E, f, both, prec);
     800           63 :   if (!mk01(E, f, prec, &zerf, &onef)) return mktrivial(both);
     801           63 :   data = mkdata(N, s, prec); s = gprec_w(s, prec + EXTRAPRECWORD);
     802           63 :   v2unpack(dirpowsuminit(s, onef, zerf, E, f, data, both), &R, &RB);
     803           63 :   W = gel(R,2); WB = RB? gel(RB,2): NULL;
     804           63 :   av = avma; u_forprime_init(&T, lg(W), N);
     805           63 :   v2unpack(sumprimeloop(&T, s, N, data, zerf, W, WB, E, f), &S, &SB);
     806           63 :   for(x1 = 1;; x1 += step)
     807              :   {
     808          413 :     if (mksqfloop(N, x1, R, RB, &S, &SB))
     809           63 :       return both? mkvec2(S, conj_i(SB? SB: S)): S;
     810          350 :     (void)gc_all(av, SB? 2: 1, &S, &SB);
     811              :   }
     812              : }
     813              : GEN
     814          203 : dirpowerssumfun(ulong N, GEN s, void *E, GEN (*f)(void *, ulong, long),
     815              :                 long both, long prec)
     816              : {
     817          203 :   pari_sp av = avma;
     818          203 :   return gc_GEN(av, dirpowerssumfun_i(N, s, E, f, both, prec));
     819              : }
     820              : 
     821              : GEN
     822          133 : dirpowerssum(ulong N, GEN s, long both, long prec)
     823          133 : { return dirpowerssumfun(N, s, NULL, NULL, both, prec); }
     824              : 
     825              : GEN
     826          154 : dirpowerssum0(GEN N, GEN s, GEN f, long both, long prec)
     827              : {
     828          154 :   if (typ(N) != t_INT) pari_err_TYPE("dirpowerssum", N);
     829          147 :   if (signe(N) <= 0) N = gen_0;
     830          147 :   if (!f) return dirpowerssum(itou(N), s, both, prec);
     831           70 :   if (typ(f) != t_CLOSURE) pari_err_TYPE("dirpowerssum", f);
     832           70 :   return dirpowerssumfun(itou(N), s, (void*)f, gp_callUp, both, prec);
     833              : }
     834              : 
     835              : GEN
     836        29148 : parsqf_worker(GEN gk, GEN vR, GEN gN)
     837              : {
     838        29148 :   pari_sp av = avma;
     839              :   GEN R, RB, onef, S, SB;
     840        29148 :   long k = itou(gk), N = itou(gN), x1 = 1 + step * k;
     841        29148 :   v2unpack(vR, &R, &RB); onef = gmael(R,1,1);
     842        29148 :   S = SB = is_vec_t(typ(onef)) ? zerovec(lg(onef) - 1): gen_0;
     843        29148 :   (void)mksqfloop(N, x1, R, RB, &S, &SB);
     844        29148 :   return gc_GEN(av, v2pack(S, RB? SB: NULL));
     845              : }
     846              : 
     847              : static GEN
     848      5351435 : mycallvec(void *f, ulong n, long prec)
     849              : {
     850      5351435 :   GEN F = (GEN)f;
     851      5351435 :   if (!f) return gen_1;
     852       390610 :   if (typ(F) == t_CLOSURE) return gp_callUp(f, n, prec);
     853       390610 :   return gel(F, (n-1) % (lg(F)-1) + 1);
     854              : }
     855              : 
     856              : GEN
     857        38309 : parsumprimefun_worker(GEN gk, GEN s, GEN zerf, GEN data, GEN vW, GEN f)
     858              : {
     859        38309 :   pari_sp av = avma;
     860              :   forprime_t T;
     861              :   GEN W, WB, S;
     862        38309 :   long k = itou(gk), sq, N = data[4], STEP = data[5];
     863              : 
     864        38309 :   v2unpack(vW, &W, &WB); sq = lg(W)-1;
     865        38304 :   if (isintzero(f)) f = NULL;
     866        38298 :   u_forprime_init(&T, k * STEP + sq + 1, minss(N, (k + 1) * STEP + sq));
     867        38278 :   S = sumprimeloop(&T, s, N, data, zerf, W, WB, (void*)f, mycallvec);
     868        38295 :   return gc_GEN(av, S);
     869              : }
     870              : 
     871              : static GEN
     872          987 : vR_get_vW(GEN vR)
     873              : {
     874              :   GEN R, RB, W, WB;
     875          987 :   v2unpack(vR, &R, &RB); W = gel(R,2); WB = RB? gel(RB,2): NULL;
     876          987 :   return v2pack(W, WB);
     877              : }
     878              : 
     879              : static GEN
     880          987 : halfconj(long both, GEN V)
     881          987 : { return both ? mkvec2(gel(V, 1), gconj(gel(V, 2))) : V; }
     882              : 
     883              : static GEN
     884         1127 : pardirpowerssumfun_i(GEN f, ulong N, GEN s, long both, long prec)
     885              : {
     886              :   GEN worker, worker2, data, vR, onef, zerf;
     887              : 
     888         1127 :   if ((f && N < 49) || (!f && N < 10000UL))
     889          140 :     return smalldirpowerssum(N, s, (void*)f, mycallvec, both, prec);
     890          987 :   if (!mk01((void*)f, mycallvec, prec, &zerf, &onef)) return mktrivial(both);
     891          987 :   data = mkdata(N, s, prec); s = gprec_w(s, prec + EXTRAPRECWORD);
     892          987 :   vR = dirpowsuminit(s, onef, zerf, (void*)f, mycallvec, data, both);
     893          987 :   worker = snm_closure(is_entry("_parsumprimefun_worker"),
     894              :                        mkvecn(5, s, zerf, data, vR_get_vW(vR), f? f: gen_0));
     895          987 :   worker2 = snm_closure(is_entry("_parsqf_worker"), mkvec2(vR, utoi(N)));
     896         1974 :   return halfconj(both,
     897          987 :                   gadd(parsum(gen_0, utoipos((N-1) / data[5]), worker),
     898          987 :                        parsum(gen_0, utoipos(maxss((N-1) / step - 1, 0)), worker2)));
     899              : }
     900              : 
     901              : GEN
     902         1127 : pardirpowerssumfun(GEN f, ulong N, GEN s, long both, long prec)
     903              : {
     904         1127 :   pari_sp av = avma;
     905         1127 :   return gc_GEN(av, pardirpowerssumfun_i(f, N, s, both, prec));
     906              : }
     907              : GEN
     908            0 : pardirpowerssum0(GEN N, GEN s, GEN f, long both, long prec)
     909              : {
     910            0 :   if (typ(N) != t_INT) pari_err_TYPE("pardirpowerssum", N);
     911            0 :   return pardirpowerssumfun(f, itou(N), s, both, prec);
     912              : }
     913              : GEN
     914            0 : pardirpowerssum(ulong N, GEN s, long prec)
     915            0 : { return pardirpowerssumfun(NULL, N, s, 0, prec); }
        

Generated by: LCOV version 2.0-1