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 - lfunlarge.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.16.2 lcov report (development 29419-8afb0ed749) Lines: 481 519 92.7 %
Date: 2024-07-02 09:03:41 Functions: 73 75 97.3 %
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             : /*****************************************************************/
      18             : /*             Program to compute L(chi,s)                       */
      19             : /*      for Im(s) large, chi primitive Dirichlet character       */
      20             : /*      In the present branch, only Tyagi's method is used      */
      21             : /*****************************************************************/
      22             : /*
      23             :    In addition, C can also be a polynomial defining an abelian
      24             :    extension of Q.
      25             : */
      26             : 
      27             : /*****************************************************************/
      28             : /*                      Character programs                       */
      29             : /*****************************************************************/
      30             : /* A character, always assumed primitive can be given in the following formats:
      31             :  * - omitted or 0: special to zetaRS,
      32             :  * - a t_INT: assumed to be a discriminant,
      33             :  * - a t_INTMOD: a conrey character,
      34             :  * - a pair [G,chi] or [bnr,chi],
      35             :  * - [C1,C2,...]~ where the Ci are characters as above with same moduli. */
      36             : 
      37             : /* Given a list of linit/ldata for chars of same conductor F, return
      38             :  * [Vecan, F, Parities, Gaussums] */
      39             : static GEN
      40        1085 : mycharinit(GEN C, long bit)
      41             : {
      42             :   GEN L, LVC, LE, LGA;
      43        1085 :   long F = 0, i, j, lc = lg(C), prec;
      44             : 
      45        1085 :   bit += 64; prec = nbits2prec(bit);
      46        1085 :   L = cgetg(lc, t_VEC);
      47        1085 :   LE = cgetg(lc, t_VECSMALL);
      48        1085 :   LGA = cgetg(lc, t_VEC);
      49        2205 :   for (i = 1; i < lc; i++)
      50             :   {
      51        1120 :     GEN gv, ga, gm, ro, ldata = gel(C, i);
      52             :     long e;
      53        1120 :     if (is_linit(ldata)) ldata = linit_get_ldata(ldata);
      54        1120 :     gv = ldata_get_gammavec(ldata); e = itou(gel(gv, 1));
      55        1120 :     gm = ldata_get_conductor(ldata);
      56        1120 :     ro = ldata_get_rootno(ldata);
      57        1120 :     if (isintzero(ro)) ro = lfunrootno(ldata, bit);
      58        1120 :     ga = gmul(ro, gsqrt(gm, prec)); if (e) ga = mulcxI(ga);
      59        1120 :     gel(LGA, i) = ga;
      60        1120 :     LE[i] = e;
      61        1120 :     if (i == 1) F = itos(gm); /* constant */
      62        1120 :     gel(L, i) = lfunan(ldata, F, prec);
      63             :   }
      64        1085 :   if (lc == 2 && is_vec_t(typ(gmael(L,1,1))))
      65             :   { /* multichar */
      66           7 :     LGA = gel(LGA,1); lc = lg(LGA);
      67           7 :     LVC = gel(L,1);
      68           7 :     LE = const_vecsmall(lc-1, LE[1]); /* FIXME: can handle mixed values */
      69             :   }
      70             :   else
      71             :   {
      72        1078 :     LVC = cgetg(F + 1, t_VEC);
      73        4459 :     for (j = 1; j <= F; j++)
      74             :     {
      75        3381 :       GEN v = cgetg(lc, t_VEC);
      76        7049 :       for (i = 1; i < lc; i++) gel(v, i) = gmael(L, i, j);
      77        3381 :       gel(LVC, j) = v;
      78             :     }
      79             :   }
      80        1085 :   return mkvec5(LVC, stoi(F), LE, LGA, grootsof1(2*F, prec));
      81             : }
      82             : 
      83             : /* n >= 1 and #VC = F, the conductor of the character or multicharacter X.
      84             :  * VC contains [X(1),X(2),...X(F)] */
      85             : static GEN
      86      653498 : mycall(GEN VC, long n)
      87             : {
      88      653498 :   long F = lg(VC) - 1;
      89      653498 :   GEN z = n <= F ? gel(VC, n) : gel(VC, ((n - 1) % F) + 1);
      90      653498 :   return gequal0(z)? NULL: z;
      91             : }
      92             : 
      93      198387 : static GEN get_chivec(GEN VCALL) { return gel(VCALL, 1); }
      94      808248 : static long get_modulus(GEN VCALL) { return itos(gel(VCALL, 2)); }
      95      197085 : static GEN get_signat(GEN VCALL) { return gel(VCALL, 3); }
      96          21 : static GEN get_gauss(GEN VCALL) { return gel(VCALL, 4); }
      97      195783 : static GEN get_chiZ(GEN VCALL) { return gel(VCALL, 5); }
      98             : 
      99             : /* (-1)^A[i] * conj(B[i]) */
     100             : static GEN
     101           7 : gnegconj(GEN A, GEN B)
     102             : {
     103           7 :   long i, l = lg(A);
     104           7 :   GEN W = cgetg(l, t_VEC);
     105          14 :   for (i = 1; i < l; i++)
     106           7 :   { GEN b = gconj(gel(B,i)); gel(W,i) = A[i]? gneg(b): b; }
     107           7 :   return W;
     108             : }
     109             : /* g(conj(CHI)) */
     110             : static GEN
     111           7 : gaussconj(GEN VCALL)
     112           7 : { return gnegconj(get_signat(VCALL), get_gauss(VCALL)); }
     113             : 
     114             : static GEN
     115           7 : myinitconj(GEN VCALL)
     116             : {
     117           7 :   GEN CONJ = shallowcopy(VCALL);
     118           7 :   gel(CONJ, 1) = gconj(get_chivec(VCALL));
     119           7 :   gel(CONJ, 4) = gaussconj(VCALL); return CONJ;
     120             : }
     121             : 
     122             : /********************************************************************/
     123             : /*                          Driver Program                          */
     124             : /********************************************************************/
     125             : 
     126             : /* assume |Im(s)| >> 1, in particular s is not a negative integer */
     127             : static GEN
     128          14 : applyfuneq(GEN gau, GEN s, GEN z, long odd, long q, long bitprec)
     129             : {
     130             :   GEN t, S;
     131             :   long prec;
     132          14 :   if (!gequal0(s)) bitprec += maxss(gexpo(s), 0);
     133          14 :   prec = nbits2prec(bitprec);
     134          14 :   if (odd) gau = mulcxmI(gau);
     135          14 :   S = gmul(Pi2n(-1, prec), gsubgs(s, odd));
     136          14 :   t = ginv(gmul2n(gmul(gcos(S, prec), ggamma(s, prec)), 1));
     137          14 :   t = gmul(gpow(gdivgs(Pi2n(1, prec), q), s, prec), t);
     138          14 :   return gmul(gmul(gau, t), z);
     139             : }
     140             : 
     141             : static GEN RZchi(GEN VCALL, GEN s, long prec);
     142             : 
     143             : /* VCALL already initialized */
     144             : static GEN
     145        1085 : lfunlarge_char(GEN VCALL, GEN s, long bitprec)
     146             : {
     147        1085 :   pari_sp av = avma;
     148             :   GEN sig, tau, z;
     149        1085 :   long funeq = 0, ts = typ(s), stau, flconj, q;
     150        1085 :   if (!is_real_t(ts) && ts != t_COMPLEX) pari_err_TYPE("lfunlarge_char", s);
     151        1085 :   sig = real_i(s); tau = imag_i(s);
     152        1085 :   if (gexpo(tau) < 1) pari_err_DOMAIN("lfun","im(s)", "<", gen_2, tau);
     153        1085 :   stau = gsigne(tau);
     154        1085 :   if (stau < 0) { tau = gneg(tau); VCALL = myinitconj(VCALL); }
     155        1085 :   if (gcmp(sig, ghalf) < 0) { funeq = 1; sig = gsubsg(1, sig); }
     156        1085 :   flconj = ((stau > 0 && funeq) || (stau < 0 && !funeq));
     157        1085 :   q = get_modulus(VCALL); bitprec += gexpo(stoi(q));
     158        1085 :   z = RZchi(VCALL, mkcomplex(sig, tau), nbits2prec(bitprec));
     159        1085 :   if (flconj) z = gconj(z);
     160        1085 :   if (funeq)
     161             :   {
     162          14 :     GEN odd = get_signat(VCALL), gau = get_gauss(VCALL), Vz;
     163          14 :     long lC = lg(gau), j;
     164          14 :     Vz = cgetg(lC, t_VEC);
     165          28 :     for (j = 1; j < lC; j++)
     166          14 :       gel(Vz,j) = applyfuneq(gel(gau,j), s, gel(z,j), odd[j], q, bitprec);
     167          14 :     z = Vz;
     168             :   }
     169        1085 :   return gerepilecopy(av, z);
     170             : }
     171             : 
     172             : static GEN
     173          14 : lfungetchars(GEN pol)
     174             : {
     175          14 :   GEN L, F, v, bnf = Buchall(pol_x(1), 0, LOWDEFAULTPREC);
     176             :   GEN w, condall, bnr;
     177             :   long i, l, lc;
     178          14 :   condall = rnfconductor(bnf, pol); bnr = gel(condall, 2);
     179          14 :   L = bnrchar(bnr, gel(condall, 3), NULL); lc = lg(L);
     180          14 :   F = cgetg(lc, t_VEC);
     181          77 :   for (i = 1; i < lc; i++)
     182             :   {
     183          63 :     GEN chi = gel(L, i), cond = bnrconductor_raw(bnr, chi);
     184          63 :     gel(F, i) = gcoeff(gel(cond,1), 1, 1);
     185             :   }
     186          14 :   w = vec_equiv(F); l = lg(w); v = cgetg(l, t_COL);
     187          42 :   for (i = 1; i < l; i++)
     188             :   {
     189          28 :     GEN wi = gel(w, i), vi;
     190          28 :     long j, li = lg(wi);
     191          28 :     gel(v,i) = vi = cgetg(li, t_VEC);
     192          28 :     if (li == 2 && equali1(gel(F, wi[1]))) /* common conductor is 1 */
     193          14 :       gel(vi,1) = lfunmisc_to_ldata_shallow(gen_1);
     194             :     else
     195             :     {
     196          63 :       for (j = 1; j < li; j++)
     197          49 :         gel(vi,j) = lfunmisc_to_ldata_shallow(mkvec2(bnr, gel(L, wi[j])));
     198             :     }
     199             :   }
     200          14 :   return v;
     201             : }
     202             : 
     203             : /********************************************************************/
     204             : /*            NEW RS IMPLEMENTATION FROM SANDEEP TYAGI              */
     205             : /********************************************************************/
     206             : /* See arXiv:2203.02509v2 */
     207             : 
     208        5523 : static long m_n0(GEN sel) { return itos(gel(sel, 1)); }
     209      609399 : static GEN m_r0(GEN sel) { return gel(sel, 2); }
     210        1085 : static GEN m_al(GEN sel) { return gel(sel, 3); }
     211      609399 : static GEN m_aleps(GEN sel) { return gel(sel, 4); }
     212        4396 : static GEN m_h(GEN sel) { return gel(sel, 5); }
     213        1113 : static GEN m_lin(GEN sel) { return gel(sel, 6); }
     214        1113 : static long m_np(GEN sel) { return itou(gel(sel, 7)); }
     215             : 
     216             : static GEN
     217        3297 : phi_hat(GEN x, long prec)
     218             : {
     219             :   GEN y;
     220        3297 :   if (gsigne(imag_i(x)) > 0)
     221        1078 :     y = gneg(gexpm1(gneg(gmul(PiI2(prec), x)), prec));
     222             :   else
     223        2219 :     y = gexpm1(gmul(PiI2(prec), x), prec);
     224        3297 :   return ginv(y);
     225             : }
     226             : 
     227             : static GEN
     228        3241 : phi_hat_h0(GEN sel, long k, long prec)
     229             : {
     230        3241 :   GEN t = gdiv(gsubsg(m_n0(sel) + k, m_r0(sel)), m_aleps(sel));
     231        3241 :   return phi_hat(gdiv(gasinh(t, prec), m_h(sel)), prec);
     232             : }
     233             : 
     234             : /* v[i] = A[i] * (a + (-1)^E[i] b) */
     235             : static GEN
     236      647800 : mul_addsub(GEN A, GEN a, GEN b, GEN E)
     237             : {
     238      647800 :   long i, l = lg(E);
     239      647800 :   GEN v = cgetg(l, t_VEC);
     240     1385720 :   for (i = 1; i < l; i++)
     241      737920 :     gel(v,i) = gmul(gel(A,i), E[i]? gsub(a, b): gadd(a, b));
     242      647800 :   return v;
     243             : }
     244             : 
     245             : static GEN
     246      195783 : wd(GEN VCALL, GEN pmd, GEN x, long prec)
     247             : {
     248      195783 :   GEN VC = get_chivec(VCALL), E = get_signat(VCALL), Z = get_chiZ(VCALL);
     249      195783 :   GEN ex, emx, xpmd = gmul(x, pmd), y = NULL;
     250      195783 :   long md = get_modulus(VCALL), N = 2*md, k;
     251      195783 :   ex = gexp(mulcxI(xpmd), prec); emx = ginv(ex);
     252      843583 :   for (k = 1; k <= (md-1) / 2; k++)
     253             :   {
     254      647800 :     GEN xc = mycall(VC, k);
     255      647800 :     if (xc)
     256             :     {
     257      647800 :       GEN p3, p2, p1 = gmul(xc, gel(Z, Fl_neg(Fl_sqr(k,N), N) + 1));
     258      647800 :       GEN a = gmul(ex, gel(Z, N - k + 1)), b = gmul(emx, gel(Z, k + 1));
     259      647800 :       GEN c = gmul(ex, gel(Z, k + 1)), d = gmul(emx, gel(Z, N - k + 1));
     260      647800 :       if (odd(md))
     261             :       {
     262      629857 :         p2 = ginv(mulcxmI(gmul2n(gsub(a,b), -1))); /* 1 / sin(xpmd - kpmd) */
     263      629857 :         p3 = ginv(mulcxmI(gmul2n(gsub(c,d), -1))); /* 1 / sin(xpmd + kpmd) */
     264             :       }
     265             :       else
     266             :       {
     267       17943 :         p2 = mulcxI(gdiv(gadd(a,b), gsub(a,b))); /* cotan(xpmd - kpmd) */
     268       17943 :         p3 = mulcxI(gdiv(gadd(c,d), gsub(c,d))); /* cotan(xpmd + kpmd) */
     269             :       }
     270      647800 :       p1 = mul_addsub(p1, p2, p3, E);
     271      647800 :       y = y ? gadd(y, p1) : p1;
     272             :     }
     273             :   }
     274      195783 :   return mulcxmI(gdivgs(y, N));
     275             : }
     276             : 
     277             : static GEN
     278        1085 : series_h0(long n0, GEN s, GEN VCALL, long fl, long prec)
     279             : {
     280        1085 :   GEN C = get_modulus(VCALL) == 1? NULL: get_chivec(VCALL);
     281        1085 :   GEN R = pardirpowerssumfun(C, n0, gneg(s), fl, prec);
     282        1085 :   if (C) return R;
     283         686 :   if (fl) return mkvec2(mkvec(gel(R,1)), mkvec(gel(R,2)));
     284         658 :   return mkvec(R);
     285             : }
     286             : 
     287             : static GEN
     288        1113 : series_residues_h0(GEN sel, GEN s, GEN VCALL, long prec)
     289             : {
     290        1113 :   long n0 = m_n0(sel), np = m_np(sel), k;
     291        1113 :   GEN val = gen_0, VC = get_chivec(VCALL);
     292        4424 :   for (k = maxss(1 - np, 1 - n0); k <= 1 + np; k++)
     293             :   {
     294        3311 :     GEN nk = mycall(VC, n0 + k); /* n0 + k > 0 */
     295        3311 :     if (nk) val = gadd(val, gmul(gmul(phi_hat_h0(sel, k, prec), nk),
     296             :                                  gpow(stoi(n0 + k), gneg(s), prec)));
     297             :   }
     298        1113 :   return val;
     299             : }
     300             : 
     301             : static GEN
     302      606158 : integrand_h0(GEN sel, GEN s, GEN VCALL, GEN x, long prec)
     303             : {
     304      606158 :   pari_sp av = avma;
     305      606158 :   long md = get_modulus(VCALL);
     306      606158 :   GEN r0 = m_r0(sel), aleps = m_aleps(sel), zn, p1;
     307      606158 :   GEN pmd = divru(mppi(prec), md), ix = ginv(x);
     308      606158 :   zn = gadd(r0, gdivgs(gmul(aleps, gsub(x, ix)), 2));
     309      606158 :   p1 = gmul(expIxy(pmd, gsqr(zn), prec),
     310             :             gmul(gpow(zn, gneg(s), prec), gmul(aleps, gadd(x, ix))));
     311      606158 :   if (md == 1)
     312      410375 :     p1 = gdiv(mkvec(mulcxI(p1)), gmul2n(gsin(gmul(pmd, zn), prec), 2));
     313             :   else
     314      195783 :     p1 = gdivgs(gmul(p1, wd(VCALL, pmd, zn, prec)), -2);
     315      606158 :   return gerepileupto(av, p1);
     316             : }
     317             : 
     318             : static GEN
     319        1113 : integral_h0(GEN sel, GEN s, GEN VCALL, long prec)
     320             : {
     321        1113 :   GEN lin_grid = m_lin(sel), S = gen_0;
     322        1113 :   pari_sp av = avma;
     323        1113 :   long j, l = lg(lin_grid);
     324      565574 :   for (j = 1; j < l; j++)
     325             :   {
     326      564461 :     S = gadd(S, integrand_h0(sel, s, VCALL, gel(lin_grid, j), prec));
     327      564461 :     if ((j & 0xff) == 0) S = gerepileupto(av, S);
     328             :   }
     329        1113 :   return gerepileupto(av, gmul(m_h(sel), S));
     330             : }
     331             : 
     332             : /* log |x| */
     333             : static GEN
     334       41865 : mylog(GEN x, long prec)
     335             : {
     336       41865 :   if (gequal0(x)) return gneg(powis(stoi(10), 20)); /* FIXME ! */
     337       41795 :   switch(typ(x))
     338             :   {
     339       41795 :     case t_COMPLEX: return gmul2n(glog(cxnorm(x), prec), -1);
     340           0 :     case t_REAL: break;
     341           0 :     default: x = gtofp(x, prec);
     342             :   }
     343           0 :   return logr_abs(x);
     344             : }
     345             : 
     346             : struct fun_q_t { GEN sel, s, VCALL, B; };
     347             : static GEN
     348       41697 : fun_q(void *E, GEN x)
     349             : {
     350       41697 :   struct fun_q_t *S = (struct fun_q_t *)E;
     351       41697 :   long prec = DEFAULTPREC;
     352       41697 :   GEN z = integrand_h0(S->sel, S->s, S->VCALL, gexp(x, prec), prec);
     353       41697 :   if (typ(z) == t_VEC) z = vecsum(z);
     354       41697 :   return addrr(S->B, mylog(z, prec));
     355             : }
     356             : static GEN
     357        2254 : brent_q(void *E, GEN (*f)(void*,GEN), GEN q_low, GEN q_hi)
     358             : {
     359        2254 :   GEN low_val = f(E, q_low), high_val = f(E, q_hi);
     360        2254 :   if (gsigne(low_val) * gsigne(high_val) >= 0) return NULL;
     361        2100 :   return zbrent(E, f, q_low, q_hi, LOWDEFAULTPREC);
     362             : }
     363             : static GEN
     364        1127 : findq(void *E, GEN (*f)(void*,GEN), GEN lq, long B)
     365             : {
     366        1127 :   GEN q_low, q_hi, q_right, q_left, q_est = gasinh(lq, LOWDEFAULTPREC);
     367        1127 :   q_low = gdivgs(gmulsg(4, q_est), 5);
     368        1127 :   q_hi = gdivgs(gmulsg(3, q_est), 2);
     369        1127 :   q_right = brent_q(E, f, q_low, q_hi); if (!q_right) q_right = q_est;
     370        1127 :   q_left = brent_q(E, f, gneg(q_low), gneg(q_hi)); if (!q_left) q_left = q_est;
     371        1127 :   return bitprecision0(gmax(q_right, q_left), B);
     372             : }
     373             : 
     374             : static GEN
     375        1085 : set_q_value(GEN sel, GEN s, GEN VCALL, long prec)
     376             : {
     377             :   struct fun_q_t E;
     378        1085 :   GEN al = m_al(sel), lq;
     379        1085 :   long md = get_modulus(VCALL), LD = DEFAULTPREC;
     380        1085 :   E.sel = sel; E.s = s; E.VCALL = VCALL, E.B = mulur(prec, mplog2(LD));
     381        1085 :   lq = gdiv(gsqrt(gdiv(gmulsg(md, E.B), Pi2n(1, LD)), LD), al);
     382        1085 :   return findq((void*)&E, &fun_q, lq, prec);
     383             : }
     384             : 
     385             : static GEN
     386        1099 : setlin_grid_exp(GEN h, long m, long prec)
     387             : {
     388        1099 :   GEN w, vex = gpowers(gexp(h, prec), (m - 1)/2);
     389             :   long i;
     390        1099 :   w = cgetg(m+1, t_VEC); gel(w, (m + 1)/2) = gen_1;
     391      281121 :   for (i = (m + 3)/2; i <= m; i++)
     392             :   {
     393      280022 :     GEN t1 = gel(vex, i - ((m - 1)/2));
     394      280022 :     gel(w, i) = t1; gel(w, (m + 1) - i) = ginv(t1);
     395             :   }
     396        1099 :   return w;
     397             : }
     398             : 
     399             : static long
     400        1099 : get_m(GEN q, long prec)
     401             : {
     402        1099 :   GEN t = divrr(mulur(4 * prec2nbits(prec), mplog2(prec)), sqrr(mppi(prec)));
     403        1099 :   return 2*itos(gfloor(mulrr(q, t))) + 1;
     404             : }
     405             : 
     406             : static GEN
     407        1085 : RZinit(GEN s, GEN VCALL, GEN numpoles, long prec)
     408             : {
     409             :   GEN sel, al, aleps, n0, r0, q, h;
     410        1085 :   long md = get_modulus(VCALL), m;
     411        1085 :   al = gcmpgs(gabs(imag_i(s), prec), 100) < 0 ? ginv(stoi(4)) : gen_1;
     412        1085 :   r0 = gsqrt(gdiv(gmulgs(s, md), PiI2(prec)), prec);
     413        1085 :   n0 = gfloor(gsub(real_i(r0), imag_i(r0)));
     414        1085 :   aleps = gmul(al, gexp(PiI2n(-2, prec), prec));
     415        1085 :   sel = mkvecn(7, n0, r0, al, aleps, NULL, NULL, numpoles);
     416        1085 :   q = set_q_value(sel, s, VCALL, prec);
     417        1085 :   m = get_m(q, prec);
     418        1085 :   gel(sel,5) = h = divru(q, (m - 1) >> 1);
     419        1085 :   gel(sel,6) = setlin_grid_exp(h, m, prec);
     420        1085 :   return sel;
     421             : }
     422             : 
     423             : static GEN
     424         441 : xpquo_one(GEN s, GEN cs, GEN ga, long odd, long md, long prec)
     425             : {
     426         441 :   GEN rho, a = odd? gen_1: gen_0, z = divsr(md, mppi(prec));
     427         441 :   rho = gmul(gdiv(gpow(gen_I(), gdivgs(gneg(a), 2), prec), gsqrt(ga, prec)),
     428             :              gpow(stoi(md), ginv(stoi(4)), prec));
     429         441 :   return gmul(gdiv(gconj(gmul(rho, gpow(z, gdivgs(cs, 2), prec))),
     430             :                    gmul(rho, gpow(z, gdivgs(s, 2), prec))),
     431             :               gexp(gsub(gconj(glngamma(gdivgs(gadd(cs, a), 2), prec)),
     432             :                         glngamma(gdivgs(gadd(s, a), 2), prec)), prec));
     433             : }
     434             : 
     435             : static GEN
     436        1085 : xpquo(GEN s, GEN VCALL, long prec)
     437             : {
     438        1085 :   long md = get_modulus(VCALL), n, lve, i;
     439        1085 :   GEN cd = NULL, z, pz, cs, VC = get_chivec(VCALL), ve, R;
     440        1085 :   if (!gequal0(s)) prec = nbits2prec(prec2nbits(prec) + maxss(gexpo(s), 0));
     441        1085 :   z = gexp(gdivgs(PiI2(prec), -md), prec);
     442        1085 :   if (md == 1)
     443         686 :     return gmul(gpow(mppi(prec), gsub(s, ghalf), prec),
     444             :                 gexp(gsub(glngamma(gdivgs(gsubsg(1, s), 2), prec),
     445             :                           glngamma(gdivgs(s, 2), prec)), prec));
     446         399 :   pz = gpowers(z, md - 1);
     447        2786 :   for (n = 1; n < md; n++)
     448             :   {
     449        2387 :     GEN xn = mycall(VC, n);
     450        2387 :     if (xn)
     451             :     {
     452        2352 :       GEN tmp = gmul(xn, gel(pz, n + 1));
     453        2352 :       cd = cd ? gadd(cd, tmp) : tmp;
     454             :     }
     455             :   }
     456         399 :   cs = gsubsg(1, gconj(s));
     457         399 :   ve = get_signat(VCALL); lve = lg(ve); R = cgetg(lve, t_VEC);
     458         840 :   for (i = 1; i < lve; i++)
     459         441 :     gel(R, i) = xpquo_one(s, cs, gel(cd, i), ve[i], md, prec);
     460         399 :   if (lve == 2) R = gel(R, 1);
     461         399 :   return R;
     462             : }
     463             : 
     464             : static GEN
     465        1113 : total_value(GEN serh0, GEN sel, GEN s, GEN VCALL, long prec)
     466             : {
     467        1113 :   return gadd(integral_h0(sel, s, VCALL, prec),
     468             :               gsub(serh0, series_residues_h0(sel, s, VCALL, prec)));
     469             : }
     470             : static GEN
     471        1085 : dirichlet_ours(GEN s, GEN VCALL, long prec)
     472             : {
     473        1085 :   int fl = !gequal(real_i(s), ghalf);
     474        1085 :   GEN sel = RZinit(s, VCALL, gen_1, prec);
     475        1085 :   GEN S1, S2, serh0 = series_h0(m_n0(sel), s, VCALL, fl, prec);
     476        1085 :   if (!fl)
     477        1057 :     S2 = S1 = total_value(serh0, sel, s, VCALL, prec);
     478             :   else
     479             :   {
     480          28 :     S1 = total_value(gel(serh0,1), sel, s, VCALL, prec);
     481          28 :     S2 = total_value(gel(serh0,2), sel, gsubsg(1, gconj(s)), VCALL, prec);
     482             :   }
     483        1085 :   return gadd(S1, vecmul(xpquo(s, VCALL, prec), gconj(S2)));
     484             : }
     485             : 
     486             : /* assume |Im(s)| > 2^-bitprec */
     487             : static GEN
     488        1085 : RZchi(GEN VCALL, GEN s, long prec)
     489             : {
     490        1085 :   long prec2 = prec + EXTRAPREC64;
     491        1085 :   return gprec_wtrunc(dirichlet_ours(gprec_w(s, prec2), VCALL, prec2), prec);
     492             : }
     493             : 
     494             : /********************************************************************/
     495             : /*                         Utility Functions                        */
     496             : /********************************************************************/
     497             : /* lam = 0, return L(s); else Lambda(s) */
     498             : static GEN
     499        1085 : lfuncharall(GEN VCALL, GEN s, long lam, long bitprec)
     500             : {
     501        1085 :   GEN ve, P, Q, R, z = lfunlarge_char(VCALL, s, bitprec);
     502             :   long l, i, q, prec;
     503        1085 :   if (!lam) return z;
     504         882 :   ve = get_signat(VCALL); l = lg(ve);
     505         882 :   q = get_modulus(VCALL); prec = nbits2prec(bitprec);
     506         882 :   R = cgetg(l, t_VEC);
     507         882 :   Q = divur(q, mppi(prec));
     508         882 :   P = (q == 1 || zv_equal0(ve))? NULL: gsqrt(utoipos(q), prec);
     509        1764 :   for (i = 1; i < l; i++)
     510             :   {
     511         882 :     GEN se = gmul2n(gaddgs(s, ve[i]), -1), r;
     512         882 :     if (lam == 1)
     513             :     {
     514           0 :       r = gmul(gpow(Q, se, prec), ggamma(se, prec));
     515           0 :       if (P && ve[i]) r = gdiv(r, P);
     516             :     }
     517             :     else
     518             :     {
     519         882 :       r = gadd(gmul(se, glog(Q, prec)), glngamma(se, prec));
     520         882 :       if (P && ve[i]) r = gsub(r, glog(P, prec));
     521             :     }
     522         882 :     gel(R, i) = r;
     523             :   }
     524         882 :   return lam == 1 ? vecmul(R, z) : gadd(R, glog(z, prec));
     525             : }
     526             : 
     527             : static GEN
     528          28 : lfunlargeall_from_chars(GEN v, GEN s, long lam, long bit)
     529             : {
     530          28 :   long i, l = lg(v);
     531          84 :   for (i = 1; i < l; i++)
     532             :   {
     533          56 :     GEN w = mycharinit(gel(v, i), bit), L = lfuncharall(w, s, lam, bit);
     534          56 :     gel(v, i) = lam==-1 ? vecsum(L): vecprod(L);
     535             :   }
     536          28 :   return lam==-1 ? vecsum(v): vecprod(v);
     537             : }
     538             : static GEN
     539        1057 : lfunlargeall(GEN ldata, GEN s, long lam, long bit)
     540             : {
     541             :   GEN w, an;
     542        1057 :   if (lg(ldata) == 2)
     543             :   { /* HACK: ldata[1] a t_DESC_PRODUCT from lfunabelianrelinit / Q */
     544          14 :     GEN v = lfunprod_get_fact(linit_get_tech(gel(ldata,1)));
     545             :     long i, l;
     546          14 :     v = shallowcopy(gel(v,1)); l = lg(v);
     547          42 :     for (i = 1; i < l; i++) gel(v,i) = mkvec(gel(v,i));
     548          14 :     return lfunlargeall_from_chars(v, s, lam, bit);
     549             :   }
     550        1043 :   an = gel(ldata_get_an(ldata), 2);
     551        1043 :   switch(ldata_get_type(ldata))
     552             :   {
     553          14 :     case t_LFUN_NF:
     554             :     {
     555          14 :       GEN v = lfungetchars(nf_get_pol(an));
     556          14 :       return lfunlargeall_from_chars(v, s, lam, bit);
     557             :     }
     558           7 :     case t_LFUN_CHIGEN:
     559             :     {
     560           7 :       GEN chi = gmael(an, 2, 2);
     561           7 :       if (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))))
     562             :       { /* multi char */
     563           7 :         w = mycharinit(mkcol(ldata), bit);
     564           7 :         return lfuncharall(w, s, lam, bit);
     565             :       }
     566             :     }
     567             :     default: /* single char */
     568        1022 :       w = mycharinit(mkcol(ldata), bit);
     569        1022 :       return gel(lfuncharall(w, s, lam, bit), 1);
     570             :   }
     571             : }
     572             : 
     573             : GEN
     574         189 : lfunlarge(GEN CHI, GEN s, long bit)
     575         189 : { return lfunlargeall(CHI, s, 0, bit); }
     576             : 
     577             : GEN
     578           0 : lfunlambdalarge(GEN CHI, GEN s, long bit)
     579           0 : { return lfunlargeall(CHI, s, 1, bit); }
     580             : 
     581             : GEN
     582         868 : lfunloglambdalarge(GEN CHI, GEN s, long bit)
     583         868 : { return lfunlargeall(CHI, s, -1, bit); }
     584             : 
     585             : /********************************************************************/
     586             : /*           LERCH RS IMPLEMENTATION FROM SANDEEP TYAGI             */
     587             : /********************************************************************/
     588             : 
     589             : static GEN
     590          56 : double_exp_residue_pos_h(GEN selsm, long k, long ind, long prec)
     591             : {
     592          56 :   long nk = itos(gel(selsm, 1)) + k;
     593          56 :   GEN r = gel(selsm, 2), ale = gel(selsm, 3), aor = gel(selsm, 4);
     594          56 :   GEN h = gel(selsm, 5), t = gen_0;
     595          56 :   switch(ind)
     596             :   {
     597          28 :     case 0: t = gaddsg(nk, aor); break;
     598           0 :     case 1: t = gneg(gaddsg(nk, aor)); break;
     599          28 :     case 2: t = gsubsg(nk, aor); break;
     600             :   }
     601          56 :   return gdiv(gasinh(gdiv(gsub(t, r), ale), prec), h);
     602             : }
     603             : 
     604             : static GEN
     605          56 : phi_hat_h(GEN selsm, long m, long ind, long prec)
     606          56 : { return phi_hat(double_exp_residue_pos_h(selsm, m, ind, prec), prec); }
     607             : 
     608             : static long
     609          56 : myex(GEN is)
     610          56 : { return gequal0(is) ? 0 : maxss(0, 2 + gexpo(is)); }
     611             : 
     612             : static GEN
     613          56 : gaminus(GEN s, long prec)
     614             : {
     615          56 :   GEN is = imag_i(s), tmp;
     616          56 :   long B = prec2nbits(prec);
     617          56 :   if (gcmpgs(is, -5*B) < 0) return gen_0;
     618          56 :   prec = nbits2prec(B + myex(is));
     619          56 :   tmp = gexp(gsub(glngamma(s, prec), gmul(PiI2n(-1, prec), s)), prec);
     620          56 :   return bitprecision0(tmp, B);
     621             : }
     622             : 
     623             : static GEN
     624          28 : gaplus(GEN s, long prec)
     625             : {
     626          28 :   GEN is = imag_i(s), tmp;
     627          28 :   long B = prec2nbits(prec);
     628          28 :   if (gcmpgs(is, 5*B) > 0) return gen_0;
     629           0 :   prec = nbits2prec(B + myex(is));
     630           0 :   tmp = gexp(gadd(glngamma(s, prec), gmul(PiI2n(-1, prec), s)), prec);
     631           0 :   return bitprecision0(tmp, B);
     632             : }
     633             : 
     634             : GEN
     635        3514 : serh_worker(GEN k, GEN z, GEN a, GEN ns, GEN gprec)
     636             : {
     637        3514 :   long prec = itou(gprec);
     638        3514 :   return gmul(gpow(z, k, prec), gpow(gadd(a, k), ns, prec));
     639             : }
     640             : 
     641             : static void
     642          28 : set_arg(GEN worker, GEN z, GEN a, GEN ns, long prec)
     643          28 : { gel(worker, 7) = mkvec4(z, a, ns, stoi(prec)); }
     644             : 
     645             : 
     646             : static GEN
     647          14 : series_h0l(GEN worker, long n0, GEN s, GEN a, GEN lam, long prec)
     648             : {
     649          14 :   GEN z = typ(lam) == t_INT ? gen_1 : gexp(gmul(PiI2(prec), lam), prec);
     650          14 :   set_arg(worker, z, a, gneg(s), prec);
     651          14 :   return parsum(gen_0, utoi(n0), worker);
     652             : }
     653             : 
     654             : static GEN
     655          14 : series_h1(GEN worker, long n1, GEN s, GEN a, GEN lam, long prec)
     656             : {
     657          14 :   GEN mP, pre_factor, z, sn = gsubgs(s, 1);
     658          14 :   GEN ini = gequal0(lam) ? gen_1 : gen_0;
     659          14 :   pre_factor = gaplus(gneg(sn), prec);
     660          14 :   if (gequal0(pre_factor)) return gen_0;
     661           0 :   mP = gneg(PiI2(prec));
     662           0 :   pre_factor = gmul(gmul(pre_factor, gexp(gmul(mP, gmul(a, lam)), prec)),
     663             :                     gpow(Pi2n(1, prec), sn, prec));
     664           0 :   z = typ(a) == t_INT ? gen_1 : gexp(gmul(mP, a), prec);
     665           0 :   set_arg(worker, z, lam, sn, prec);
     666           0 :   return gmul(pre_factor,  parsum(ini, stoi(n1 - 1), worker));
     667             : }
     668             : 
     669             : static GEN
     670          14 : series_h2(GEN worker, long n2, GEN s, GEN a, GEN lam, long prec)
     671             : {
     672          14 :   GEN P, pre_factor, z, sn = gsubgs(s, 1);
     673          14 :   pre_factor = gaminus(gneg(sn), prec);
     674          14 :   if (gequal0(pre_factor)) return gen_0;
     675          14 :   P = PiI2(prec);
     676          14 :   pre_factor = gmul(gmul(pre_factor, gexp(gmul(gneg(P), gmul(a, lam)), prec)),
     677             :                     gpow(Pi2n(1, prec), sn, prec));
     678          14 :   z = typ(a) == t_INT ? gen_1 : gexp(gmul(P, a), prec);
     679          14 :   set_arg(worker, z, gneg(lam), sn, prec);
     680          14 :   return gmul(pre_factor, parsum(gen_1, stoi(n2), worker));
     681             : }
     682             : 
     683             : static GEN
     684          14 : series_residues_h0l(long numpoles, GEN selsm0, GEN s, GEN a, GEN lam, long prec)
     685             : {
     686          14 :   GEN P, val = gen_0, ra = real_i(a);
     687          14 :   long n0 = m_n0(selsm0), k;
     688          14 :   P = PiI2(prec);
     689          42 :   for (k = -numpoles + 1; k <= numpoles; k++)
     690          28 :     if (gsigne(gaddsg(n0 + k, ra)) > 0)
     691          28 :       val = gadd(val, gmul(gmul(phi_hat_h(selsm0, k, 0, prec),
     692             :                                 gexp(gmul(P, gmulgs(lam, n0 + k)), prec)),
     693             :                            gpow(gaddsg(n0 + k, a), gneg(s), prec)));
     694          14 :   return val;
     695             : }
     696             : 
     697             : static GEN
     698          14 : series_residues_h1(long numpoles, GEN selsm1, GEN s, GEN a, GEN lam, long prec)
     699             : {
     700          14 :   GEN mP, val = gen_0, rlam = real_i(lam), pre_factor, sn = gsubgs(s, 1);
     701          14 :   long n1 = m_n0(selsm1), k;
     702          14 :   pre_factor = gaplus(gneg(sn), prec);
     703          14 :   if (gequal0(pre_factor)) return gen_0;
     704           0 :   mP = gneg(PiI2(prec));
     705           0 :   pre_factor = gmul(gmul(pre_factor, gexp(gmul(mP, gmul(a, lam)), prec)),
     706             :                     gpow(Pi2n(1, prec), sn, prec));
     707           0 :   for (k = -numpoles; k <= numpoles - 1; k++)
     708           0 :     if (gsigne(gaddsg(n1 + k, rlam)) > 0)
     709           0 :       val = gadd(val, gmul(gmul(phi_hat_h(selsm1, k, 1, prec),
     710             :                                 gexp(gmul(mP, gmulgs(a, n1 + k)), prec)),
     711             :                            gpow(gaddsg(n1 + k, lam), sn, prec)));
     712           0 :   return gmul(pre_factor, val);
     713             : }
     714             : 
     715             : static GEN
     716          14 : series_residues_h2(long numpoles, GEN selsm2, GEN s, GEN a, GEN lam, long prec)
     717             : {
     718          14 :   GEN P, val = gen_0, rlam = real_i(lam), pre_factor, sn = gsubgs(s, 1);
     719          14 :   long n2 = m_n0(selsm2), k;
     720          14 :   pre_factor = gaminus(gneg(sn), prec);
     721          14 :   if (gequal0(pre_factor)) return gen_0;
     722          14 :   P = PiI2(prec);
     723          14 :   pre_factor = gmul(gmul(pre_factor, gexp(gmul(gneg(P), gmul(a, lam)), prec)),
     724             :                     gpow(Pi2n(1, prec), sn, prec));
     725          42 :   for (k = -numpoles + 1; k <= numpoles; k++)
     726          28 :     if (gsigne(gsubsg(n2 + k, rlam)) > 0)
     727          28 :       val = gsub(val, gmul(gmul(phi_hat_h(selsm2, k, 2, prec),
     728             :                                 gexp(gmul(P, gmulgs(a, n2 + k)), prec)),
     729             :                            gpow(gsubsg(n2 + k, lam), sn, prec)));
     730          14 :   return gmul(pre_factor, val);
     731             : }
     732             : 
     733             : static GEN
     734        3430 : integrand_h0l(GEN selsm0, GEN s, GEN alam1, GEN x, long prec)
     735             : {
     736        3430 :   GEN r0 = gel(selsm0, 2), ale = gel(selsm0, 3), a = gel(selsm0, 4);
     737        3430 :   GEN ix = ginv(x), zn = gadd(r0, gmul2n(gmul(ale, gsub(x, ix)), -1));
     738        3430 :   GEN P = PiI2n(0, prec), den, num;
     739        3430 :   den = gexpm1(gmul(P, gmul2n(gsub(zn,a), 1)), prec);
     740        3430 :   num = gexp(gmul(gmul(P, zn), gsub(alam1, zn)), prec);
     741        3430 :   num = gmul(gmul(gmul(num, ale), gmul2n(gadd(x, ix), -1)),
     742             :              gpow(zn, gneg(s), prec));
     743        3430 :   return gdiv(num, den);
     744             : }
     745             : 
     746             : static GEN
     747        6860 : integrand_h12(GEN selsm1, GEN s, GEN alam1, GEN x, long prec)
     748             : {
     749        6860 :   GEN r1 = gel(selsm1, 2), ale = gel(selsm1, 3), lam = gel(selsm1, 4);
     750        6860 :   GEN ix = ginv(x), zn = gadd(r1, gmul2n(gmul(ale, gsub(x, ix)), -1));
     751        6860 :   GEN P = PiI2n(0, prec), den, num, y;
     752        6860 :   den = gexpm1(gmul(P, gmul2n(gadd(zn,lam), 1)), prec);
     753        6860 :   num = gexp(gmul(gmul(P, zn), gadd(alam1, zn)), prec);
     754        6860 :   num = gmul(gmul(gmul(num, ale), gmul2n(gadd(x, ix), -1)),
     755             :              gpow(zn, gsubgs(s, 1), prec));
     756        6860 :   y = gdiv(num, den);
     757        6860 :   if (gcmp(garg(zn, prec), Pi2n(-2, prec)) > 0)
     758        1722 :     y = gmul(y, gexp(gmul(PiI2(prec), gsubsg(1, s)), prec));
     759        6860 :   return y;
     760             : }
     761             : 
     762             : static GEN
     763          14 : integral_h0l(GEN lin_grid, GEN selsm0, GEN s, GEN a, GEN lam, long prec)
     764             : {
     765          14 :   GEN A = gaddgs(gmul2n(gadd(a, lam),1), 1), S = gen_0;
     766          14 :   pari_sp av = avma;
     767          14 :   long j, l = lg(lin_grid);
     768             : 
     769        3388 :   for (j = 1; j < l; j++)
     770             :   {
     771        3374 :     S = gadd(S, integrand_h0l(selsm0, s, A, gel(lin_grid, j), prec));
     772        3374 :     if ((j & 0xff) == 0) S = gerepileupto(av, S);
     773             :   }
     774          14 :   S = gmul(m_h(selsm0), S);
     775          14 :   A = gmul(a, gaddsg(1, gadd(a, gmul2n(lam, 1))));
     776          14 :   return gmul(S, gexp(gneg(gmul(PiI2n(0, prec), A)), prec));
     777             : }
     778             : 
     779             : /* do not forget a minus sign for index 2 */
     780             : static GEN
     781          28 : integral_h12(GEN lin_grid, GEN selsm1, GEN s, GEN a, GEN lam, long prec)
     782             : {
     783          28 :   GEN A, E, S = gen_0, ga = gaminus(gsubsg(1, s), prec);
     784          28 :   pari_sp av = avma;
     785          28 :   long j, l = lg(lin_grid);
     786             : 
     787          28 :   if (gequal0(ga)) return S;
     788          28 :   A = gaddgs(gmul2n(gadd(a,lam), 1), 1);
     789        6776 :   for (j = 1; j < l; j++)
     790             :   {
     791        6748 :     S = gadd(S, integrand_h12(selsm1, s, A, gel(lin_grid, j), prec));
     792        6748 :     if ((j & 0xff) == 0) S = gerepileupto(av, S);
     793             :   }
     794          28 :   if (gequal0(S)) return gen_0;
     795          28 :   S = gmul(m_h(selsm1), S);
     796          28 :   E = gexp(gmul(PiI2n(0, prec), gmul(lam, gaddgs(lam, 1))), prec);
     797          28 :   return gmul(gmul(gmul(S, ga), E), gpow(Pi2n(1, prec), gsubgs(s, 1), prec));
     798             : }
     799             : 
     800             : struct _fun_q0_t { GEN sel, s, alam1, B; };
     801             : static GEN
     802          56 : _fun_q0(void *E, GEN x)
     803             : {
     804          56 :   struct _fun_q0_t *S = (struct _fun_q0_t*)E;
     805          56 :   GEN z = integrand_h0l(S->sel, S->s, S->alam1, x, DEFAULTPREC);
     806          56 :   return addrr(S->B, mylog(z, DEFAULTPREC));
     807             : }
     808             : static GEN
     809         112 : _fun_q12(void *E, GEN x)
     810             : {
     811         112 :   struct _fun_q0_t *S = (struct _fun_q0_t*)E;
     812         112 :   GEN z = integrand_h12(S->sel, S->s, S->alam1, x, DEFAULTPREC);
     813         112 :   return addrr(S->B, mylog(z, DEFAULTPREC));
     814             : }
     815             : 
     816             : static GEN
     817          14 : RZLERinit(GEN s, GEN a, GEN lam, GEN al, GEN numpoles, long prec)
     818             : {
     819             :   GEN eps, r0, r1, r2, h, lin_grid, q, q0, q1, q2, sel0, sel1, sel2, lq;
     820          14 :   GEN pinv = ginv(PiI2(prec)), c = gmul2n(gadd(a, lam), -1), n0, n1, n2, c2;
     821             :   long m;
     822             :   struct _fun_q0_t E;
     823             : 
     824          14 :   if (!al || gequal0(al))
     825           0 :     al = gcmpgs(gabs(imag_i(s), prec), 100) < 0 ? ginv(stoi(4)) : gen_1;
     826          14 :   c2 = gsub(gsqr(c), gmul(s, pinv));
     827          14 :   r0 = gadd(c, gsqrt(c2, prec));
     828          14 :   r1 = gsqrt(gadd(c2, pinv), prec);
     829          14 :   r2 = gsub(r1, c);
     830          14 :   r1 = gneg(gadd(r1, c));
     831          14 :   n0 = gfloor(gsub(gadd(real_i(r0), imag_i(r0)), a));
     832          14 :   n1 = gneg(gfloor(gadd(gsub(real_i(r1), imag_i(r1)), real_i(lam))));
     833          14 :   n2 = gfloor(gadd(gsub(real_i(r2), imag_i(r2)), real_i(lam)));
     834             : 
     835          14 :   E.s = s; E.alam1 = gaddgs(gmul2n(gadd(a, lam), 1), 1);
     836          14 :   E.B = mulur(prec, mplog2(prec));
     837          14 :   lq = gmul(al, sqrtr_abs(mulrr(divsr(prec, Pi2n(1, DEFAULTPREC)),
     838             :                                 mplog2(DEFAULTPREC))));
     839          14 :   eps = gexp(PiI2n(-2, prec), prec);
     840          14 :   E.sel = sel0 = mkvec5(n0, r0, gdiv(al, eps), a, gen_0);
     841          14 :   q0 = findq(&E, &_fun_q0, lq, prec);
     842             : 
     843          14 :   if (!gequal1(al)) lq = gdiv(lq, gsqr(al));
     844          14 :   E.sel = sel1 = mkvec5(n1, r1, gmul(al, eps), lam, gen_0);
     845          14 :   q1 = findq(&E, &_fun_q12, lq, prec);
     846          14 :   E.sel = sel2 = mkvec5(n2, r2, gmul(al, eps), lam, gen_0);
     847          14 :   q2 = findq(&E, &_fun_q12, lq, prec);
     848          14 :   q = vecmax(mkvec3(q0, q1, q2)); m = get_m(q, prec);
     849          14 :   gel(sel0, 5) = gel(sel1, 5) = gel(sel2, 5) = h = divru(q, (m-1) >> 1);
     850          14 :   lin_grid = setlin_grid_exp(h, m, prec);
     851          14 :   if (!numpoles) numpoles = gen_1;
     852          14 :   return mkvec5(sel0, sel1, sel2, lin_grid, numpoles);
     853             : }
     854             : 
     855          42 : static GEN add3(GEN x, GEN y, GEN z) { return gadd(x, gadd(y,z)); }
     856          14 : static GEN addsub(GEN x, GEN y, GEN z) { return gadd(x, gsub(y,z)); }
     857             : 
     858             : static GEN
     859          14 : lerch_ours(GEN sel, GEN s, GEN a, GEN lam, long prec)
     860             : {
     861          14 :   GEN selsm0 = gel(sel, 1), selsm1 = gel(sel, 2), selsm2 = gel(sel, 3);
     862          14 :   GEN lin_grid = gel(sel, 4), v0, v1, v2;
     863          14 :   long numpoles = itos(gel(sel, 5));
     864          14 :   GEN worker = snm_closure(is_entry("_serh_worker"),
     865             :                            mkvec4(NULL, NULL, NULL, NULL));
     866          14 :   v0 = add3(series_h0l(worker, m_n0(selsm0), s, a, lam, prec),
     867             :             series_residues_h0l(numpoles, selsm0, s, a, lam, prec),
     868             :             integral_h0l(lin_grid, selsm0, s, a, lam, prec));
     869          14 :   v1 = add3(series_h1(worker, m_n0(selsm1), s, a, lam, prec),
     870             :             series_residues_h1(numpoles, selsm1, s, a, lam, prec),
     871             :             integral_h12(lin_grid, selsm1, s, a, lam, prec));
     872          14 :   v2 = addsub(series_h2(worker, m_n0(selsm2), s, a, lam, prec),
     873             :             series_residues_h2(numpoles, selsm2, s, a, lam, prec),
     874             :             integral_h12(lin_grid, selsm2, s, a, lam, prec));
     875          14 :   return add3(v0, v1, v2);
     876             : }
     877             : 
     878             : static GEN
     879           0 : RZlerch_easy(GEN s, GEN a, GEN lam, long prec)
     880             : {
     881           0 :   pari_sp av = avma;
     882             :   GEN z, y, N;
     883           0 :   long B = prec2nbits(prec), LD = LOWDEFAULTPREC;
     884           0 :   N = gdiv(gmulsg(B + 5, mplog2(LD)), gmul(Pi2n(1, LD), imag_i(lam)));
     885           0 :   if (gexpo(N) > 40) pari_err_IMPL("precision too large in lerchzeta");
     886           0 :   N = gceil(N); prec += EXTRAPREC64;
     887           0 :   z = typ(lam) == t_INT ? gen_1 : gexp(gmul(PiI2(prec), lam), prec);
     888           0 :   y = parsum(gen_0, N, snm_closure(is_entry("_serh_worker"),
     889             :                                    mkvec4(z, a, gneg(s), stoi(prec))));
     890           0 :   return gerepilecopy(av, gprec_wtrunc(y, prec));
     891             : }
     892             : 
     893             : static GEN
     894          14 : mygfrac(GEN z)
     895           0 : { return typ(z) == t_COMPLEX ? mkcomplex(gfrac(real_i(z)), imag_i(z))
     896          14 :                              : gfrac(z); }
     897             : 
     898             : static GEN
     899          42 : lerchlarge(GEN s, GEN a, GEN lam, GEN al, GEN numpoles, long prec)
     900             : {
     901          42 :   pari_sp av = avma;
     902          42 :   GEN val, sel, imlam = imag_i(lam);
     903             :   long prec2;
     904          42 :   switch(gsigne(imlam))
     905             :   {
     906           0 :     case -1: pari_err_IMPL("imag(lam) < 0");
     907           0 :     case  1: if (gexpo(imlam) >= -16) return RZlerch_easy(s, a, lam, prec);
     908             :   }
     909          42 :   if (gcmpgs(real_i(a), 1) < 0)
     910             :   {
     911          14 :     GEN P = gexp(gmul(PiI2(prec), lam), prec);
     912          14 :     GEN L = lerchlarge(s, gaddgs(a, 1), lam, al, numpoles, prec);
     913          14 :     return gerepileupto(av, gadd(gpow(a, gneg(s), prec), gmul(P, L)));
     914             :   }
     915          28 :   if (gcmpgs(real_i(a), 2) >= 0)
     916             :   {
     917           0 :     GEN L, P = gexp(gneg(gmul(PiI2(prec), lam)), prec);
     918           0 :     a = gsubgs(a, 1); L = lerchlarge(s, a, lam, al, numpoles, prec);
     919           0 :     return gerepileupto(av, gmul(P, gsub(L, gpow(a, gneg(s), prec))));
     920             :   }
     921          28 :   if (gsigne(imag_i(s)) > 0)
     922             :   {
     923             :     GEN L;
     924          14 :     lam = mygfrac(gneg(gconj(lam)));
     925          14 :     L = lerchlarge(gconj(s), a, lam, al, numpoles, prec);
     926          14 :     return gerepileupto(av, gconj(L));
     927             :   }
     928          14 :   prec2 = prec + EXTRAPREC64;
     929          14 :   a = gprec_w(a, prec2);
     930          14 :   s = gprec_w(s, prec2);
     931          14 :   lam = gprec_w(lam, prec2);
     932          14 :   sel = RZLERinit(s, a, lam, al, numpoles, prec2);
     933          14 :   val = lerch_ours(sel, s, a, lam, prec2);
     934          14 :   return gerepilecopy(av, gprec_wtrunc(val, prec));
     935             : }
     936             : 
     937             : GEN
     938           7 : zetahurwitzlarge(GEN s, GEN a, long prec)
     939           7 : { return lerchlarge(s, a, gen_0, gen_1, gen_1, prec); }
     940             : 
     941             : GEN
     942           7 : lerchzetalarge(GEN s, GEN a, GEN lam, long prec)
     943           7 : { return lerchlarge(s, a, lam, gen_1, gen_1, prec); }

Generated by: LCOV version 1.16