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 - lfunutils.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31041-bd73e9fcdd) Lines: 91.7 % 1740 1596
Test Date: 2026-07-22 22:45:42 Functions: 94.2 % 172 162
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              : /**                 L-functions: Applications                      **/
      18              : /**                                                                **/
      19              : /********************************************************************/
      20              : 
      21              : #include "pari.h"
      22              : #include "paripriv.h"
      23              : 
      24              : #define DEBUGLEVEL DEBUGLEVEL_lfun
      25              : 
      26              : static GEN
      27        27104 : tag(GEN x, long t) { return mkvec2(mkvecsmall(t), x); }
      28              : 
      29              : /* v a t_VEC of length > 1 */
      30              : static int
      31       109437 : is_tagged(GEN v)
      32              : {
      33       109437 :   GEN T = gel(v,1);
      34       109437 :   return (typ(T)==t_VEC && lg(T)==3 && typ(gel(T,1))==t_VECSMALL);
      35              : }
      36              : /* rough check */
      37              : static long
      38       131594 : is_ldata(GEN L)
      39              : {
      40       131594 :   long l = lg(L);
      41       131594 :   return typ(L) == t_VEC && (l == 7 || l == 8);
      42              : }
      43              : /* thorough check */
      44              : static void
      45       109143 : checkldata(GEN ldata)
      46              : {
      47              :   GEN vga, w, N;
      48              : #if 0 /* assumed already checked and true */
      49              :   if (!is_ldata(ldata) || !is_tagged(ldata)) pari_err_TYPE("checkldata", ldata);
      50              : #endif
      51       109143 :   vga = ldata_get_gammavec(ldata);
      52       109143 :   if (typ(vga) != t_VEC) pari_err_TYPE("checkldata [gammavec]",vga);
      53       109143 :   w = gel(ldata, 4); /* FIXME */
      54       109143 :   switch(typ(w))
      55              :   {
      56       106476 :     case t_INT: case t_FRAC: case t_REAL: break;
      57         2667 :     case t_VEC: if (lg(w) == 3 && is_real_t(typ(gel(w,1)))) break;
      58            0 :     default: pari_err_TYPE("checkldata [weight]",w);
      59              :   }
      60       109143 :   N = ldata_get_conductor(ldata);
      61       109143 :   if (gsigne(N) <= 0) pari_err_TYPE("checkldata [conductor]",N);
      62       109143 : }
      63              : 
      64              : /* tag as t_LFUN_GENERIC */
      65              : static void
      66          770 : lfuncreate_tag(GEN L)
      67              : {
      68          770 :   if (is_tagged(L)) return;
      69          469 :   gel(L,1) = tag(gel(L,1), t_LFUN_GENERIC);
      70          469 :   if (typ(gel(L,2)) != t_INT) gel(L,2) = tag(gel(L,2), t_LFUN_GENERIC);
      71              : }
      72              : 
      73              : /* shallow */
      74              : static GEN
      75          421 : closure2ldata(GEN C, long prec)
      76              : {
      77          421 :   GEN L = closure_callgen0prec(C, prec);
      78          421 :   if (is_ldata(L)) { checkldata(L); lfuncreate_tag(L); }
      79          169 :   else L = lfunmisc_to_ldata_shallow(L);
      80          421 :   return L;
      81              : }
      82              : 
      83              : /* data may be either an object (polynomial, elliptic curve, etc...)
      84              :  * or a description vector [an,sd,Vga,k,conductor,rootno,{poles}]. */
      85              : GEN
      86         4074 : lfuncreate(GEN data)
      87              : {
      88         4074 :   if (is_ldata(data))
      89              :   {
      90          518 :     GEN L = gcopy(data);
      91          518 :     lfuncreate_tag(L); checkldata(L); return L;
      92              :   }
      93         3556 :   if (typ(data) == t_CLOSURE && closure_arity(data)==0)
      94              :   {
      95           35 :     pari_sp av = avma;
      96           35 :     GEN L = closure2ldata(data, DEFAULTPREC);
      97           35 :     gel(L,1) = tag(data, t_LFUN_CLOSURE0); return gc_GEN(av, L);
      98              :   }
      99         3521 :   return lfunmisc_to_ldata(data);
     100              : }
     101              : 
     102              : GEN
     103          469 : lfunparams(GEN L, long prec)
     104              : {
     105          469 :   pari_sp av = avma;
     106              :   GEN k, N, v;
     107              :   long p;
     108              : 
     109          469 :   if (!is_ldata(L) || !is_tagged(L)) L = lfunmisc_to_ldata_shallow(L);
     110          469 :   N = ldata_get_conductor(L);
     111          469 :   k = ldata_get_k(L);
     112          469 :   v = ldata_get_gammavec(L);
     113          469 :   p = gprecision(v);
     114          469 :   if (p > prec) v = gprec_wtrunc(v, prec);
     115          469 :   else if (p < prec)
     116              :   {
     117          463 :     GEN van = ldata_get_an(L), an = gel(van,2);
     118          463 :     long t = mael(van,1,1);
     119          463 :     if (t == t_LFUN_CLOSURE0) L = closure2ldata(an, prec);
     120              :   }
     121          469 :   return gc_GEN(av, mkvec3(N, k, v));
     122              : }
     123              : 
     124              : /********************************************************************/
     125              : /**                     Simple constructors                        **/
     126              : /********************************************************************/
     127              : static GEN ldata_eulerf(GEN van, GEN p, long prec);
     128              : 
     129              : static GEN
     130          154 : vecan_conj(GEN an, long n, long prec)
     131              : {
     132          154 :   GEN p1 = ldata_vecan(gel(an,1), n, prec);
     133          154 :   return typ(p1) == t_VEC? conj_i(p1): p1;
     134              : }
     135              : 
     136              : static GEN
     137            0 : eulerf_conj(GEN an, GEN p, long prec)
     138              : {
     139            0 :   GEN p1 = ldata_eulerf(gel(an,1), p, prec);
     140            0 :   return conj_i(p1);
     141              : }
     142              : 
     143              : static GEN
     144          413 : vecan_mul(GEN an, long n, long prec)
     145              : {
     146          413 :   GEN p1 = ldata_vecan(gel(an,1), n, prec);
     147          413 :   GEN p2 = ldata_vecan(gel(an,2), n, prec);
     148          413 :   if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1);
     149          413 :   if (typ(p2) == t_VECSMALL) p2 = vecsmall_to_vec(p2);
     150          413 :   return dirmul(p1, p2);
     151              : }
     152              : 
     153              : static GEN
     154           42 : eulerf_mul(GEN an, GEN p, long prec)
     155              : {
     156           42 :   GEN p1 = ldata_eulerf(gel(an,1), p, prec);
     157           42 :   GEN p2 = ldata_eulerf(gel(an,2), p, prec);
     158           42 :   return gmul(p1, p2);
     159              : }
     160              : 
     161              : static GEN
     162           84 : lfunconvol(GEN a1, GEN a2)
     163           84 : { return tag(mkvec2(a1, a2), t_LFUN_MUL); }
     164              : 
     165              : static GEN
     166          630 : vecan_div(GEN an, long n, long prec)
     167              : {
     168          630 :   GEN p1 = ldata_vecan(gel(an,1), n, prec);
     169          630 :   GEN p2 = ldata_vecan(gel(an,2), n, prec);
     170          630 :   if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1);
     171          630 :   if (typ(p2) == t_VECSMALL) p2 = vecsmall_to_vec(p2);
     172          630 :   return dirdiv(p1, p2);
     173              : }
     174              : 
     175              : static GEN
     176           14 : eulerf_div(GEN an, GEN p, long prec)
     177              : {
     178           14 :   GEN p1 = ldata_eulerf(gel(an,1), p, prec);
     179           14 :   GEN p2 = ldata_eulerf(gel(an,2), p, prec);
     180           14 :   return gdiv(p1, p2);
     181              : }
     182              : 
     183              : static GEN
     184           56 : lfunconvolinv(GEN a1, GEN a2)
     185           56 : { return tag(mkvec2(a1,a2), t_LFUN_DIV); }
     186              : 
     187              : static GEN
     188           98 : lfunconj(GEN a1)
     189           98 : { return tag(mkvec(a1), t_LFUN_CONJ); }
     190              : 
     191              : static GEN
     192          140 : lfuncombdual(GEN (*fun)(GEN, GEN), GEN ldata1, GEN ldata2)
     193              : {
     194          140 :   GEN a1 = ldata_get_an(ldata1), a2 = ldata_get_an(ldata2);
     195          140 :   GEN b1 = ldata_get_dual(ldata1), b2 = ldata_get_dual(ldata2);
     196          140 :   if (typ(b1)==t_INT && typ(b2)==t_INT)
     197          140 :     return utoi(signe(b1) || signe(b2));
     198              :   else
     199              :   {
     200            0 :     if (typ(b1)==t_INT) b1 = signe(b1) ? lfunconj(a1): a1;
     201            0 :     if (typ(b2)==t_INT) b2 = signe(b2) ? lfunconj(a2): a2;
     202            0 :     return fun(b1, b2);
     203              :   }
     204              : }
     205              : 
     206              : static GEN
     207         2884 : vecan_twist(GEN an, long n, long prec)
     208              : {
     209         2884 :   GEN p1 = ldata_vecan(gel(an,1), n, prec);
     210         2884 :   GEN p2 = ldata_vecan(gel(an,2), n, prec);
     211              :   long i;
     212              :   GEN V;
     213         2884 :   if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1);
     214         2884 :   if (typ(p2) == t_VECSMALL) p2 = vecsmall_to_vec(p2);
     215         2884 :   V = cgetg(n+1, t_VEC);
     216      1425767 :   for(i = 1; i <= n ; i++)
     217      1422883 :     gel(V, i) = gmul(gel(p1, i), gel(p2, i));
     218         2884 :   return V;
     219              : }
     220              : 
     221              : static GEN
     222           14 : eulerf_twist(GEN an, GEN p, long prec)
     223              : {
     224           14 :   GEN p1 = ldata_eulerf(gel(an,1), p, prec);
     225           14 :   GEN p2 = ginv(ldata_eulerf(gel(an,2), p, prec));
     226           14 :   if (typ(p2)!=t_POL || degpol(p2)==0)
     227            0 :     return poleval(p1,pol_0(0));
     228           14 :   if (degpol(p2)!=1) pari_err_IMPL("lfuneuler");
     229           14 :   return poleval(p1,monomial(gneg(gel(p2,3)),1,0));
     230              : }
     231              : 
     232              : static GEN
     233          861 : vecan_shift(GEN an, long n, long prec)
     234              : {
     235          861 :   GEN p1 = ldata_vecan(gel(an,1), n, prec);
     236          861 :   GEN s = gel(an,2);
     237              :   long i;
     238              :   GEN V;
     239          861 :   if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1);
     240          861 :   V = cgetg(n+1, t_VEC);
     241          861 :   if (typ(s)==t_INT)
     242              :   {
     243          567 :     if (equali1(s))
     244        31850 :       for(i = 1; i <= n ; i++)
     245              :       {
     246        31500 :         GEN gi = gel(p1, i);
     247        31500 :         gel(V, i) = gequal0(gi)? gi: gmulgu(gi, i);
     248              :       }
     249              :     else
     250         3577 :       for(i = 1; i <= n ; i++)
     251              :       {
     252         3360 :         GEN gi = gel(p1, i);
     253         3360 :         gel(V, i) = gequal0(gi)? gi: gmul(gi, powgi(utoi(i), s));
     254              :       }
     255              :   }
     256              :   else
     257              :   {
     258          294 :     GEN D = dirpowers(n, s, prec);
     259         7735 :     for(i = 1; i <= n ; i++)
     260         7441 :       gel(V, i) = gmul(gel(p1,i), gel(D,i));
     261              :   }
     262          861 :   return V;
     263              : }
     264              : 
     265              : static GEN
     266           70 : eulerf_shift(GEN an, GEN p, long prec)
     267              : {
     268           70 :   GEN p1 = ldata_eulerf(gel(an,1), p, prec);
     269           70 :   GEN s = gel(an,2);
     270           70 :   return gsubst(p1, 0, monomial(gpow(p, s, prec), 1, 0));
     271              : }
     272              : 
     273              : static GEN
     274           84 : eulerf_hgm(GEN an, GEN p)
     275              : {
     276           84 :   GEN H = gel(an,1), t = gel(an,2);
     277           84 :   if (typ(t)==t_VEC && lg(t)==3)
     278              :   {
     279           28 :     GEN L = gel(t,2);
     280           28 :     long i, l = lg(L);
     281           28 :     t = gel(t,1);
     282           49 :     for (i = 1; i < l; i++) /* wild primes */
     283           35 :       if (equalii(p, gmael(L, i, 1))) break;
     284           28 :     if (i<l) return gmael(L,i,2);
     285              :   }
     286           70 :   return ginv(hgmeulerfactor(H, t, itos(p), NULL));
     287              : }
     288              : 
     289              : static GEN
     290          455 : deg1ser_shallow(GEN a1, GEN a0, long e)
     291          455 : { return RgX_to_ser(deg1pol_shallow(a1, a0, 0), e+2); }
     292              : /* lfunrtopoles without sort */
     293              : static GEN
     294          182 : rtopoles(GEN r)
     295              : {
     296          182 :   long j, l = lg(r);
     297          182 :   GEN v = cgetg(l, t_VEC);
     298          378 :   for (j = 1; j < l; j++)
     299              :   {
     300          196 :     GEN rj = gel(r,j), a = gel(rj,1);
     301          196 :     gel(v,j) = a;
     302              :   }
     303          182 :   return v;
     304              : }
     305              : /* re = polar part; overestimate when re = gen_0 (unknown) */
     306              : static long
     307          280 : orderpole(GEN re) { return typ(re) == t_SER? -valser(re): 1; }
     308              : static GEN
     309           84 : lfunmulpoles(GEN ldata1, GEN ldata2, long bitprec)
     310              : {
     311           84 :   GEN r, k = ldata_get_k(ldata1), b1 = NULL, b2 = NULL;
     312           84 :   GEN r1 = ldata_get_residue(ldata1);
     313           84 :   GEN r2 = ldata_get_residue(ldata2);
     314           84 :   long i, j, l, L = 0;
     315              : 
     316           84 :   if (!r1 && !r2) return NULL;
     317           77 :   if (r1 && !is_vec_t(typ(r1))) r1 = mkvec(mkvec2(k, r1));
     318           77 :   if (r2 && !is_vec_t(typ(r2))) r2 = mkvec(mkvec2(k, r2));
     319           77 :   if (r1) { b1 = rtopoles(r1); L += lg(b1); }
     320           77 :   if (r2) { b2 = rtopoles(r2); L += lg(b2); }
     321           77 :   r = cgetg(L, t_VEC); j = 1;
     322           77 :   if (b1)
     323              :   {
     324           70 :     l = lg(b1);
     325          147 :     for (i = 1; i < l; i++)
     326              :     {
     327           77 :       GEN z, z1, z2, be = gmael(r1,i,1);
     328           77 :       long n, v = orderpole(gmael(r1,i,2));
     329           77 :       if (b2 && (n = RgV_isin(b2, be))) v += orderpole(gmael(r2,n,2));
     330           77 :       z = deg1ser_shallow(gen_1, be, 2 + v);
     331           77 :       z1 = lfun(ldata1,z,bitprec);
     332           77 :       z2 = lfun(ldata2,z,bitprec);
     333           77 :       gel(r,j++) = mkvec2(be, gmul(z1, z2));
     334              :     }
     335              :   }
     336           77 :   if (b2)
     337              :   {
     338           70 :     long l = lg(b2);
     339          147 :     for (i = 1; i < l; i++)
     340              :     {
     341           77 :       GEN z, z1, z2, be = gmael(r2,i,1);
     342           77 :       long n, v = orderpole(gmael(r2,i,2));
     343           77 :       if (b1 && (n = RgV_isin(b1, be))) continue; /* done already */
     344           35 :       z = deg1ser_shallow(gen_1, be, 2 + v);
     345           35 :       z1 = lfun(ldata1,z,bitprec);
     346           35 :       z2 = lfun(ldata2,z,bitprec);
     347           35 :       gel(r,j++) = mkvec2(be, gmul(z1, z2));
     348              :     }
     349              :   }
     350           77 :   setlg(r, j); return r;
     351              : }
     352              : 
     353              : static GEN
     354           84 : lfunmul_k(GEN ldata1, GEN ldata2, GEN k, long bitprec)
     355              : {
     356              :   GEN r, N, Vga, eno, a1a2, b1b2;
     357           84 :   r = lfunmulpoles(ldata1, ldata2, bitprec);
     358           84 :   N = gmul(ldata_get_conductor(ldata1), ldata_get_conductor(ldata2));
     359           84 :   Vga = shallowconcat(ldata_get_gammavec(ldata1), ldata_get_gammavec(ldata2));
     360           84 :   Vga = sort(Vga);
     361           84 :   eno = gmul(ldata_get_rootno(ldata1), ldata_get_rootno(ldata2));
     362           84 :   a1a2 = lfunconvol(ldata_get_an(ldata1), ldata_get_an(ldata2));
     363           84 :   b1b2 = lfuncombdual(lfunconvol, ldata1, ldata2);
     364           84 :   return mkvecn(r? 7: 6, a1a2, b1b2, Vga, k, N, eno, r);
     365              : }
     366              : 
     367              : GEN
     368           63 : lfunmul(GEN ldata1, GEN ldata2, long bitprec)
     369              : {
     370           63 :   pari_sp ltop = avma;
     371              :   GEN k;
     372           63 :   long prec = nbits2prec(bitprec);
     373           63 :   ldata1 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata1), prec);
     374           63 :   ldata2 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata2), prec);
     375           63 :   k = ldata_get_k(ldata1);
     376           63 :   if (!gequal(ldata_get_k(ldata2),k))
     377            0 :     pari_err_OP("lfunmul [weight]",ldata1, ldata2);
     378           63 :   return gc_GEN(ltop, lfunmul_k(ldata1, ldata2, k, bitprec));
     379              : }
     380              : 
     381              : static GEN
     382           56 : lfundivpoles(GEN ldata1, GEN ldata2, long bitprec)
     383              : {
     384              :   long i, j, l;
     385           56 :   GEN be2, k  = ldata_get_k(ldata1);
     386           56 :   GEN r1 = ldata_get_residue(ldata1);
     387           56 :   GEN r2 = ldata_get_residue(ldata2), r;
     388              : 
     389           56 :   if (r1 && !is_vec_t(typ(r1))) r1 = mkvec(mkvec2(k, r1));
     390           56 :   if (r2 && !is_vec_t(typ(r2))) r2 = mkvec(mkvec2(k, r2));
     391           56 :   if (!r1) return NULL;
     392           56 :   l = lg(r1); r = cgetg(l, t_VEC);
     393           56 :   be2 = r2? rtopoles(r2): NULL;
     394          112 :   for (i = j = 1; j < l; j++)
     395              :   {
     396           56 :     GEN z, v = gel(r1,j), be = gel(v,1), s1 = gel(v,2);
     397              :     long n;
     398           56 :     if (be2 && (n = RgV_isin(be2, be)))
     399              :     {
     400           42 :       GEN s2 = gmael(r2,n,2); /* s1,s2: polar parts */
     401           42 :       if (orderpole(s1) == orderpole(s2)) continue;
     402              :     }
     403           14 :     z = gdiv(lfun(ldata1,be,bitprec), lfun(ldata2,be,bitprec));
     404           14 :     if (valser(z) < 0) gel(r,i++) = mkvec2(be, z);
     405              :   }
     406           56 :   if (i == 1) return NULL;
     407           14 :   setlg(r, i); return r;
     408              : }
     409              : 
     410              : static GEN
     411           56 : lfunvgasub(GEN v01, GEN v2)
     412              : {
     413           56 :   GEN v1 = shallowcopy(v01), v;
     414           56 :   long l1 = lg(v1), l2 = lg(v2), j1, j2, j;
     415          119 :   for (j2 = 1; j2 < l2; j2++)
     416              :   {
     417           91 :     for (j1 = 1; j1 < l1; j1++)
     418           91 :       if (gel(v1,j1) && gequal(gel(v1,j1), gel(v2,j2)))
     419              :       {
     420           63 :         gel(v1,j1) = NULL; break;
     421              :       }
     422           63 :     if (j1 == l1) pari_err_OP("lfunvgasub", v1, v2);
     423              :   }
     424           56 :   v = cgetg(l1-l2+1, t_VEC);
     425          259 :   for (j1 = j = 1; j1 < l1; j1++)
     426          203 :     if (gel(v1, j1)) gel(v,j++) = gel(v1,j1);
     427           56 :   return v;
     428              : }
     429              : 
     430              : GEN
     431           56 : lfundiv(GEN ldata1, GEN ldata2, long bitprec)
     432              : {
     433           56 :   pari_sp ltop = avma;
     434              :   GEN k, r, N, v, eno, a1a2, b1b2, eno2;
     435           56 :   long prec = nbits2prec(bitprec);
     436           56 :   ldata1 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata1), prec);
     437           56 :   ldata2 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata2), prec);
     438           56 :   k = ldata_get_k(ldata1);
     439           56 :   if (!gequal(ldata_get_k(ldata2),k))
     440            0 :     pari_err_OP("lfundiv [weight]",ldata1, ldata2);
     441           56 :   N = gdiv(ldata_get_conductor(ldata1), ldata_get_conductor(ldata2));
     442           56 :   if (typ(N) != t_INT) pari_err_OP("lfundiv [conductor]",ldata1, ldata2);
     443           56 :   r = lfundivpoles(ldata1, ldata2, bitprec);
     444           56 :   a1a2 = lfunconvolinv(ldata_get_an(ldata1), ldata_get_an(ldata2));
     445           56 :   b1b2 = lfuncombdual(lfunconvolinv, ldata1, ldata2);
     446           56 :   eno2 = ldata_get_rootno(ldata2);
     447           56 :   eno = isintzero(eno2)? gen_0: gdiv(ldata_get_rootno(ldata1), eno2);
     448           56 :   v = lfunvgasub(ldata_get_gammavec(ldata1), ldata_get_gammavec(ldata2));
     449           56 :   return gc_GEN(ltop,  mkvecn(r? 7: 6, a1a2, b1b2, v, k, N, eno, r));
     450              : }
     451              : 
     452              : static GEN
     453         2394 : gamma_imagchi(GEN gam, GEN w)
     454              : {
     455         2394 :   long i, j, k=1, l;
     456         2394 :   GEN g = cgetg_copy(gam, &l);
     457         2394 :   gam = shallowcopy(gam);
     458         7182 :   for (i = l-1; i>=1; i--)
     459              :   {
     460         4788 :     GEN al = gel(gam, i);
     461         4788 :     if (al)
     462              :     {
     463         2401 :       GEN N = gadd(w,gmul2n(real_i(al),1));
     464         2401 :       if (gcmpgs(N,2) > 0)
     465              :       {
     466         2387 :         GEN bl = gsubgs(al, 1);
     467         2387 :         for (j=1; j < i; j++)
     468         2387 :           if (gel(gam,j) && gequal(gel(gam,j), bl))
     469         2387 :           { gel(gam,j) = NULL; break; }
     470         2387 :         if (j==i) return NULL;
     471         2387 :         gel(g, k++) = al;
     472         2387 :         gel(g, k++) = bl;
     473           14 :       } else if (gequal0(N))
     474           14 :         gel(g, k++) = gaddgs(al, 1);
     475            0 :       else if (gequal1(N))
     476            0 :         gel(g, k++) = gsubgs(al, 1);
     477            0 :       else return NULL;
     478              :     }
     479              :   }
     480         2394 :   return sort(g);
     481              : }
     482              : 
     483              : GEN
     484         5187 : lfuntwist(GEN ldata1, GEN chi, long bitprec)
     485              : {
     486         5187 :   pari_sp ltop = avma;
     487              :   GEN k, L, N, N1, N2, a, a1, a2, b, b1, b2, gam, gam1, gam2;
     488              :   GEN ldata2;
     489              :   long d1, t;
     490         5187 :   long prec = nbits2prec(bitprec);
     491         5187 :   ldata1 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata1), prec);
     492         5187 :   ldata2 = lfunmisc_to_ldata_shallow(chi);
     493         5187 :   t = ldata_get_type(ldata2);
     494         5187 :   a1 = ldata_get_an(ldata1);
     495         5187 :   a2 = ldata_get_an(ldata2);
     496         5187 :   if (t == t_LFUN_ZETA)
     497         2422 :     return gc_GEN(ltop, ldata1);
     498         2765 :   if (t != t_LFUN_CHIZ && t != t_LFUN_KRONECKER &&
     499            7 :     ( t != t_LFUN_CHIGEN || nf_get_degree(bnr_get_nf(gmael(a2,2,1))) != 1))
     500            0 :     pari_err_TYPE("lfuntwist", chi);
     501         2765 :   N1 = ldata_get_conductor(ldata1);
     502         2765 :   N2 = ldata_get_conductor(ldata2);
     503         2765 :   if (!gequal1(gcdii(N1, N2)))
     504            0 :     pari_err_IMPL("lfuntwist (conductors not coprime)");
     505         2765 :   k = ldata_get_k(ldata1);
     506         2765 :   d1 = ldata_get_degree(ldata1);
     507         2765 :   N = gmul(N1, gpowgs(N2, d1));
     508         2765 :   gam1 = ldata_get_gammavec(ldata1);
     509         2765 :   gam2 = ldata_get_gammavec(ldata2);
     510         2765 :   if (gequal0(gel(gam2, 1)))
     511          371 :     gam = gam1;
     512              :   else
     513         2394 :     gam = gamma_imagchi(ldata_get_gammavec(ldata1), gaddgs(k,-1));
     514         2765 :   if (!gam) pari_err_IMPL("lfuntwist (gammafactors)");
     515         2765 :   b1 = ldata_get_dual(ldata1);
     516         2765 :   b2 = ldata_get_dual(ldata2);
     517         2765 :   a = tag(mkvec2(a1, a2), t_LFUN_TWIST);
     518         2765 :   if (typ(b1)==t_INT)
     519         2765 :     b = signe(b1) && signe(b2) ? gen_0: gen_1;
     520              :   else
     521            0 :     b = tag(mkvec2(b1,lfunconj(a2)), t_LFUN_TWIST);
     522         2765 :   L = mkvecn(6, a, b, gam, k, N, gen_0);
     523         2765 :   return gc_GEN(ltop, L);
     524              : }
     525              : 
     526              : static GEN
     527          308 : lfundualpoles(GEN ldata, GEN reno)
     528              : {
     529              :   long l, j;
     530          308 :   GEN k = ldata_get_k(ldata);
     531          308 :   GEN r = gel(reno,2), eno = gel(reno,3), R;
     532          308 :   R = cgetg_copy(r, &l);
     533          966 :   for (j = 1; j < l; j++)
     534              :   {
     535          658 :     GEN b = gmael(r,j,1), e = gmael(r,j,2);
     536          658 :     long v = varn(e);
     537          658 :     GEN E = gsubst(gdiv(e, eno), v, gneg(pol_x(v)));
     538          658 :     gel(R,l-j) = mkvec2(gsub(k,b), E);
     539              :   }
     540          308 :   return R;
     541              : }
     542              : 
     543              : static GEN
     544          595 : ginvvec(GEN x)
     545              : {
     546          595 :   if (is_vec_t(typ(x)))
     547           42 :     pari_APPLY_same(ginv(gel(x,i)))
     548              :   else
     549          581 :     return ginv(x);
     550              : }
     551              : 
     552              : GEN
     553          672 : lfundual(GEN L, long bitprec)
     554              : {
     555          672 :   pari_sp av = avma;
     556          672 :   long prec = nbits2prec(bitprec);
     557          672 :   GEN ldata = ldata_newprec(lfunmisc_to_ldata_shallow(L), prec);
     558          672 :   GEN a = ldata_get_an(ldata), b = ldata_get_dual(ldata);
     559          672 :   GEN e = ldata_get_rootno(ldata);
     560          672 :   GEN ldual, ad, bd, ed, Rd = NULL;
     561          672 :   if (typ(b) == t_INT)
     562              :   {
     563          644 :     ad = equali1(b) ? lfunconj(a): a;
     564          644 :     bd = b;
     565              :   }
     566           28 :   else { ad = b; bd = a; }
     567          672 :   if (lg(ldata)==8)
     568              :   {
     569          308 :     GEN reno = lfunrootres(ldata, bitprec);
     570          308 :     e = gel(reno,3);
     571          308 :     Rd = lfundualpoles(ldata, reno);
     572              :   }
     573          672 :   ed = isintzero(e) ? e: ginvvec(e);
     574          672 :   ldual = mkvecn(Rd ? 7:6, ad, bd, gel(ldata,3), gel(ldata,4), gel(ldata,5), ed, Rd);
     575          672 :   return gc_GEN(av, ldual);
     576              : }
     577              : 
     578              : static GEN
     579          224 : RgV_Rg_translate(GEN x, GEN s)
     580          511 : { pari_APPLY_same(gadd(gel(x,i),s)) }
     581              : 
     582              : static GEN
     583           28 : pole_translate(GEN x, GEN s, GEN Ns)
     584              : {
     585           28 :   x = shallowcopy(x);
     586           28 :   gel(x,1) = gadd(gel(x,1), s);
     587           28 :   if (Ns)
     588           28 :     gel(x,2) = gmul(gel(x,2), Ns);
     589           28 :   return x;
     590              : }
     591              : 
     592              : static GEN
     593           14 : poles_translate(GEN x, GEN s, GEN Ns)
     594           42 : { pari_APPLY_same(pole_translate(gel(x,i), s, Ns)) }
     595              : 
     596              : /* r / x + O(1) */
     597              : static GEN
     598          392 : simple_pole(GEN r)
     599              : {
     600              :   GEN S;
     601          392 :   if (isintzero(r)) return gen_0;
     602          343 :   S = deg1ser_shallow(gen_0, r, 1);
     603          343 :   setvalser(S, -1); return S;
     604              : }
     605              : 
     606              : GEN
     607          224 : lfunshift(GEN ldata, GEN s, long flag, long bitprec)
     608              : {
     609          224 :   pari_sp ltop = avma;
     610              :   GEN k, k1, L, N, a, b, gam, eps, res;
     611          224 :   long prec = nbits2prec(bitprec);
     612          224 :   if (!is_real_t(typ(s))) pari_err_TYPE("lfunshift",s);
     613          224 :   ldata = ldata_newprec(lfunmisc_to_ldata_shallow(ldata), prec);
     614          224 :   a = ldata_get_an(ldata);
     615          224 :   b = ldata_get_dual(ldata);
     616          224 :   gam = RgV_Rg_translate(ldata_get_gammavec(ldata), gneg(s));
     617          224 :   k = gadd(ldata_get_k(ldata), gmul2n(s, 1));
     618          224 :   k1 = gadd(ldata_get_k1(ldata), s);
     619          224 :   N = ldata_get_conductor(ldata);
     620          224 :   eps = ldata_get_rootno(ldata);
     621          224 :   res = ldata_get_residue(ldata);
     622          224 :   a = tag(mkvec2(a, s), t_LFUN_SHIFT);
     623          224 :   if (typ(b) != t_INT)
     624            0 :     b = tag(mkvec2(b, s), t_LFUN_SHIFT);
     625          224 :   if (res)
     626          224 :     switch(typ(res))
     627              :     {
     628            0 :     case t_VEC:
     629            0 :       res = poles_translate(res, s, NULL);
     630            0 :       break;
     631           14 :     case t_COL:
     632           14 :       res = poles_translate(res, s, gpow(N, gmul2n(s, -1), prec));
     633           14 :       break;
     634          210 :     default:
     635          210 :       res = mkvec(mkvec2(gsub(k, s), simple_pole(res)));
     636              :     }
     637          224 :   L = mkvecn(res ? 7: 6, a, b, gam, mkvec2(k, k1), N, eps, res);
     638          224 :   if (flag) L = lfunmul_k(ldata, L, gsub(k, s), bitprec);
     639          224 :   return gc_GEN(ltop, L);
     640              : }
     641              : 
     642              : /*****************************************************************/
     643              : /*  L-series from closure                                        */
     644              : /*****************************************************************/
     645              : static GEN
     646        58912 : localfactor(void *E, GEN p, long n)
     647              : {
     648        58912 :   GEN s = closure_callgen2((GEN)E, p, utoi(n));
     649        58912 :   return direuler_factor(s, n);
     650              : }
     651              : static GEN
     652         1967 : vecan_closure(GEN a, long L, long prec)
     653              : {
     654         1967 :   long ta = typ(a);
     655         1967 :   GEN gL, Sbad = NULL;
     656              : 
     657         1967 :   if (!L) return cgetg(1,t_VEC);
     658         1967 :   if (ta == t_VEC)
     659              :   {
     660         1064 :     long l = lg(a);
     661         1064 :     if (l == 1) pari_err_TYPE("vecan_closure", a);
     662         1064 :     ta = typ(gel(a,1));
     663              :     /* regular vector, return it */
     664         1064 :     if (ta != t_CLOSURE) return vecslice(a, 1, minss(L,l-1));
     665          119 :     if (l != 3) pari_err_TYPE("vecan_closure", a);
     666          119 :     Sbad = gel(a,2);
     667          119 :     if (typ(Sbad) != t_VEC) pari_err_TYPE("vecan_closure", a);
     668          112 :     a = gel(a,1);
     669              :   }
     670          903 :   else if (ta != t_CLOSURE) pari_err_TYPE("vecan_closure", a);
     671         1001 :   push_localprec(prec);
     672         1001 :   gL = stoi(L);
     673         1001 :   switch(closure_arity(a))
     674              :   {
     675          357 :     case 2:
     676          357 :       a = direuler_bad((void*)a, localfactor, gen_2, gL,gL, Sbad);
     677          322 :       break;
     678          637 :     case 1:
     679          637 :       a = closure_callgen1(a, gL);
     680          637 :       if (typ(a) != t_VEC) pari_err_TYPE("vecan_closure", a);
     681          630 :       break;
     682            7 :     default: pari_err_TYPE("vecan_closure [wrong arity]", a);
     683              :       a = NULL; /*LCOV_EXCL_LINE*/
     684              :   }
     685          952 :   pop_localprec(); return a;
     686              : }
     687              : 
     688              : static GEN
     689           70 : eulerf_closure(GEN a, GEN p, long prec)
     690              : {
     691           70 :   long ta = typ(a);
     692           70 :   GEN Sbad = NULL, f;
     693              : 
     694           70 :   if (ta == t_VEC)
     695              :   {
     696            0 :     long l = lg(a);
     697            0 :     if (l == 1) pari_err_TYPE("vecan_closure", a);
     698            0 :     ta = typ(gel(a,1));
     699              :     /* regular vector, return it */
     700            0 :     if (ta != t_CLOSURE) return NULL;
     701            0 :     if (l != 3) pari_err_TYPE("vecan_closure", a);
     702            0 :     Sbad = gel(a,2);
     703            0 :     if (typ(Sbad) != t_VEC) pari_err_TYPE("vecan_closure", a);
     704            0 :     a = gel(a,1);
     705              :   }
     706           70 :   else if (ta != t_CLOSURE) pari_err_TYPE("vecan_closure", a);
     707           70 :   push_localprec(prec);
     708           70 :   switch(closure_arity(a))
     709              :   {
     710           14 :     case 2:
     711           14 :       f = closure_callgen2(a, p, mkoo()); break;
     712           56 :     case 1:
     713           56 :       f = NULL; break;
     714            0 :     default:
     715            0 :       f = NULL; pari_err_TYPE("vecan_closure", a);
     716              :   }
     717           70 :   pop_localprec(); return f;
     718              : }
     719              : 
     720              : /*****************************************************************/
     721              : /*  L-series of Dirichlet characters.                            */
     722              : /*****************************************************************/
     723              : 
     724              : static GEN
     725         4228 : lfunzeta(void)
     726              : {
     727         4228 :   GEN zet = mkvecn(7, NULL, gen_0, NULL, gen_1, gen_1, gen_1, gen_1);
     728         4228 :   gel(zet,1) = tag(gen_1, t_LFUN_ZETA);
     729         4228 :   gel(zet,3) = mkvec(gen_0);
     730         4228 :   return zet;
     731              : }
     732              : 
     733              : static GEN
     734         3668 : vecan_Kronecker(GEN D, long n)
     735              : {
     736         3668 :   GEN v = cgetg(n+1, t_VECSMALL);
     737         3668 :   ulong Du = itou_or_0(D);
     738         3668 :   long i, id, d = Du ? minuu(Du, n): n;
     739        42553 :   for (i = 1; i <= d; i++) v[i] = krois(D,i);
     740       554925 :   for (id = i; i <= n; i++,id++) /* periodic mod d */
     741              :   {
     742       551257 :     if (id > d) id = 1;
     743       551257 :     gel(v, i) = gel(v, id);
     744              :   }
     745         3668 :   return v;
     746              : }
     747              : 
     748              : static GEN
     749         7049 : lfunchiquad(GEN D)
     750              : {
     751              :   GEN r;
     752         7049 :   D = coredisc(D);
     753         7049 :   if (equali1(D)) return lfunzeta();
     754         6090 :   if (!isfundamental(D)) pari_err_TYPE("lfunchiquad [not primitive]", D);
     755         6090 :   r = mkvecn(6, NULL, gen_0, NULL, gen_1, NULL, gen_1);
     756         6090 :   gel(r,1) = tag(icopy(D), t_LFUN_KRONECKER);
     757         6090 :   gel(r,3) = mkvec(signe(D) < 0? gen_1: gen_0);
     758         6090 :   gel(r,5) = mpabs(D);
     759         6090 :   return r;
     760              : }
     761              : 
     762              : /* Begin Hecke characters. Here a character is assumed to be given by a
     763              :    vector on the generators of the ray class group clgp of CL_m(K).
     764              :    If clgp = [h,[d1,...,dk],[g1,...,gk]] with dk|...|d2|d1, a character chi
     765              :    is given by [a1,a2,...,ak] such that chi(gi)=\zeta_di^ai. */
     766              : 
     767              : /* Value of CHI on x, coprime to bnr.mod */
     768              : static GEN
     769       106127 : chigeneval_i(GEN logx, GEN d, GEN nchi, GEN z, long prec)
     770              : {
     771       106127 :   pari_sp av = avma;
     772       106127 :   GEN e = FpV_dotproduct(nchi, logx, d);
     773       106127 :   if (!is_vec_t(typ(z)))
     774         1225 :     return gc_upto(av, gpow(z, e, prec));
     775              :   else
     776       104902 :     return gc_const(av, gel(z, itou(e) + 1));
     777              : }
     778              : 
     779              : static GEN
     780        86730 : chigenevalvec(GEN logx, GEN nchi, GEN z, long prec, long multi)
     781              : {
     782        86730 :   GEN d = gel(nchi,1), x = gel(nchi, 2);
     783        86730 :   if (multi)
     784        45605 :     pari_APPLY_same(chigeneval_i(logx, d, gel(x,i), z, prec))
     785              :   else
     786        73626 :     return chigeneval_i(logx, d, x, z, prec);
     787              : }
     788              : 
     789              : /* return x + yz; y != 0; z = 0,1 "often"; x = 0 "often" */
     790              : static GEN
     791      1911392 : gaddmul(GEN x, GEN y, GEN z)
     792              : {
     793              :   pari_sp av;
     794      1911392 :   if (typ(z) == t_INT)
     795              :   {
     796      1705039 :     if (!signe(z)) return x;
     797        30086 :     if (equali1(z)) return gadd(x,y);
     798              :   }
     799       227129 :   if (isintzero(x)) return gmul(y,z);
     800       119931 :   av = avma;
     801       119931 :   return gc_upto(av, gadd(x, gmul(y,z)));
     802              : }
     803              : 
     804              : static GEN
     805      1809619 : gaddmulvec(GEN x, GEN y, GEN z, long multi)
     806              : {
     807      1809619 :   if (multi)
     808       272741 :     pari_APPLY_same(gaddmul(gel(x,i),gel(y,i),gel(z,i)))
     809              :   else
     810      1724135 :     return gaddmul(x,y,z);
     811              : }
     812              : 
     813              : static GEN
     814         5201 : mkvchi(GEN chi, long n)
     815              : {
     816              :   GEN v;
     817         5201 :   if (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))))
     818          623 :   {
     819          623 :     long d = lg(chi)-1;
     820          623 :     v = const_vec(n, zerovec(d));
     821          623 :     gel(v,1) = const_vec(d, gen_1);
     822              :   }
     823              :   else
     824         4578 :     v = vec_ei(n, 1);
     825         5201 :   return v;
     826              : }
     827              : 
     828              : static GEN
     829         3647 : vecan_chiZ(GEN an, long n, long prec)
     830              : {
     831              :   forprime_t iter;
     832         3647 :   GEN G = gel(an,1);
     833         3647 :   GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2), z;
     834         3647 :   GEN gp = cgetipos(3), v = mkvchi(chi, n);
     835         3647 :   GEN N = znstar_get_N(G);
     836         3647 :   long ord = itos_or_0(gord);
     837         3647 :   ulong Nu = itou_or_0(N);
     838         3647 :   long i, id, d = Nu ? minuu(Nu, n): n;
     839         3647 :   long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))));
     840              :   ulong p;
     841         3647 :   if (!multichi && ord && n > (ord>>4))
     842         3521 :   {
     843         3521 :     GEN w = ncharvecexpo(G, nchi);
     844         3521 :     z = grootsof1(ord, prec);
     845        37926 :     for (i = 1; i <= d; i++)
     846        34405 :       if (w[i] >= 0) gel(v, i) = gel(z, w[i]+1);
     847              :   }
     848              :   else
     849              :   {
     850          126 :     z = rootsof1_cx(gord, prec);
     851          126 :     u_forprime_init(&iter, 2, d);
     852          805 :     while ((p = u_forprime_next(&iter)))
     853              :     {
     854              :       GEN ch;
     855              :       ulong k;
     856          679 :       if (!umodiu(N,p)) continue;
     857          560 :       gp[2] = p;
     858          560 :       ch = chigenevalvec(znconreylog(G, gp), nchi, z, prec, multichi);
     859          560 :       gel(v, p)  = ch;
     860         1582 :       for (k = 2*p; k <= (ulong)d; k += p)
     861         1022 :         gel(v, k) = gaddmulvec(gel(v, k), ch, gel(v, k/p), multichi);
     862              :     }
     863              :   }
     864       898765 :   for (id = i = d+1; i <= n; i++,id++) /* periodic mod d */
     865              :   {
     866       895118 :     if (id > d) id = 1;
     867       895118 :     gel(v, i) = gel(v, id);
     868              :   }
     869         3647 :   return v;
     870              : }
     871              : 
     872              : static GEN
     873           42 : eulerf_chiZ(GEN an, GEN p, long prec)
     874              : {
     875           42 :   GEN G = gel(an,1);
     876           42 :   GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2);
     877           42 :   long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))));
     878           42 :   GEN z = rootsof1_cx(gord, prec);
     879           42 :   GEN N = znstar_get_N(G);
     880           42 :   GEN ch = dvdii(N,p) ? gen_0: chigenevalvec(znconreylog(G, p), nchi, z, prec, multichi);
     881           42 :   return mkrfrac(gen_1, deg1pol_shallow(gneg(ch), gen_1,0));
     882              : }
     883              : 
     884              : static GEN
     885         1554 : vecan_chigen(GEN an, long n, long prec)
     886              : {
     887              :   forprime_t iter;
     888         1554 :   GEN bnr = gel(an,1), nf = bnr_get_nf(bnr);
     889         1554 :   GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2), z;
     890         1554 :   GEN gp = cgetipos(3), v = mkvchi(chi, n);
     891         1554 :   GEN N = gel(bnr_get_mod(bnr), 1), NZ = gcoeff(N,1,1);
     892         1554 :   long ord = itos_or_0(gord);
     893         1554 :   long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))));
     894              :   ulong p;
     895              : 
     896         1554 :   if (ord && n > (ord>>4))
     897         1554 :     z = grootsof1(ord, prec);
     898              :   else
     899            0 :     z = rootsof1_cx(gord, prec);
     900              : 
     901         1554 :   if (nf_get_degree(nf) == 1)
     902              :   {
     903         1155 :     ulong Nu = itou_or_0(NZ);
     904         1155 :     long i, id, d = Nu ? minuu(Nu, n): n;
     905         1155 :     u_forprime_init(&iter, 2, d);
     906         6909 :     while ((p = u_forprime_next(&iter)))
     907              :     {
     908              :       GEN ch;
     909              :       ulong k;
     910         5754 :       if (!umodiu(NZ,p)) continue;
     911         4480 :       gp[2] = p;
     912         4480 :       ch = chigenevalvec(isprincipalray(bnr,gp), nchi, z, prec, multichi);
     913         4480 :       gel(v, p)  = ch;
     914        13370 :       for (k = 2*p; k <= (ulong)d; k += p)
     915         8890 :         gel(v, k) = gaddmulvec(gel(v, k), ch, gel(v, k/p), multichi);
     916              :     }
     917        13909 :     for (id = i = d+1; i <= n; i++,id++) /* periodic mod d */
     918              :     {
     919        12754 :       if (id > d) id = 1;
     920        12754 :       gel(v, i) = gel(v, id);
     921              :     }
     922              :   }
     923              :   else
     924              :   {
     925          399 :     GEN BOUND = stoi(n);
     926          399 :     u_forprime_init(&iter, 2, n);
     927        82369 :     while ((p = u_forprime_next(&iter)))
     928              :     {
     929              :       GEN L;
     930              :       long j;
     931        81970 :       int check = !umodiu(NZ,p);
     932        81970 :       gp[2] = p;
     933        81970 :       L = idealprimedec_limit_norm(nf, gp, BOUND);
     934       163828 :       for (j = 1; j < lg(L); j++)
     935              :       {
     936        81858 :         GEN pr = gel(L, j), ch;
     937              :         ulong k, q;
     938        81858 :         if (check && idealval(nf, N, pr)) continue;
     939        81613 :         ch = chigenevalvec(isprincipalray(bnr,pr), nchi, z, prec, multichi);
     940        81613 :         q = upr_norm(pr);
     941        81613 :         gel(v, q) = gadd(gel(v, q), ch);
     942      1881320 :         for (k = 2*q; k <= (ulong)n; k += q)
     943      1799707 :           gel(v, k) = gaddmulvec(gel(v, k), ch, gel(v, k/q), multichi);
     944              :       }
     945              :     }
     946              :   }
     947         1554 :   return v;
     948              : }
     949              : 
     950              : static GEN
     951           28 : eulerf_chigen(GEN an, GEN p, long prec)
     952              : {
     953           28 :   GEN bnr = gel(an,1), nf = bnr_get_nf(bnr);
     954           28 :   GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2), z;
     955           28 :   GEN N = gel(bnr_get_mod(bnr), 1), NZ = gcoeff(N,1,1), f;
     956           28 :   long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1))));
     957              : 
     958           28 :   z = rootsof1_cx(gord, prec);
     959           28 :   if (nf_get_degree(nf) == 1)
     960              :   {
     961              :     GEN ch;
     962            0 :     if (dvdii(NZ,p)) ch = gen_0;
     963              :     else
     964              :     {
     965            0 :       ch = chigenevalvec(isprincipalray(bnr,p), nchi, z, prec, multichi);
     966            0 :       if (typ(ch)==t_VEC) return NULL;
     967              :     }
     968            0 :     f = deg1pol_shallow(gneg(ch), gen_1, 0);
     969              :   }
     970              :   else
     971              :   {
     972           28 :     int check = dvdii(NZ,p);
     973           28 :     GEN L = idealprimedec(nf, p);
     974           28 :     long j, lL = lg(L);
     975           28 :     f = pol_1(0);
     976           49 :     for (j = 1; j < lL; j++)
     977              :     {
     978           35 :       GEN pr = gel(L, j), ch;
     979           35 :       if (check && idealval(nf, N, pr)) ch = gen_0;
     980              :       else
     981           35 :       ch = chigenevalvec(isprincipalray(bnr,pr), nchi, z, prec, multichi);
     982           35 :       if (typ(ch)==t_VEC) return NULL;
     983           21 :       f = gmul(f, gsub(gen_1, monomial(ch, pr_get_f(pr), 0)));
     984              :     }
     985              :   }
     986           14 :   return mkrfrac(gen_1,f);
     987              : }
     988              : 
     989              : static GEN
     990         4760 : vec01(long r1, long r2)
     991              : {
     992         4760 :   long d = r1+r2, i;
     993         4760 :   GEN v = cgetg(d+1,t_VEC);
     994        13811 :   for (i = 1; i <= r1; i++) gel(v,i) = gen_0;
     995         8316 :   for (     ; i <= d;  i++) gel(v,i) = gen_1;
     996         4760 :   return v;
     997              : }
     998              : 
     999              : /* true nf or t_POL */
    1000              : static GEN
    1001         1288 : lfunzetak_i(GEN T)
    1002              : {
    1003              :   GEN Vga, N;
    1004              :   long r1, r2;
    1005         1288 :   if (typ(T) == t_POL)
    1006              :   {
    1007          686 :     T = nfinit0(T, nf_NOLLL, DEFAULTPREC);
    1008          686 :     if (lg(T) == 3) T = gel(T,1); /* [nf,change of var] */
    1009              :   }
    1010         1288 :   if (nf_get_degree(T) == 1) return lfunzeta();
    1011         1288 :   nf_get_sign(T,&r1,&r2); Vga = vec01(r1+r2,r2);
    1012         1288 :   N = absi_shallow(nf_get_disc(T));
    1013         1288 :   return mkvecn(7, tag(T,t_LFUN_NF), gen_0, Vga, gen_1, N, gen_1, gen_0);
    1014              : }
    1015              : /* truen nf or t_POL */
    1016              : static GEN
    1017          861 : lfunzetak(GEN T)
    1018          861 : { pari_sp av = avma; return gc_GEN(av, lfunzetak_i(T)); }
    1019              : 
    1020              : /* C = normalized character of order dividing o; renormalize so that it has
    1021              :  * apparent order o */
    1022              : GEN
    1023         1204 : char_renormalize(GEN C, GEN o)
    1024              : {
    1025         1204 :   GEN oc = gel(C,1), c = gel(C,2);
    1026         1204 :   if (!equalii(o, oc)) c = ZC_Z_mul(c, diviiexact(o, oc));
    1027         1204 :   return c;
    1028              : }
    1029              : static GEN
    1030           21 : vecchar_renormalize(GEN x, GEN o)
    1031           63 : { pari_APPLY_same(char_renormalize(gel(x,i), o)); }
    1032              : 
    1033              : /* G is a bid of nftyp typ_BIDZ */
    1034              : static GEN
    1035         8449 : lfunchiZ(GEN G, GEN CHI)
    1036              : {
    1037         8449 :   pari_sp av = avma;
    1038         8449 :   GEN sig = NULL, N = bid_get_ideal(G), nchi, r;
    1039              :   int real;
    1040              :   long s;
    1041              : 
    1042         8449 :   if (typ(N) != t_INT) pari_err_TYPE("lfunchiZ", G);
    1043         8449 :   if (typ(CHI) == t_VEC && !RgV_is_ZV(CHI))
    1044           21 :   {
    1045           42 :     GEN C, G0 = G, o = gen_1;
    1046           42 :     long i, l = lg(CHI);
    1047           42 :     nchi = cgetg(l, t_VEC);
    1048           42 :     N = znconreyconductor(G, gel(CHI,1), &C);
    1049           35 :     if (typ(N) != t_INT) G = znstar0(N, 1);
    1050           35 :     s = zncharisodd(G, C);
    1051           91 :     for (i = 1; i < l; i++)
    1052              :     {
    1053           70 :       if (i > 1)
    1054              :       {
    1055           35 :         if (!gequal(N, znconreyconductor(G0, gel(CHI,i), &C))
    1056           28 :             || zncharisodd(G, C) != s)
    1057           14 :           pari_err_TYPE("lfuncreate [different conductors]", CHI);
    1058              :       }
    1059           56 :       C = znconreylog_normalize(G, C);
    1060           56 :       o = lcmii(o, gel(C,1)); /* lcm with charorder */
    1061           56 :       gel(nchi,i) = C;
    1062              :     }
    1063           21 :     nchi = mkvec2(o, vecchar_renormalize(nchi, o));
    1064           21 :     if (typ(N) != t_INT) N = gel(N,1);
    1065              :   }
    1066              :   else
    1067              :   {
    1068         8407 :     N = znconreyconductor(G, CHI, &CHI);
    1069         8407 :     if (typ(N) != t_INT)
    1070              :     {
    1071            7 :       if (equali1(gel(N,1))) { set_avma(av); return lfunzeta(); }
    1072            0 :       G = znstar0(N, 1);
    1073            0 :       N = gel(N,1);
    1074              :     }
    1075              :     /* CHI now primitive on G */
    1076         8400 :     switch(itou_or_0(zncharorder(G, CHI)))
    1077              :     {
    1078         2422 :       case 1: set_avma(av); return lfunzeta();
    1079         2996 :       case 2: if (zncharisodd(G,CHI)) N = negi(N);
    1080         2996 :               return gc_upto(av, lfunchiquad(N));
    1081              :     }
    1082         2982 :     nchi = znconreylog_normalize(G, CHI);
    1083         2982 :     s = zncharisodd(G, CHI);
    1084              :   }
    1085         3003 :   sig = mkvec(s? gen_1: gen_0);
    1086         3003 :   real = abscmpiu(gel(nchi,1), 2) <= 0;
    1087         3003 :   r = mkvecn(6, tag(mkvec2(G,nchi), t_LFUN_CHIZ),
    1088              :                 real? gen_0: gen_1, sig, gen_1, N, gen_0);
    1089         3003 :   return gc_GEN(av, r);
    1090              : }
    1091              : 
    1092              : static GEN
    1093         1540 : lfunchigen(GEN bnr, GEN CHI)
    1094              : {
    1095         1540 :   pari_sp av = avma;
    1096              :   GEN N, sig, Ldchi, nf, nchi, NN;
    1097              :   long r1, r2, n1;
    1098              :   int real;
    1099              : 
    1100         1540 :   if (typ(CHI) == t_VEC && !RgV_is_ZV(CHI))
    1101              :   {
    1102          350 :     bnr_vecchar_sanitize(&bnr, &CHI);
    1103          343 :     nchi = CHI;
    1104              :   }
    1105              :   else
    1106              :   {
    1107         1190 :     bnr_char_sanitize(&bnr, &CHI);
    1108         1190 :     nchi = NULL; /* now CHI is primitive wrt bnr */
    1109              :   }
    1110              : 
    1111         1533 :   N = bnr_get_mod(bnr);
    1112         1533 :   nf = bnr_get_nf(bnr);
    1113         1533 :   n1 = lg(vec01_to_indices(gel(N,2))) - 1; /* vecsum(N[2]) */
    1114         1533 :   N = gel(N,1);
    1115         1533 :   NN = mulii(idealnorm(nf, N), absi_shallow(nf_get_disc(nf)));
    1116         1533 :   if (!nchi)
    1117              :   {
    1118         1190 :     if (equali1(NN)) { set_avma(av); return lfunzeta(); }
    1119          735 :     if (ZV_equal0(CHI)) return gc_GEN(av, lfunzetak_i(bnr_get_nf(bnr)));
    1120          658 :     nchi = char_normalize(CHI, cyc_normalize(bnr_get_cyc(bnr)));
    1121              :   }
    1122         1001 :   real = abscmpiu(gel(nchi,1), 2) <= 0;
    1123         1001 :   nf_get_sign(nf, &r1, &r2);
    1124         1001 :   sig = vec01(r1+r2-n1, r2+n1);
    1125         1001 :   Ldchi = mkvecn(6, tag(mkvec2(bnr, nchi), t_LFUN_CHIGEN),
    1126              :                     real? gen_0: gen_1, sig, gen_1, NN, gen_0);
    1127         1001 :   return gc_GEN(av, Ldchi);
    1128              : }
    1129              : 
    1130              : /* Find all characters of clgp whose kernel contain group given by HNF H.
    1131              :  * Set *pcnj[i] to the conductor */
    1132              : static GEN
    1133          532 : chigenkerfind(GEN bnr, GEN H, GEN *pcnj)
    1134              : {
    1135          532 :   GEN res, cnj, L = bnrchar(bnr, H, NULL);
    1136          532 :   long i, k, l = lg(L);
    1137              : 
    1138          532 :   res = cgetg(l, t_VEC);
    1139          532 :   *pcnj = cnj = cgetg(l, t_VEC);
    1140         2597 :   for (i = k = 1; i < l; i++)
    1141              :   {
    1142         2065 :     GEN chi = gel(L,i);
    1143         2065 :     gel(res, k) = chi;
    1144         2065 :     gel(cnj, k) = ZV_equal0(chi)? gen_0: bnrconductor_raw(bnr, chi);
    1145         2065 :     k++;
    1146              :   }
    1147          532 :   setlg(cnj, k);
    1148          532 :   setlg(res, k); return res;
    1149              : }
    1150              : 
    1151              : static GEN
    1152          532 : vec_classes(GEN A, GEN F)
    1153              : {
    1154          532 :   GEN w = vec_equiv(F);
    1155          532 :   long i, l = lg(w);
    1156          532 :   GEN V = cgetg(l, t_VEC);
    1157         1813 :   for (i = 1; i < l; i++) gel(V,i) = vecpermute(A,gel(w,i));
    1158          532 :   return V;
    1159              : }
    1160              : 
    1161              : static GEN
    1162       990451 : abelrel_pfactor(GEN bnr, GEN pr, GEN U, GEN D, GEN h)
    1163              : {
    1164       990451 :   GEN v = bnrisprincipalmod(bnr, pr, h, 0);
    1165       990451 :   GEN E = ZV_ZV_mod(ZM_ZC_mul(U, v), D);
    1166       990451 :   ulong o = itou(charorder(D, E)), f = pr_get_f(pr);
    1167       990451 :   return gpowgs(gsub(gen_1, monomial(gen_1, f * o, 0)), itou(h) / o);
    1168              : }
    1169              : 
    1170              : static GEN
    1171       687925 : abelrel_factor(GEN bnr, GEN C, GEN p, GEN mod, GEN U, GEN D, GEN h)
    1172              : {
    1173       687925 :   GEN nf = bnr_get_nf(bnr), F = pol_1(0), prid = idealprimedec(nf,p);
    1174       687925 :   GEN mod2 = shallowcopy(mod);
    1175       687925 :   long i, l = lg(prid);
    1176      1678376 :   for (i = 1; i < l; i++)
    1177              :   {
    1178       990451 :     GEN pr = gel(prid, i), Fpr;
    1179       990451 :     long v = idealval(nf,mod,pr);
    1180       990451 :     if (v > 0)
    1181              :     {
    1182              :       GEN bnr2, C2, U2, D2, h2;
    1183          161 :       gel(mod2, 1) = idealdivpowprime(nf, gel(mod, 1), pr, utoi(v));
    1184          161 :       bnr2 = bnrinitmod(bnr, mod2, 0, h);
    1185          161 :       C2 = bnrmap(bnrmap(bnr, bnr2), C);
    1186          161 :       D2 = ZM_snfall_i(C2, &U2, NULL, 1);
    1187          161 :       h2 = ZV_prod(D2);
    1188          161 :       Fpr = abelrel_pfactor(bnr2, pr, U2, D2, h2);
    1189              :     }
    1190              :     else
    1191       990290 :       Fpr = abelrel_pfactor(bnr, pr, U, D, h);
    1192       990451 :     F = ZX_mul(F, Fpr);
    1193              :   }
    1194       687925 :   return gcopy(mkrfrac(gen_1, F));
    1195              : }
    1196              : 
    1197              : static GEN
    1198           42 : eulerf_abelrel(GEN an, GEN p)
    1199              : {
    1200           42 :   GEN bnr = gel(an,1), C = gel(an,2), mod = gel(an,3);
    1201           42 :   GEN U, D = ZM_snfall_i(C, &U, NULL, 1), h = ZV_prod(D);
    1202           42 :   return abelrel_factor(bnr, C, p, mod, U, D, h);
    1203              : }
    1204              : 
    1205              : struct direuler_abelrel
    1206              : {
    1207              :   GEN bnr, C, mod, U, D, h;
    1208              : };
    1209              : 
    1210              : static GEN
    1211       687883 : _direuler_abelrel(void *E, GEN p)
    1212              : {
    1213       687883 :   struct direuler_abelrel *s = (struct direuler_abelrel*) E;
    1214       687883 :   return abelrel_factor(s->bnr, s->C, p, s->mod, s->U, s->D, s->h);
    1215              : }
    1216              : 
    1217              : static GEN
    1218          168 : vecan_abelrel(GEN an, long N)
    1219              : {
    1220              :   struct direuler_abelrel s;
    1221          168 :   s.bnr = gel(an,1);
    1222          168 :   s.C   = gel(an,2);
    1223          168 :   s.mod = gel(an,3);
    1224          168 :   s.D = ZM_snfall_i(s.C, &s.U, NULL, 1);
    1225          168 :   s.h = ZV_prod(s.D);
    1226          168 :   return direuler((void*)&s, _direuler_abelrel, gen_1, stoi(N), NULL);
    1227              : }
    1228              : 
    1229              : static GEN
    1230          553 : lfunabelrel_i(GEN bnr, GEN H, GEN mod)
    1231              : {
    1232          553 :   GEN NrD = bnrdisc(bnr, H, 0), N = absi_shallow(gel(NrD,3));
    1233          553 :   long n = itos(gel(NrD,1)), r1 = itos(gel(NrD,2)), r2 = (n-r1)>>1;
    1234          553 :   if (!mod) mod = bnrconductor(bnr, H, 0);
    1235          553 :   return mkvecn(7, tag(mkvec3(bnr,H,mod),t_LFUN_ABELREL),
    1236              :                    gen_0, vec01(r1+r2, r2), gen_1, N, gen_1, gen_0);
    1237              : }
    1238              : static GEN
    1239           21 : lfunabelrel(GEN bnr, GEN H, GEN mod)
    1240           21 : { pari_sp av = avma; return gc_GEN(av, lfunabelrel_i(bnr, H, mod)); }
    1241              : 
    1242              : 
    1243              : static GEN
    1244         1281 : lfunchiinit(GEN bnr, GEN chi, GEN dom, long der, long bitprec)
    1245              : {
    1246         1281 :   GEN L = lfunchigen(bnr, lg(chi)==2 ? gel(chi,1): chi);
    1247         1281 :   return lfuninit(L, dom, der, bitprec);
    1248              : }
    1249              : static GEN
    1250          532 : veclfunchiinit(GEN bnr, GEN x, GEN dom, long der, long bitprec)
    1251         1813 : { pari_APPLY_same(lfunchiinit(bnr, gel(x,i), dom, der, bitprec)); }
    1252              : GEN
    1253          532 : lfunabelianrelinit(GEN bnr, GEN H, GEN dom, long der, long bitprec)
    1254              : {
    1255          532 :   GEN cnj, M, D, C = chigenkerfind(bnr, H, &cnj);
    1256              :   long l;
    1257          532 :   C = vec_classes(C, cnj); l = lg(C);
    1258          532 :   M = mkvec3(veclfunchiinit(bnr, C, dom, der, bitprec),
    1259              :              const_vecsmall(l-1, 1), const_vecsmall(l-1, 0));
    1260          532 :   D = mkvec2(dom, mkvecsmall2(der, bitprec));
    1261          532 :   return lfuninit_make(t_LDESC_PRODUCT, lfunabelrel_i(bnr, H, NULL), M, D);
    1262              : }
    1263              : 
    1264              : /*****************************************************************/
    1265              : /*                 Dedekind zeta functions                       */
    1266              : /*****************************************************************/
    1267              : /* true nf */
    1268              : static GEN
    1269         2107 : dirzetak0(GEN nf, ulong N)
    1270              : {
    1271         2107 :   GEN vect, c, c2, T = nf_get_pol(nf), index = nf_get_index(nf);
    1272         2107 :   pari_sp av = avma, av2;
    1273         2107 :   const ulong SQRTN = usqrt(N);
    1274              :   ulong i, p, lx;
    1275         2107 :   long court[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0};
    1276              :   forprime_t S;
    1277              : 
    1278         2107 :   c  = cgetalloc(N+1, t_VECSMALL);
    1279         2107 :   c2 = cgetalloc(N+1, t_VECSMALL);
    1280      2671991 :   c2[1] = c[1] = 1; for (i=2; i<=N; i++) c[i] = 0;
    1281         2107 :   u_forprime_init(&S, 2, N); av2 = avma;
    1282       348579 :   while ( (p = u_forprime_next(&S)) )
    1283              :   {
    1284       346472 :     set_avma(av2);
    1285       346472 :     if (umodiu(index, p)) /* p does not divide index */
    1286       346108 :       vect = gel(Flx_degfact(ZX_to_Flx(T,p), p),1);
    1287              :     else
    1288              :     {
    1289          364 :       court[2] = p;
    1290          364 :       vect = idealprimedec_degrees(nf,court);
    1291              :     }
    1292       346472 :     lx = lg(vect);
    1293       346472 :     if (p <= SQRTN)
    1294        35245 :       for (i=1; i<lx; i++)
    1295              :       {
    1296        23548 :         ulong qn, q = upowuu(p, vect[i]); /* Norm P[i] */
    1297        23548 :         if (!q || q > N) break;
    1298        20797 :         memcpy(c2 + 2, c + 2, (N-1)*sizeof(long));
    1299              :         /* c2[i] <- c[i] + sum_{k = 1}^{v_q(i)} c[i/q^k] for all i <= N */
    1300        42889 :         for (qn = q; qn <= N; qn *= q)
    1301              :         {
    1302        42889 :           ulong k0 = N/qn, k, k2; /* k2 = k*qn */
    1303      3760050 :           for (k = k0, k2 = k*qn; k > 0; k--, k2 -=qn) c2[k2] += c[k];
    1304        42889 :           if (q > k0) break; /* <=> q*qn > N */
    1305              :         }
    1306        20797 :         swap(c, c2);
    1307              :       }
    1308              :     else /* p > sqrt(N): simpler */
    1309       656292 :       for (i=1; i<lx; i++)
    1310              :       {
    1311              :         ulong k, k2; /* k2 = k*p */
    1312       581798 :         if (vect[i] > 1) break;
    1313              :         /* c2[i] <- c[i] + sum_{k = 1}^{v_q(i)} c[i/q^k] for all i <= N */
    1314      1906723 :         for (k = N/p, k2 = k*p; k > 0; k--, k2 -= p) c[k2] += c[k];
    1315              :       }
    1316              :   }
    1317         2107 :   pari_free(c2); return gc_const(av, c);
    1318              : }
    1319              : 
    1320              : static GEN
    1321          168 : eulerf_zetak(GEN nf, GEN p)
    1322              : {
    1323          168 :   GEN v, f = pol_1(0);
    1324              :   long i, l;
    1325          168 :   if (dvdii(nf_get_index(nf), p)) /* p does not divide index */
    1326            7 :     v = idealprimedec_degrees(nf,p);
    1327              :   else
    1328          161 :     v = gel(FpX_degfact(nf_get_pol(nf), p), 1);
    1329          168 :   l = lg(v);
    1330          406 :   for (i = 1; i < l; i++) f = ZX_sub(f, RgX_shift_shallow(f, v[i]));
    1331          168 :   retmkrfrac(gen_1, ZX_copy(f));
    1332              : }
    1333              : 
    1334              : GEN
    1335         2107 : dirzetak(GEN nf, GEN b)
    1336              : {
    1337              :   GEN z, c;
    1338              :   long n;
    1339              : 
    1340         2107 :   if (typ(b) != t_INT) pari_err_TYPE("dirzetak",b);
    1341         2107 :   if (signe(b) <= 0) return cgetg(1,t_VEC);
    1342         2107 :   nf = checknf(nf);
    1343         2107 :   n = itou_or_0(b); if (!n) pari_err_OVERFLOW("dirzetak");
    1344         2107 :   c = dirzetak0(nf, n);
    1345         2107 :   z = vecsmall_to_vec(c); pari_free(c); return z;
    1346              : }
    1347              : 
    1348              : static GEN
    1349          658 : linit_get_mat(GEN linit)
    1350              : {
    1351          658 :   if (linit_get_type(linit)==t_LDESC_PRODUCT)
    1352          161 :     return lfunprod_get_fact(linit_get_tech(linit));
    1353              :   else
    1354          497 :     return mkvec3(mkvec(linit), mkvecsmall(1), mkvecsmall(0));
    1355              : }
    1356              : 
    1357              : static GEN
    1358          329 : lfunproduct(GEN ldata, GEN linit1, GEN linit2, GEN domain)
    1359              : {
    1360          329 :   GEN M1 = linit_get_mat(linit1);
    1361          329 :   GEN M2 = linit_get_mat(linit2);
    1362          329 :   GEN M3 = mkvec3(shallowconcat(gel(M1, 1), gel(M2, 1)),
    1363          329 :                   vecsmall_concat(gel(M1, 2), gel(M2, 2)),
    1364          329 :                   vecsmall_concat(gel(M1, 3), gel(M2, 3)));
    1365          329 :   return lfuninit_make(t_LDESC_PRODUCT, ldata, M3, domain);
    1366              : }
    1367              : static GEN lfunzetakinit_artin(GEN nf, GEN gal, GEN dom, long der, long bit);
    1368              : /* true nf */
    1369              : static GEN
    1370          329 : lfunzetakinit_quotient(GEN nf, GEN polk, GEN dom, long der, long bitprec)
    1371              : {
    1372              :   GEN ak, an, nfk, Vga, ldata, N, Lk, LKk, domain;
    1373              :   long r1k, r2k, r1, r2;
    1374              : 
    1375          329 :   nf_get_sign(nf,&r1,&r2);
    1376          329 :   nfk = nfinit(polk, nbits2prec(bitprec));
    1377          329 :   Lk = lfunzetakinit(nfk, dom, der, bitprec); /* zeta_k */
    1378          329 :   nf_get_sign(nfk,&r1k,&r2k);
    1379          329 :   Vga = vec01((r1+r2) - (r1k+r2k), r2-r2k);
    1380          329 :   N = absi_shallow(diviiexact(nf_get_disc(nf), nf_get_disc(nfk)));
    1381          329 :   ak = nf_get_degree(nf)==1 ? tag(gen_1, t_LFUN_ZETA): tag(nfk, t_LFUN_NF);
    1382          329 :   an = tag(mkvec2(tag(nf,t_LFUN_NF), ak), t_LFUN_DIV);
    1383          329 :   ldata = mkvecn(6, an, gen_0, Vga, gen_1, N, gen_1);
    1384          329 :   LKk = lfuninit(ldata, dom, der, bitprec); /* zeta_K/zeta_k */
    1385          329 :   domain = mkvec2(dom, mkvecsmall2(der, bitprec));
    1386          329 :   return lfunproduct(lfunzetak_i(nf), Lk, LKk, domain);
    1387              : }
    1388              : /* true nf */
    1389              : GEN
    1390          959 : lfunzetakinit(GEN nf, GEN dom, long der, long bitprec)
    1391              : {
    1392          959 :   long n, d = nf_get_degree(nf);
    1393          959 :   GEN L, Q, R, T = nf_get_pol(nf);
    1394          959 :   if (d == 1) return lfuninit(lfunzeta(), dom, der, bitprec);
    1395          791 :   if (d > 2)
    1396              :   {
    1397          455 :     GEN G = galoisinit(nf, NULL);
    1398          455 :     if (isintzero(G))
    1399              :     { /* not Galois */
    1400          329 :       GEN S = nfsubfields(nf, 0); n = lg(S)-1;
    1401          329 :       return lfunzetakinit_quotient(nf, gmael(S,n-1,1), dom, der, bitprec);
    1402              :     }
    1403          126 :     if (!group_isabelian(galois_group(G))) /* Galois, not Abelian */
    1404           21 :       return lfunzetakinit_artin(nf, G, dom, der, bitprec);
    1405              :   }
    1406              :   /* Abelian over Q */
    1407          441 :   Q = Buchall(pol_x(1), 0, nbits2prec(bitprec));
    1408          441 :   T = shallowcopy(T); setvarn(T,0);
    1409          441 :   R = rnfconductor0(Q, T, 1);
    1410          441 :   L = lfunabelianrelinit(gel(R,2), gel(R,3), dom, der, bitprec);
    1411          441 :   delete_var(); return L;
    1412              : }
    1413              : 
    1414              : /***************************************************************/
    1415              : /*             Elliptic Curves and Modular Forms               */
    1416              : /***************************************************************/
    1417              : 
    1418              : static GEN
    1419          210 : lfunellnf(GEN e)
    1420              : {
    1421          210 :   pari_sp av = avma;
    1422          210 :   GEN ldata = cgetg(7, t_VEC), nf = ellnf_get_nf(e);
    1423          210 :   GEN N = gel(ellglobalred(e), 1);
    1424          210 :   long n = nf_get_degree(nf);
    1425          210 :   gel(ldata, 1) = tag(e, t_LFUN_ELL);
    1426          210 :   gel(ldata, 2) = gen_0;
    1427          210 :   gel(ldata, 3) = vec01(n, n);
    1428          210 :   gel(ldata, 4) = gen_2;
    1429          210 :   gel(ldata, 5) = mulii(idealnorm(nf,N), sqri(nf_get_disc(nf)));
    1430          210 :   gel(ldata, 6) = stoi(ellrootno_global(e));
    1431          210 :   return gc_GEN(av, ldata);
    1432              : }
    1433              : 
    1434              : static GEN
    1435         3878 : lfunellQ(GEN e)
    1436              : {
    1437         3878 :   pari_sp av = avma;
    1438         3878 :   GEN ldata = cgetg(7, t_VEC);
    1439         3878 :   gel(ldata, 1) = tag(ellanal_globalred(e, NULL), t_LFUN_ELL);
    1440         3878 :   gel(ldata, 2) = gen_0;
    1441         3878 :   gel(ldata, 3) = mkvec2(gen_0, gen_1);
    1442         3878 :   gel(ldata, 4) = gen_2;
    1443         3878 :   gel(ldata, 5) = ellQ_get_N(e);
    1444         3878 :   gel(ldata, 6) = stoi(ellrootno_global(e));
    1445         3878 :   return gc_GEN(av, ldata); /* ellanal_globalred not stack-safe */
    1446              : }
    1447              : 
    1448              : static GEN
    1449         4088 : lfunell(GEN e)
    1450              : {
    1451         4088 :   long t = ell_get_type(e);
    1452         4088 :   switch(t)
    1453              :   {
    1454         3878 :     case t_ELL_Q: return lfunellQ(e);
    1455          210 :     case t_ELL_NF:return lfunellnf(e);
    1456              :   }
    1457            0 :   pari_err_TYPE("lfun",e);
    1458              :   return NULL; /*LCOV_EXCL_LINE*/
    1459              : }
    1460              : 
    1461              : static GEN
    1462          140 : ellsympow_gamma(long m)
    1463              : {
    1464          140 :   GEN V = cgetg(m+2, t_VEC);
    1465          140 :   long i = 1, j;
    1466          140 :   if (!odd(m)) gel(V, i++) = stoi(-2*(m>>2));
    1467          364 :   for (j = (m+1)>>1; j > 0; i+=2, j--)
    1468              :   {
    1469          224 :     gel(V,i)   = stoi(1-j);
    1470          224 :     gel(V,i+1) = stoi(1-j+1);
    1471              :   }
    1472          140 :   return V;
    1473              : }
    1474              : 
    1475              : static GEN
    1476        86434 : ellsympow_trace(GEN p, GEN t, long m)
    1477              : {
    1478        86434 :   long k, n = m >> 1;
    1479        86434 :   GEN tp = gpowers0(sqri(t), n, odd(m)? t: NULL);
    1480        86555 :   GEN pp = gen_1, b = gen_1, r = gel(tp,n+1);
    1481       245647 :   for(k=1; k<=n; k++)
    1482              :   {
    1483              :     GEN s;
    1484       159365 :     pp = mulii(pp, p);
    1485       159288 :     b  = diviuexact(muliu(b, (m-(2*k-1))*(m-(2*k-2))), k*(m-(k-1)));
    1486       158622 :     s = mulii(mulii(b, gel(tp,1+n-k)), pp);
    1487       158974 :     r = odd(k) ? subii(r, s): addii(r, s);
    1488              :   }
    1489        86282 :   return r;
    1490              : }
    1491              : 
    1492              : static GEN
    1493         3129 : ellsympow_abelian(GEN p, GEN ap, long m, long o)
    1494              : {
    1495         3129 :   pari_sp av = avma;
    1496         3129 :   long i, M, n = (m+1)>>1;
    1497              :   GEN pk, tv, pn, pm, F, v;
    1498         3129 :   if (!odd(o))
    1499              :   {
    1500            0 :     if (odd(m)) return pol_1(0);
    1501            0 :     M = m >> 1; o >>= 1;
    1502              :   }
    1503              :   else
    1504         3129 :     M = m * ((o+1) >> 1);
    1505         3129 :   pk = gpowers(p,n); pn = gel(pk,n+1);
    1506         3129 :   tv = cgetg(m+2,t_VEC);
    1507         3129 :   gel(tv, 1) = gen_2;
    1508         3129 :   gel(tv, 2) = ap;
    1509        10668 :   for (i = 3; i <= m+1; i++)
    1510         7539 :     gel(tv,i) = subii(mulii(ap,gel(tv,i-1)), mulii(p,gel(tv,i-2)));
    1511         3129 :   pm = odd(m)? mulii(gel(pk,n), pn): sqri(pn); /* cheap p^m */
    1512         3129 :   F = deg2pol_shallow(pm, gen_0, gen_1, 0);
    1513         3129 :   v = odd(m) ? pol_1(0): deg1pol_shallow(negi(pn), gen_1, 0);
    1514         9450 :   for (i = M % o; i < n; i += o) /* o | m-2*i */
    1515              :   {
    1516         6321 :     gel(F,3) = negi(mulii(gel(tv,m-2*i+1), gel(pk,i+1)));
    1517         6321 :     v = ZX_mul(v, F);
    1518              :   }
    1519         3129 :   return gc_GEN(av, v);
    1520              : }
    1521              : 
    1522              : static GEN
    1523        89564 : ellsympow(GEN E, ulong m, GEN p, long n)
    1524              : {
    1525        89564 :   pari_sp av = avma;
    1526        89564 :   GEN ap = ellap(E, p);
    1527        89500 :   if (n <= 2)
    1528              :   {
    1529        86399 :     GEN t = ellsympow_trace(p, ap, m);
    1530        86281 :     return deg1pol_shallow(t, gen_1, 0);
    1531              :   }
    1532              :   else
    1533         3101 :     return gc_upto(av, RgXn_inv_i(ellsympow_abelian(p, ap, m, 1), n));
    1534              : }
    1535              : 
    1536              : GEN
    1537         5629 : direllsympow_worker(GEN P, ulong X, GEN E, ulong m)
    1538              : {
    1539         5629 :   pari_sp av = avma;
    1540         5629 :   long i, l = lg(P);
    1541         5629 :   GEN W = cgetg(l, t_VEC);
    1542        95191 :   for(i = 1; i < l; i++)
    1543              :   {
    1544        89557 :     ulong p = uel(P,i);
    1545        89557 :     long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */
    1546        89551 :     gel(W,i) = ellsympow(E, m, utoi(uel(P,i)), d);
    1547              :   }
    1548         5634 :   return gc_GEN(av, mkvec2(P,W));
    1549              : }
    1550              : 
    1551              : static GEN
    1552           56 : eulerf_bad(GEN bad, GEN p)
    1553              : {
    1554           56 :   long i, l = lg(bad);
    1555          112 :   for (i = 1; i < l; i++)
    1556           56 :     if (equalii(gmael(bad,i,1), p))
    1557            0 :       return gmael(bad,i,2);
    1558           56 :   return NULL;
    1559              : }
    1560              : 
    1561              : static GEN
    1562          343 : vecan_ellsympow(GEN an, long n)
    1563              : {
    1564          343 :   GEN nn = utoi(n), crvm = gel(an,1), bad = gel(an,2);
    1565          343 :   GEN worker = snm_closure(is_entry("_direllsympow_worker"), crvm);
    1566          343 :   return pardireuler(worker, gen_2, nn, nn, bad);
    1567              : }
    1568              : 
    1569              : static GEN
    1570           28 : eulerf_ellsympow(GEN an, GEN p)
    1571              : {
    1572           28 :   GEN crvm = gel(an,1), bad = gel(an,2), E = gel(crvm,1);
    1573           28 :   GEN f = eulerf_bad(bad, p);
    1574           28 :   if (f) return f;
    1575           28 :   retmkrfrac(gen_1,ellsympow_abelian(p, ellap(E, p), itos(gel(crvm,2)), 1));
    1576              : }
    1577              : 
    1578              : static long
    1579          196 : ellsympow_betam(long o, long m)
    1580              : {
    1581          196 :   const long c3[]={3, -1, 1};
    1582          196 :   const long c12[]={6, -2, 2, 0, 4, -4};
    1583          196 :   const long c24[]={12, -2, -4, 6, 4, -10};
    1584          196 :   if (!odd(o) && odd(m)) return 0;
    1585          161 :   switch(o)
    1586              :   {
    1587            0 :     case 1:  return m+1;
    1588           14 :     case 2:  return m+1;
    1589           84 :     case 3:  case 6: return (m+c3[m%3])/3;
    1590            0 :     case 4:  return m%4 == 0 ? (m+2)/2: m/2;
    1591           21 :     case 8:  return m%4 == 0 ? (m+4)/4: (m-2)/4;
    1592           35 :     case 12: return (m+c12[(m%12)/2])/6;
    1593            7 :     case 24: return (m+c24[(m%12)/2])/12;
    1594              :   }
    1595            0 :   return 0;
    1596              : }
    1597              : 
    1598              : static long
    1599           98 : ellsympow_epsm(long o, long m) { return m + 1 - ellsympow_betam(o, m); }
    1600              : 
    1601              : static GEN
    1602           98 : ellsympow_multred(GEN E, GEN p, long m, long vN, long *cnd, long *w)
    1603              : {
    1604           98 :   if (vN == 1 || !odd(m))
    1605              :   {
    1606           98 :     GEN s = (odd(m) && signe(ellap(E,p)) < 0)? gen_1: gen_m1;
    1607           98 :     *cnd = m;
    1608           98 :     *w = odd(m)? ellrootno(E, p): 1;
    1609           98 :     return deg1pol_shallow(s, gen_1, 0);
    1610              :   }
    1611              :   else
    1612              :   {
    1613            0 :     *cnd = equaliu(p,2)? ((m+1)>>1) * vN: m+1;
    1614            0 :     *w = (m & 3) == 1? ellrootno(E, p): 1;
    1615            0 :     return pol_1(0);
    1616              :   }
    1617              : }
    1618              : 
    1619              : static GEN
    1620           98 : ellsympow_nonabelian(GEN p, long m, long bet)
    1621              : {
    1622           98 :  GEN q = powiu(p, m >> 1), q2 = sqri(q), F;
    1623           98 :  if (odd(m))
    1624              :  {
    1625           35 :    q2 = mulii(q2, p); /* p^m */
    1626           35 :    return gpowgs(deg2pol_shallow(q2, gen_0, gen_1, 0), bet>>1);
    1627              :  }
    1628           63 :  togglesign_safe(&q2);
    1629           63 :  F = gpowgs(deg2pol_shallow(q2, gen_0, gen_1, 0), bet>>1);
    1630           63 :  if (!odd(bet)) return F;
    1631           28 :  if (m%4 != 2) togglesign_safe(&q);
    1632           28 :  return gmul(F, deg1pol_shallow(q, gen_1, 0));
    1633              : }
    1634              : 
    1635              : static long
    1636            0 : safe_Z_pvalrem(GEN n, GEN p, GEN *pr)
    1637            0 : { return signe(n)==0? -1: Z_pvalrem(n, p, pr); }
    1638              : 
    1639              : static GEN
    1640            0 : c4c6_ap(GEN c4, GEN c6, GEN p)
    1641              : {
    1642            0 :   GEN N = Fp_ellcard(Fp_muls(c4, -27, p), Fp_muls(c6, -54, p), p);
    1643            0 :   return subii(addiu(p, 1), N);
    1644              : }
    1645              : 
    1646              : static GEN
    1647            0 : ellsympow_abelian_twist(GEN E, GEN p, long m, long o)
    1648              : {
    1649            0 :   GEN ap, c4t, c6t, c4 = ell_get_c4(E), c6 = ell_get_c6(E);
    1650            0 :   long v4 = safe_Z_pvalrem(c4, p, &c4t);
    1651            0 :   long v6 = safe_Z_pvalrem(c6, p, &c6t);
    1652            0 :   if (v6>=0 && (v4==-1 || 3*v4>=2*v6)) c6 = c6t;
    1653            0 :   if (v4>=0 && (v6==-1 || 3*v4<=2*v6)) c4 = c4t;
    1654            0 :   ap = c4c6_ap(c4, c6, p);
    1655            0 :   return ellsympow_abelian(p, ap, m, o);
    1656              : }
    1657              : 
    1658              : static GEN
    1659            0 : ellsympow_goodred(GEN E, GEN p, long m, long *cnd, long *w)
    1660              : {
    1661            0 :   long o = 12/cgcd(12, Z_pval(ell_get_disc(E), p));
    1662            0 :   long bet = ellsympow_betam(o, m);
    1663            0 :   long eps = m + 1 - bet;
    1664            0 :   *w = odd(m) && odd(eps>>1) ? ellrootno(E,p): 1;
    1665            0 :   *cnd = eps;
    1666            0 :   if (umodiu(p, o) == 1)
    1667            0 :     return ellsympow_abelian_twist(E, p, m, o);
    1668              :   else
    1669            0 :     return ellsympow_nonabelian(p, m, bet);
    1670              : }
    1671              : 
    1672              : static long
    1673           70 : ellsympow_inertia3(GEN E, long vN)
    1674              : {
    1675           70 :   long vD = Z_lval(ell_get_disc(E), 3);
    1676           70 :   if (vN==2) return vD%2==0 ? 2: 4;
    1677           70 :   if (vN==4) return vD%4==0 ? 3: 6;
    1678           70 :   if (vN==3 || vN==5) return 12;
    1679            0 :   return 0;
    1680              : }
    1681              : 
    1682              : static long
    1683           70 : ellsympow_deltam3(long o, long m, long vN)
    1684              : {
    1685           70 :   if (o==3 || o==6) return ellsympow_epsm(3, m);
    1686           70 :   if (o==12 && vN ==3) return (ellsympow_epsm(3, m))/2;
    1687            0 :   if (o==12 && vN ==5) return (ellsympow_epsm(3, m))*3/2;
    1688            0 :   return 0;
    1689              : }
    1690              : 
    1691              : static long
    1692            0 : ellsympow_isabelian3(GEN E)
    1693              : {
    1694            0 :   ulong c4 = umodiu(ell_get_c4(E),81), c6 = umodiu(ell_get_c6(E), 243);
    1695            0 :   return (c4 == 27 || (c4%27==9 && (c6==108 || c6==135)));
    1696              : }
    1697              : 
    1698              : static long
    1699           35 : ellsympow_rootno3(GEN E, GEN p, long o, long m)
    1700              : {
    1701           35 :   const long  w6p[]={1,-1,-1,-1,1,1};
    1702           35 :   const long  w6n[]={-1,1,-1,1,-1,1};
    1703           35 :   const long w12p[]={1,1,-1,1,1,1};
    1704           35 :   const long w12n[]={-1,-1,-1,-1,-1,1};
    1705           35 :   long w = ellrootno(E, p), mm = (m%12)>>1;
    1706           35 :   switch(o)
    1707              :   {
    1708            0 :     case 2: return m%4== 1 ? -1: 1;
    1709            0 :     case 6:  return w == 1 ? w6p[mm]: w6n[mm];
    1710           35 :     case 12: return w == 1 ? w12p[mm]: w12n[mm];
    1711            0 :     default: return 1;
    1712              :   }
    1713              : }
    1714              : 
    1715              : static GEN
    1716           70 : ellsympow_goodred3(GEN E, GEN F, GEN p, long m, long vN, long *cnd, long *w)
    1717              : {
    1718           70 :   long o = ellsympow_inertia3(E, vN);
    1719           70 :   long bet = ellsympow_betam(o, m);
    1720           70 :   *cnd = m + 1 - bet + ellsympow_deltam3(o, m, vN);
    1721           70 :   *w = odd(m)? ellsympow_rootno3(E, p, o, m): 1;
    1722           70 :   if (o==1 || o==2)
    1723            0 :     return ellsympow_abelian(p, ellap(F, p), m, o);
    1724           70 :   if ((o==3 || o==6) && ellsympow_isabelian3(F))
    1725            0 :     return ellsympow_abelian(p, p, m, o);
    1726              :   else
    1727           70 :     return ellsympow_nonabelian(p, m, bet);
    1728              : }
    1729              : 
    1730              : static long
    1731           28 : ellsympow_inertia2(GEN F, long vN)
    1732              : {
    1733           28 :   long vM = itos(gel(elllocalred(F, gen_2),1));
    1734           28 :   GEN c6 = ell_get_c6(F);
    1735           28 :   long v6 = signe(c6) ? vali(c6): 24;
    1736           28 :   if (vM==0) return vN==0 ? 1: 2;
    1737           28 :   if (vM==2) return vN==2 ? 3: 6;
    1738           14 :   if (vM==5) return 8;
    1739            7 :   if (vM==8) return v6>=9? 8: 4;
    1740            7 :   if (vM==3 || vN==7) return 24;
    1741            0 :   return 0;
    1742              : }
    1743              : 
    1744              : static long
    1745           28 : ellsympow_deltam2(long o, long m, long vN)
    1746              : {
    1747           28 :   if ((o==2 || o==6) && vN==4) return ellsympow_epsm(2, m);
    1748           28 :   if ((o==2 || o==6) && vN==6) return 2*ellsympow_epsm(2, m);
    1749           28 :   if (o==4) return 2*ellsympow_epsm(4, m)+ellsympow_epsm(2, m);
    1750           28 :   if (o==8 && vN==5) return ellsympow_epsm(8, m)+ellsympow_epsm(2, m)/2;
    1751           21 :   if (o==8 && vN==6) return ellsympow_epsm(8, m)+ellsympow_epsm(2, m);
    1752           21 :   if (o==8 && vN==8) return ellsympow_epsm(8, m)+ellsympow_epsm(4, m)+ellsympow_epsm(2, m);
    1753           21 :   if (o==24 && vN==3) return (2*ellsympow_epsm(8, m)+ellsympow_epsm(2, m))/6;
    1754           14 :   if (o==24 && vN==4) return (ellsympow_epsm(8, m)+ellsympow_epsm(2, m)*2)/3;
    1755           14 :   if (o==24 && vN==6) return (ellsympow_epsm(8, m)+ellsympow_epsm(2, m)*5)/3;
    1756           14 :   if (o==24 && vN==7) return (ellsympow_epsm(8, m)*10+ellsympow_epsm(2, m)*5)/6;
    1757           14 :   return 0;
    1758              : }
    1759              : 
    1760              : static long
    1761            0 : ellsympow_isabelian2(GEN F)
    1762            0 : { return umodi2n(ell_get_c4(F),7) == 96; }
    1763              : 
    1764              : static long
    1765            0 : ellsympow_rootno2(GEN E, long vN, long m, long bet)
    1766              : {
    1767            0 :   long eps2 = (m + 1 - bet)>>1;
    1768            0 :   long eta = odd(vN) && m%8==3 ? -1 : 1;
    1769            0 :   long w2 = odd(eps2) ? ellrootno(E, gen_2): 1;
    1770            0 :   return eta == w2 ? 1 : -1;
    1771              : }
    1772              : 
    1773              : static GEN
    1774           28 : ellsympow_goodred2(GEN E, GEN F, GEN p, long m, long vN, long *cnd, long *w)
    1775              : {
    1776           28 :   long o = ellsympow_inertia2(F, vN);
    1777           28 :   long bet = ellsympow_betam(o, m);
    1778           28 :   *cnd = m + 1 - bet + ellsympow_deltam2(o, m, vN);
    1779           28 :   *w = odd(m) ? ellsympow_rootno2(E, vN, m, bet): 1;
    1780           28 :   if (o==1 || o==2)
    1781            0 :     return ellsympow_abelian(p, ellap(F, p), m, o);
    1782           28 :   if (o==4 && ellsympow_isabelian2(F))
    1783            0 :     return ellsympow_abelian(p, p, m, o);
    1784              :   else
    1785           28 :     return ellsympow_nonabelian(p, m, bet);
    1786              : }
    1787              : 
    1788              : static GEN
    1789          189 : ellminimaldotwist(GEN E, GEN *pD)
    1790              : {
    1791          189 :   GEN D = ellminimaltwistcond(E), Et = elltwist(E, D), Etmin;
    1792          189 :   if (pD) *pD = D;
    1793          189 :   Etmin = ellminimalmodel(Et, NULL);
    1794          189 :   obj_free(Et); return Etmin;
    1795              : }
    1796              : 
    1797              : /* Based on
    1798              : Symmetric powers of elliptic curve L-functions,
    1799              : Phil Martin and Mark Watkins, ANTS VII
    1800              : <http://magma.maths.usyd.edu.au/users/watkins/papers/antsVII.pdf>
    1801              : with thanks to Mark Watkins. BA20180402
    1802              : */
    1803              : static GEN
    1804          140 : lfunellsympow(GEN e, ulong m)
    1805              : {
    1806          140 :   pari_sp av = avma;
    1807              :   GEN B, N, Nfa, pr, ex, ld, bad, ejd, et, pole;
    1808          140 :   long i, l, mero, w = (m&7)==1 || (m&7)==3 ? -1: 1;
    1809          140 :   checkell_Q(e);
    1810          140 :   e = ellminimalmodel(e, NULL);
    1811          140 :   ejd = Q_denom(ell_get_j(e));
    1812          140 :   mero = m==0 || (m%4==0 && ellQ_get_CM(e)<0);
    1813          140 :   ellQ_get_Nfa(e, &N, &Nfa);
    1814          140 :   pr = gel(Nfa,1);
    1815          140 :   ex = gel(Nfa,2); l = lg(pr);
    1816          140 :   if (ugcdiu(N,6) == 1)
    1817           21 :     et = NULL;
    1818              :   else
    1819          119 :     et = ellminimaldotwist(e, NULL);
    1820          140 :   B = gen_1;
    1821          140 :   bad = cgetg(l, t_VEC);
    1822          336 :   for (i=1; i<l; i++)
    1823              :   {
    1824          196 :     long vN = itos(gel(ex,i));
    1825          196 :     GEN p = gel(pr,i), eul;
    1826              :     long cnd, wp;
    1827          196 :     if (dvdii(ejd, p))
    1828           98 :       eul = ellsympow_multred(e, p, m, vN, &cnd, &wp);
    1829           98 :     else if (equaliu(p, 2))
    1830           28 :       eul = ellsympow_goodred2(e, et, p, m, vN, &cnd, &wp);
    1831           70 :     else if (equaliu(p, 3))
    1832           70 :       eul = ellsympow_goodred3(e, et, p, m, vN, &cnd, &wp);
    1833              :     else
    1834            0 :       eul = ellsympow_goodred(e, p, m, &cnd, &wp);
    1835          196 :     gel(bad, i) = mkvec2(p, ginv(eul));
    1836          196 :     B = mulii(B, powiu(p,cnd));
    1837          196 :     w *= wp;
    1838              :   }
    1839          140 :   pole = mero ? mkvec(mkvec2(stoi(1+(m>>1)),gen_0)): NULL;
    1840          280 :   ld = mkvecn(mero? 7: 6, tag(mkvec2(mkvec2(e,utoi(m)),bad), t_LFUN_SYMPOW_ELL),
    1841          140 :         gen_0, ellsympow_gamma(m), stoi(m+1), B, stoi(w), pole);
    1842          140 :   if (et) obj_free(et);
    1843          140 :   return gc_GEN(av, ld);
    1844              : }
    1845              : 
    1846              : GEN
    1847           70 : lfunsympow(GEN ldata, ulong m)
    1848              : {
    1849           70 :   ldata = lfunmisc_to_ldata_shallow(ldata);
    1850           70 :   if (ldata_get_type(ldata) != t_LFUN_ELL)
    1851            0 :     pari_err_IMPL("lfunsympow");
    1852           70 :   return lfunellsympow(gel(ldata_get_an(ldata), 2), m);
    1853              : }
    1854              : 
    1855              : static GEN
    1856          133 : check_0(GEN z, long bit) { return gexpo(z) < -bit? gen_0: z; }
    1857              : static GEN
    1858          133 : check_real(GEN z, long bit)
    1859              : {
    1860          133 :   if (typ(z) != t_COMPLEX) return check_0(z, bit);
    1861            0 :   if (check_0(gel(z,2), bit) != gen_0) pari_err_BUG("lfunmfspec");
    1862            0 :   return check_0(gel(z,1), bit);
    1863              : }
    1864              : static GEN
    1865           42 : lfunmfspec_i(GEN lmisc, long bit)
    1866              : {
    1867              :   GEN linit, ldataf, v, ve, vo, om, op, B, dom;
    1868              :   long k, k2, bit2, j;
    1869              : 
    1870           42 :   ldataf = lfunmisc_to_ldata_shallow(lmisc);
    1871           42 :   if (!gequal(ldata_get_gammavec(ldataf), mkvec2(gen_0,gen_1)))
    1872            0 :     pari_err_TYPE("lfunmfspec", lmisc);
    1873           42 :   k = gtos(ldata_get_k(ldataf));
    1874           42 :   if (k == 1) return mkvec2(cgetg(1, t_VEC), gen_1);
    1875           35 :   dom = mkvec3(dbltor(k/2.), dbltor((k-2)/2.), gen_0);
    1876           35 :   if (is_linit(lmisc) && linit_get_type(lmisc) == t_LDESC_INIT
    1877            0 :       && sdomain_isincl((double)k, dom, lfun_get_dom(linit_get_tech(lmisc))))
    1878            0 :     linit = lmisc;
    1879              :   else
    1880           35 :     linit = lfuninit(ldataf, dom, 0, bit);
    1881           35 :   B = int2n(bit/4);
    1882           35 :   v = cgetg(k, t_VEC);
    1883          238 :   for (j = 1; j < k; j++) gel(v,j) = lfunlambda(linit, utoi(j), bit);
    1884           35 :   om = gel(v,1);
    1885           35 :   if (odd(k)) return mkvec2(bestappr(gdiv(v, om), B), om);
    1886              : 
    1887           21 :   k2 = k/2; bit2 = bit/2;
    1888           21 :   ve = cgetg(k2, t_VEC);
    1889           21 :   vo = cgetg(k2+1, t_VEC);
    1890           21 :   gel(vo,1) = check_real(gel(v,1), bit2);
    1891           77 :   for (j = 1; j < k2; j++)
    1892              :   {
    1893           56 :     gel(ve,j)   = check_real(gel(v,2*j), bit2);
    1894           56 :     gel(vo,j+1) = check_real(gel(v,2*j+1), bit2);
    1895              :   }
    1896           21 :   if (k2 == 1) { om = gen_1; op = gel(vo,1); }
    1897              :   else
    1898              :   {
    1899           21 :     om = gel(ve,1); if (om != gen_0) ve = gdiv(ve, om);
    1900           21 :     op = gel(vo,2);
    1901           21 :     if (gexpo(op) < -bit2) op = gel(vo,1); /* should happen only in weight 6 */
    1902           21 :     if (op != gen_0) vo = gdiv(vo, op);
    1903              :   }
    1904           21 :   return mkvec4(bestappr(ve,B), bestappr(vo,B), om, op);
    1905              : }
    1906              : GEN
    1907           42 : lfunmfspec(GEN lmisc, long bit)
    1908              : {
    1909           42 :   pari_sp av = avma;
    1910           42 :   return gc_GEN(av, lfunmfspec_i(lmisc, bit));
    1911              : }
    1912              : 
    1913              : static long
    1914           28 : ellsymsq_bad2(GEN c4, GEN c6, long e)
    1915              : {
    1916           28 :   switch (e)
    1917              :   {
    1918           14 :     case 2: return 1;
    1919            7 :     case 3: return 0;
    1920            7 :     case 5: return 0;
    1921            0 :     case 7: return 0;
    1922            0 :     case 8:
    1923            0 :       if (!umodi2n(c6,9)) return 0;
    1924            0 :       return umodi2n(c4,7)==32 ? 1 : -1;
    1925            0 :     default: return 0;
    1926              :   }
    1927              : }
    1928              : static long
    1929           14 : ellsymsq_bad3(GEN c4, GEN c6, long e)
    1930              : {
    1931              :   long c6_243, c4_81;
    1932           14 :   switch (e)
    1933              :   {
    1934            0 :     case 2: return 1;
    1935           14 :     case 3: return 0;
    1936            0 :     case 5: return 0;
    1937            0 :     case 4:
    1938            0 :       c4_81 = umodiu(c4,81);
    1939            0 :       if (c4_81 == 27) return -1;
    1940            0 :       if (c4_81%27 != 9) return 1;
    1941            0 :       c6_243 = umodiu(c6,243);
    1942            0 :       return (c6_243==108 || c6_243==135)? -1: 1;
    1943            0 :     default: return 0;
    1944              :   }
    1945              : }
    1946              : static int
    1947            0 : c4c6_testp(GEN c4, GEN c6, GEN p)
    1948            0 : { GEN p2 = sqri(p); return (dvdii(c6,p2) && !dvdii(c4,p2)); }
    1949              : /* assume e = v_p(N) >= 2 */
    1950              : static long
    1951           42 : ellsymsq_badp(GEN c4, GEN c6, GEN p, long e)
    1952              : {
    1953           42 :   if (absequaliu(p, 2)) return ellsymsq_bad2(c4, c6, e);
    1954           14 :   if (absequaliu(p, 3)) return ellsymsq_bad3(c4, c6, e);
    1955            0 :   switch(umodiu(p, 12UL))
    1956              :   {
    1957            0 :     case 1: return -1;
    1958            0 :     case 5: return c4c6_testp(c4,c6,p)? -1: 1;
    1959            0 :     case 7: return c4c6_testp(c4,c6,p)?  1:-1;
    1960            0 :     default:return 1; /* p%12 = 11 */
    1961              :   }
    1962              : }
    1963              : static GEN
    1964           70 : lfunellsymsqmintwist(GEN e)
    1965              : {
    1966           70 :   pari_sp av = avma;
    1967              :   GEN N, Nfa, P, E, V, c4, c6, ld;
    1968              :   long i, l, k;
    1969           70 :   checkell_Q(e);
    1970           70 :   e = ellminimalmodel(e, NULL);
    1971           70 :   ellQ_get_Nfa(e, &N, &Nfa);
    1972           70 :   c4 = ell_get_c4(e);
    1973           70 :   c6 = ell_get_c6(e);
    1974           70 :   P = gel(Nfa,1); l = lg(P);
    1975           70 :   E = gel(Nfa,2);
    1976           70 :   V = cgetg(l, t_VEC);
    1977          196 :   for (i=k=1; i<l; i++)
    1978              :   {
    1979          126 :     GEN p = gel(P,i);
    1980          126 :     long a, e = itos(gel(E,i));
    1981          126 :     if (e == 1) continue;
    1982           42 :     a = ellsymsq_badp(c4, c6, p, e);
    1983           42 :     gel(V,k++) = mkvec2(p, stoi(a));
    1984              :   }
    1985           70 :   setlg(V, k);
    1986           70 :   ld = lfunellsympow(e, 2);
    1987           70 :   return gc_GEN(av, mkvec2(ld, V));
    1988              : }
    1989              : 
    1990              : static GEN
    1991           70 : mfpeters(GEN ldata2, GEN fudge, GEN N, long k, long bitprec)
    1992              : {
    1993           70 :   GEN t, L = real_i(lfun(ldata2, stoi(k), bitprec));
    1994           70 :   long prec = nbits2prec(bitprec);
    1995           70 :   t = powrs(mppi(prec), k+1); shiftr_inplace(t, 2*k-1); /* Pi/2 * (4Pi)^k */
    1996           70 :   return gmul(gdiv(gmul(mulii(N,mpfact(k-1)), fudge), t), L);
    1997              : }
    1998              : 
    1999              : /* Assume E to be twist-minimal */
    2000              : static GEN
    2001           70 : lfunellmfpetersmintwist(GEN E, long bitprec)
    2002              : {
    2003           70 :   pari_sp av = avma;
    2004           70 :   GEN symsq, veceuler, N = ellQ_get_N(E), fudge = gen_1;
    2005           70 :   long j, k = 2;
    2006           70 :   symsq = lfunellsymsqmintwist(E);
    2007           70 :   veceuler = gel(symsq,2);
    2008          112 :   for (j = 1; j < lg(veceuler); j++)
    2009              :   {
    2010           42 :     GEN v = gel(veceuler,j), p = gel(v,1), q = powis(p,1-k);
    2011           42 :     long s = signe(gel(v,2));
    2012           42 :     if (s) fudge = gmul(fudge, s==1 ? gaddsg(1, q): gsubsg(1, q));
    2013              :   }
    2014           70 :   return gc_upto(av, mfpeters(gel(symsq,1),fudge,N,k,bitprec));
    2015              : }
    2016              : 
    2017              : /* From Christophe Delaunay, http://delaunay.perso.math.cnrs.fr/these.pdf */
    2018              : static GEN
    2019           70 : elldiscfix(GEN E, GEN Et, GEN D)
    2020              : {
    2021           70 :   GEN N = ellQ_get_N(E), Nt = ellQ_get_N(Et);
    2022           70 :   GEN P = gel(absZ_factor(D), 1);
    2023           70 :   GEN f = gen_1;
    2024           70 :   long i, l = lg(P);
    2025          133 :   for (i=1; i < l; i++)
    2026              :   {
    2027           63 :     GEN r, p = gel(P,i);
    2028           63 :     long v = Z_pval(N, p), vt = Z_pval(Nt, p);
    2029           63 :     if (v <= vt) continue;
    2030              :     /* v > vt */
    2031           49 :     if (absequaliu(p, 2))
    2032              :     {
    2033           28 :       if (vt == 0 && v >= 4)
    2034            0 :         r = shifti(subsi(9, sqri(ellap(Et, p))), v-3);  /* 9=(2+1)^2 */
    2035           28 :       else if (vt == 1)
    2036            7 :         r = gmul2n(utoipos(3), v-3);  /* not in Z if v=2 */
    2037           21 :       else if (vt >= 2)
    2038           21 :         r = int2n(v-vt);
    2039              :       else
    2040            0 :         r = gen_1; /* vt = 0, 1 <= v <= 3 */
    2041              :     }
    2042           21 :     else if (vt >= 1)
    2043           14 :       r = gdiv(subiu(sqri(p), 1), p);
    2044              :     else
    2045            7 :       r = gdiv(mulii(subiu(p, 1), subii(sqri(addiu(p, 1)), sqri(ellap(Et, p)))), p);
    2046           49 :     f = gmul(f, r);
    2047              :   }
    2048           70 :   return f;
    2049              : }
    2050              : 
    2051              : GEN
    2052           70 : lfunellmfpeters(GEN E, long bitprec)
    2053              : {
    2054           70 :   pari_sp ltop = avma;
    2055           70 :   GEN D, Et = ellminimaldotwist(E, &D);
    2056           70 :   GEN nor = lfunellmfpetersmintwist(Et, bitprec);
    2057           70 :   GEN nor2 = gmul(nor, elldiscfix(E, Et, D));
    2058           70 :   obj_free(Et); return gc_upto(ltop, nor2);
    2059              : }
    2060              : 
    2061              : /*************************************************************/
    2062              : /*               Genus 2 curves                              */
    2063              : /*************************************************************/
    2064              : 
    2065              : static GEN
    2066            0 : eulerf_genus2(GEN an, GEN p)
    2067              : {
    2068            0 :   GEN Q = gel(an,1), bad = gel(an, 2);
    2069            0 :   GEN f = eulerf_bad(bad, p);
    2070            0 :   if (f) return f;
    2071            0 :   f = RgX_recip(hyperellcharpoly(gmul(Q,gmodulo(gen_1, p))));
    2072            0 :   return mkrfrac(gen_1,f);
    2073              : }
    2074              : 
    2075              : GEN
    2076          392 : lfungenus2(GEN G)
    2077              : {
    2078          392 :   pari_sp ltop = avma;
    2079              :   GEN Ldata;
    2080          392 :   GEN gr = genus2red(G, NULL);
    2081          392 :   GEN N  = gel(gr, 1), M = gel(gr, 2), PQ = gel(gr, 3), L = gel(gr, 4);
    2082          392 :   GEN e, F = gadd(gsqr(gel(PQ, 2)), gmul2n(gel(PQ, 1), 2));
    2083          392 :   long i, lL = lg(L), ram2;
    2084          392 :   ram2 = absequaliu(gmael(M,1,1),2);
    2085          392 :   if (ram2 && equalis(gmael(M,2,1),-1))
    2086          189 :     pari_warn(warner,"unknown valuation of conductor at 2");
    2087          392 :   e = cgetg(lL+(ram2?0:1), t_VEC);
    2088          567 :   gel(e,1) = mkvec2(gen_2, ram2 ? ginv(RgX_recip(genus2_eulerfact2(PQ)))
    2089          175 :            : ginv(RgX_recip(hyperellcharpoly(gmul(PQ,gmodulss(1,2))))) );
    2090          938 :   for(i = ram2? 2: 1; i < lL; i++)
    2091              :   {
    2092          546 :     GEN Li = gel(L, i);
    2093          546 :     GEN p = gel(Li, 1), r = gel(Li, 4);
    2094          546 :     gel(e, ram2 ? i: i+1) = mkvec2(p, ginv(RgX_recip(genus2_eulerfact(F,p, r[1],r[2]))));
    2095              :   }
    2096          392 :   Ldata = mkvecn(6, tag(mkvec2(F,e), t_LFUN_GENUS2),
    2097              :       gen_0, mkvec4(gen_0, gen_0, gen_1, gen_1), gen_2, N, gen_0);
    2098          392 :   return gc_GEN(ltop, Ldata);
    2099              : }
    2100              : 
    2101              : /*************************************************************/
    2102              : /*                        ETA QUOTIENTS                      */
    2103              : /* An eta quotient is a matrix with 2 columns [m, r_m] with  */
    2104              : /* m >= 1 representing f(\tau)=\prod_m\eta(m\tau)^{r_m}.     */
    2105              : /*************************************************************/
    2106              : 
    2107              : /* eta(x^v) + O(x^L) */
    2108              : GEN
    2109         1222 : eta_ZXn(long v, long L)
    2110              : {
    2111         1222 :   long n, k = 0, v2 = 2*v, bn = v, cn = 0;
    2112              :   GEN P;
    2113         1222 :   if (!L) return zeropol(0);
    2114         1222 :   P = cgetg(L+2,t_POL); P[1] = evalsigne(1);
    2115        72543 :   for(n = 0; n < L; n++) gel(P,n+2) = gen_0;
    2116         1222 :   for(n = 0;; n++, bn += v2, cn += v)
    2117         3000 :   { /* k = v * (3*n-1) * n / 2; bn = v * (2*n+1); cn = v * n */
    2118              :     long k2;
    2119         4222 :     gel(P, k+2) = odd(n)? gen_m1: gen_1;
    2120         4222 :     k2 = k+cn; if (k2 >= L) break;
    2121         3770 :     k = k2;
    2122              :     /* k = v * (3*n+1) * n / 2 */;
    2123         3770 :     gel(P, k+2) = odd(n)? gen_m1: gen_1;
    2124         3770 :     k2 = k+bn; if (k2 >= L) break;
    2125         3000 :     k = k2;
    2126              :   }
    2127         1222 :   setlg(P, k+3); return P;
    2128              : }
    2129              : GEN
    2130          322 : eta_product_ZXn(GEN eta, long L)
    2131              : {
    2132          322 :   pari_sp av = avma;
    2133          322 :   GEN P = NULL, D = gel(eta,1), R = gel(eta,2);
    2134          322 :   long i, l = lg(D);
    2135         1148 :   for (i = 1; i < l; ++i)
    2136              :   {
    2137          826 :     GEN Q = eta_ZXn(D[i], L);
    2138          826 :     long r = R[i];
    2139          826 :     if (r < 0) { Q = RgXn_inv_i(Q, L); r = -r; }
    2140          826 :     if (r != 1) Q = RgXn_powu_i(Q, r, L);
    2141          826 :     P = P? ZXn_mul(P, Q, L): Q;
    2142          826 :     if (gc_needed(av,1) && i > 1)
    2143              :     {
    2144            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"eta_product_ZXn");
    2145            0 :       P = gc_GEN(av, P);
    2146              :     }
    2147              :   }
    2148          322 :   return P;
    2149              : }
    2150              : static GEN
    2151          147 : vecan_eta(GEN an, long L)
    2152              : {
    2153          147 :   long v = itos(gel(an, 3));
    2154              :   GEN t;
    2155          147 :   if (v > L) return zerovec(L);
    2156          140 :   t = eta_product_ZXn(an, L - v);
    2157          140 :   if (v) t = RgX_shift_shallow(t, v);
    2158          140 :   return RgX_to_RgV(t, L);
    2159              : }
    2160              : /* return 1 if cuspidal, 0 if holomorphic, -1 otherwise */
    2161              : static int
    2162          231 : etacuspidal(GEN N, GEN k, GEN B, GEN R, GEN NB)
    2163              : {
    2164          231 :   long i, j, lD, l, cusp = 1;
    2165          231 :   pari_sp av = avma;
    2166              :   GEN D;
    2167          231 :   if (gsigne(k) < 0) return -1;
    2168          224 :   D = divisors(N); lD = lg(D); l = lg(B);
    2169         1505 :   for (i = 1; i < lD; i++)
    2170              :   {
    2171         1281 :     GEN t = gen_0, d = gel(D,i);
    2172              :     long s;
    2173         3997 :     for (j = 1; j < l; j++)
    2174         2716 :       t = addii(t, mulii(gel(NB,j), mulii(gel(R,j), sqri(gcdii(d, gel(B,j))))));
    2175         1281 :     s = signe(t);
    2176         1281 :     if (s < 0) return -1;
    2177         1281 :     if (!s) cusp = 0;
    2178              :   }
    2179          224 :   return gc_bool(av, cusp);
    2180              : }
    2181              : /* u | 24, level N = u*N0, N0 = lcm(B), NB[i] = N0/B[i] */
    2182              : static int
    2183           49 : etaselfdual(GEN B, GEN R, GEN NB, ulong u)
    2184              : {
    2185           49 :   pari_sp av = avma;
    2186           49 :   long i, l = lg(B);
    2187          161 :   for (i = 1; i < l; i++)
    2188              :   {
    2189          112 :     long j = ZV_search(B, muliu(gel(NB,i), u)); /* search for N / B[i] */
    2190          112 :     set_avma(av); if (!j || !equalii(gel(R,i),gel(R,j))) return 0;
    2191              :   }
    2192           49 :   return 1;
    2193              : }
    2194              : /* return Nebentypus of eta quotient, k2 = 2*k integral */
    2195              : static GEN
    2196          203 : etachar(GEN B, GEN R, GEN k2)
    2197              : {
    2198          203 :   long i, l = lg(B);
    2199          203 :   GEN P = gen_1;
    2200          546 :   for (i = 1; i < l; ++i) if (mpodd(gel(R,i))) P = mulii(P, gel(B,i));
    2201          203 :   switch(Mod4(k2))
    2202              :   {
    2203          133 :     case 0: break;
    2204           42 :     case 2:  P = negi(P); break;
    2205           28 :     default: P = shifti(P, 1); break;
    2206              :   }
    2207          203 :   return coredisc(P);
    2208              : }
    2209              : /* Return 0 if not on gamma_0(N). Sets conductor, modular weight, character,
    2210              :  * canonical matrix, v_q(eta), sd = 1 iff self-dual, cusp = 1 iff cuspidal
    2211              :  * [0 if holomorphic at all cusps, else -1] */
    2212              : long
    2213          259 : etaquotype(GEN *peta, GEN *pN, GEN *pk, GEN *CHI, long *pv, long *sd,
    2214              :            long *cusp)
    2215              : {
    2216          259 :   GEN B, R, S, T, N, NB, eta = *peta;
    2217              :   long l, i, u, S24;
    2218              : 
    2219          259 :   if (lg(eta) != 3) pari_err_TYPE("lfunetaquo", eta);
    2220          259 :   switch(typ(eta))
    2221              :   {
    2222           77 :     case t_VEC: eta = mkmat2(mkcol(gel(eta,1)), mkcol(gel(eta,2))); break;
    2223          182 :     case t_MAT: break;
    2224            0 :     default: pari_err_TYPE("lfunetaquo", eta);
    2225              :   }
    2226          259 :   if (!RgV_is_ZVpos(gel(eta,1)) || !RgV_is_ZV(gel(eta,2)))
    2227            0 :     pari_err_TYPE("lfunetaquo", eta);
    2228          259 :   *peta = eta = famat_reduce(eta);
    2229          259 :   B = gel(eta,1); l = lg(B); /* sorted in increasing order */
    2230          259 :   R = gel(eta,2);
    2231          259 :   N = ZV_lcm(B); NB = cgetg(l, t_VEC);
    2232          721 :   for (i = 1; i < l; i++) gel(NB,i) = diviiexact(N, gel(B,i));
    2233          259 :   S = gen_0; T = gen_0; u = 0;
    2234          721 :   for (i = 1; i < l; ++i)
    2235              :   {
    2236          462 :     GEN b = gel(B,i), r = gel(R,i);
    2237          462 :     S = addii(S, mulii(b, r));
    2238          462 :     T = addii(T, r);
    2239          462 :     u += umodiu(r,24) * umodiu(gel(NB,i), 24);
    2240              :   }
    2241          259 :   S = divis_rem(S, 24, &S24);
    2242          259 :   if (S24) return 0; /* nonintegral valuation at oo */
    2243          252 :   u = 24 / ugcd(24, u % 24);
    2244          252 :   *pN = muliu(N, u); /* level */
    2245          252 :   *pk = gmul2n(T,-1); /* weight */
    2246          252 :   *pv = itos(S); /* valuation */
    2247          252 :   if (cusp) *cusp = etacuspidal(*pN, *pk, B, R, NB);
    2248          252 :   if (sd) *sd = etaselfdual(B, R, NB, u);
    2249          252 :   if (CHI) *CHI = etachar(B, R, T);
    2250          252 :   return 1;
    2251              : }
    2252              : 
    2253              : GEN
    2254           49 : lfunetaquo(GEN eta0)
    2255              : {
    2256           49 :   pari_sp ltop = avma;
    2257           49 :   GEN Ldata, N, BR, k, eta = eta0;
    2258              :   long v, sd, cusp;
    2259           49 :   if (!etaquotype(&eta, &N, &k, NULL, &v, &sd, &cusp))
    2260            0 :     pari_err_TYPE("lfunetaquo", eta0);
    2261           49 :   if (!cusp) pari_err_IMPL("noncuspidal eta quotient");
    2262           49 :   if (!sd) pari_err_IMPL("non self-dual eta quotient");
    2263           49 :   if (typ(k) != t_INT) pari_err_TYPE("lfunetaquo [nonintegral weight]", eta0);
    2264           49 :   BR = mkvec3(ZV_to_zv(gel(eta,1)), ZV_to_zv(gel(eta,2)), stoi(v - 1));
    2265           49 :   Ldata = mkvecn(6, tag(BR,t_LFUN_ETA), gen_0, mkvec2(gen_0,gen_1), k,N, gen_1);
    2266           49 :   return gc_GEN(ltop, Ldata);
    2267              : }
    2268              : 
    2269              : static GEN
    2270          399 : vecan_qf(GEN Q, long L)
    2271              : {
    2272          399 :   GEN v, w = qfrep0(Q, utoi(L), 1);
    2273              :   long i;
    2274          399 :   v = cgetg(L+1, t_VEC);
    2275        26698 :   for (i = 1; i <= L; i++) gel(v,i) = utoi(2 * w[i]);
    2276          399 :   return v;
    2277              : }
    2278              : 
    2279              : long
    2280          336 : qfiseven(GEN M)
    2281              : {
    2282          336 :   long i, l = lg(M);
    2283          784 :   for (i=1; i<l; i++)
    2284          679 :     if (mpodd(gcoeff(M,i,i))) return 0;
    2285          105 :   return 1;
    2286              : }
    2287              : 
    2288              : GEN
    2289           91 : lfunqf(GEN M, long prec)
    2290              : {
    2291           91 :   pari_sp ltop = avma;
    2292              :   long n;
    2293              :   GEN k, D, d, Mi, Ldata, poles, eno, dual;
    2294              : 
    2295           91 :   if (typ(M) != t_MAT) pari_err_TYPE("lfunqf", M);
    2296           91 :   if (!RgM_is_ZM(M))   pari_err_TYPE("lfunqf [not integral]", M);
    2297           91 :   n = lg(M)-1;
    2298           91 :   k = uutoQ(n,2);
    2299           91 :   M = Q_primpart(M);
    2300           91 :   Mi = ZM_inv(M, &d); /* d M^(-1) */
    2301           91 :   if (!qfiseven(M)) { M = gmul2n(M, 1); d = shifti(d,1); }
    2302           91 :   if (!qfiseven(Mi)){ Mi= gmul2n(Mi,1); d = shifti(d,1); }
    2303              :   /* det(Mi) = d^n/det(M), D^2 = det(Mi)/det(M) */
    2304           91 :   D = gdiv(gpow(d,k,prec), ZM_det(M));
    2305           91 :   if (!issquareall(D, &eno)) eno = gsqrt(D, prec);
    2306           91 :   dual = gequal1(D) ? gen_0: tag(Mi, t_LFUN_QF);
    2307           91 :   poles = mkcol2(mkvec2(k, simple_pole(gmul2n(eno,1))),
    2308              :                  mkvec2(gen_0, simple_pole(gen_m2)));
    2309           91 :   Ldata = mkvecn(7, tag(M, t_LFUN_QF), dual,
    2310              :        mkvec2(gen_0, gen_1), k, d, eno, poles);
    2311           91 :   return gc_GEN(ltop, Ldata);
    2312              : }
    2313              : 
    2314              : /********************************************************************/
    2315              : /**  Artin L function, based on a GP script by Charlotte Euvrard   **/
    2316              : /********************************************************************/
    2317              : 
    2318              : static GEN
    2319          119 : artin_charfromgens(GEN G, GEN M)
    2320              : {
    2321          119 :   GEN R, V, ord = gal_get_orders(G), grp = gal_get_group(G);
    2322          119 :   long i, j, k, n = lg(ord)-1, m = lg(grp)-1;
    2323              : 
    2324          119 :   if (lg(M)-1 != n) pari_err_DIM("lfunartin");
    2325          119 :   R = cgetg(m+1, t_VEC);
    2326          119 :   gel(R, 1) = matid(lg(gel(M, 1))-1);
    2327          357 :   for (i = 1, k = 1; i <= n; ++i)
    2328              :   {
    2329          238 :     long c = k*(ord[i] - 1);
    2330          238 :     gel(R, ++k) = gel(M, i);
    2331         1043 :     for (j = 2; j <= c; ++j) gel(R, ++k) = gmul(gel(R,j), gel(M,i));
    2332              :   }
    2333          119 :   V = cgetg(m+1, t_VEC);
    2334         1281 :   for (i = 1; i <= m; i++) gel(V, gel(grp,i)[1]) = gtrace(gel(R,i));
    2335          119 :   return V;
    2336              : }
    2337              : 
    2338              : /* TODO move somewhere else? */
    2339              : GEN
    2340          280 : galois_get_conj(GEN G)
    2341              : {
    2342          280 :   GEN grp = gal_get_group(G);
    2343          280 :   long i, k, r = lg(grp)-1;
    2344          280 :   GEN b = zero_F2v(r);
    2345          959 :   for (k = 2; k <= r; ++k)
    2346              :   {
    2347          959 :     GEN g = gel(grp,k);
    2348          959 :     if (!F2v_coeff(b,g[1]) && g[g[1]]==1)
    2349              :     {
    2350          392 :       pari_sp av = avma;
    2351          392 :       GEN F = galoisfixedfield(G, g, 1, -1);
    2352          392 :       if (ZX_sturmpart(F, NULL) > 0) return gc_const(av, g);
    2353         1456 :       for (i = 1; i<=r; i++)
    2354              :       {
    2355         1344 :         GEN h = gel(grp, i);
    2356         1344 :         long t = h[1];
    2357         5264 :         while (h[t]!=1) t = h[t];
    2358         1344 :         F2v_set(b, h[g[t]]);
    2359              :       }
    2360          112 :       set_avma(av);
    2361              :     }
    2362              :   }
    2363            0 :   pari_err_BUG("galois_get_conj");
    2364              :   return NULL;/*LCOV_EXCL_LINE*/
    2365              : }
    2366              : 
    2367              : static GEN
    2368         7700 : cyclotoi(GEN v) { return simplify_shallow(lift_shallow(v)); }
    2369              : static long
    2370         2891 : cyclotos(GEN v) { return gtos(cyclotoi(v)); }
    2371              : static long
    2372         2821 : char_dim(GEN ch) { return cyclotos(gel(ch,1)); }
    2373              : 
    2374              : static GEN
    2375         1379 : artin_gamma(GEN N, GEN G, GEN ch)
    2376              : {
    2377         1379 :   long a, t, d = char_dim(ch);
    2378         1379 :   if (nf_get_r2(N) == 0) return vec01(d, 0);
    2379           70 :   a = galois_get_conj(G)[1];
    2380           70 :   t = cyclotos(gel(ch,a));
    2381           70 :   return vec01((d+t) / 2, (d-t) / 2);
    2382              : }
    2383              : 
    2384              : static long
    2385         3213 : artin_dim(GEN ind, GEN ch)
    2386              : {
    2387         3213 :   long n = lg(ch)-1;
    2388         3213 :   GEN elts = group_elts(ind, n);
    2389         3213 :   long i, d = lg(elts)-1;
    2390         3213 :   GEN s = gen_0;
    2391        18123 :   for(i=1; i<=d; i++)
    2392        14910 :     s = gadd(s, gel(ch, gel(elts,i)[1]));
    2393         3213 :   return gtos(gdivgu(cyclotoi(s), d));
    2394              : }
    2395              : 
    2396              : static GEN
    2397          623 : artin_ind(GEN elts, GEN ch, GEN p)
    2398              : {
    2399          623 :   long i, d = lg(elts)-1;
    2400          623 :   GEN s = gen_0;
    2401         2149 :   for(i=1; i<=d; i++)
    2402         1526 :     s = gadd(s, gel(ch, gmul(gel(elts,i),p)[1]));
    2403          623 :   return gdivgu(s, d);
    2404              : }
    2405              : 
    2406              : static GEN
    2407         2282 : artin_ram(GEN nf, GEN gal, GEN aut, GEN pr, GEN ramg, GEN ch, long d)
    2408              : {
    2409         2282 :   pari_sp av = avma;
    2410              :   long i, v, n;
    2411              :   GEN p, q, V, elts;
    2412         2282 :   if (d==0) return pol_1(0);
    2413          616 :   n = degpol(gal_get_pol(gal));
    2414          616 :   q = p = idealramfrobenius_aut(nf, gal, pr, ramg, aut);
    2415          616 :   elts = group_elts(gel(ramg,2), n);
    2416          616 :   v = fetch_var_higher();
    2417          616 :   V = cgetg(d+2, t_POL);
    2418          616 :   V[1] = evalsigne(1)|evalvarn(v);
    2419         1239 :   for(i=1; i<=d; i++)
    2420              :   {
    2421          623 :     gel(V,i+1) = artin_ind(elts, ch, q);
    2422          623 :     q = gmul(q, p);
    2423              :   }
    2424          616 :   delete_var();
    2425          616 :   V = RgXn_expint(RgX_neg(V),d+1);
    2426          616 :   setvarn(V,0); return gc_upto(av, ginv(V));
    2427              : }
    2428              : 
    2429              : /* N true nf; [Artin conductor, vec of [p, Lp]] */
    2430              : static GEN
    2431         1379 : artin_badprimes(GEN N, GEN G, GEN aut, GEN ch)
    2432              : {
    2433         1379 :   pari_sp av = avma;
    2434         1379 :   long i, d = char_dim(ch);
    2435         1379 :   GEN P = gel(absZ_factor(nf_get_disc(N)), 1);
    2436         1379 :   long lP = lg(P);
    2437         1379 :   GEN B = cgetg(lP, t_VEC), C = cgetg(lP, t_VEC);
    2438              : 
    2439         3661 :   for (i = 1; i < lP; ++i)
    2440              :   {
    2441         2282 :     GEN p = gel(P, i), pr = idealprimedec_galois(N, p);
    2442         2282 :     GEN J = idealramgroups_aut(N, G, pr, aut);
    2443         2282 :     GEN G0 = gel(J,2); /* inertia group */
    2444         2282 :     long lJ = lg(J);
    2445         2282 :     long sdec = artin_dim(G0, ch);
    2446         2282 :     long ndec = group_order(G0);
    2447         2282 :     long j, v = ndec * (d - sdec);
    2448         3213 :     for (j = 3; j < lJ; ++j)
    2449              :     {
    2450          931 :       GEN Jj = gel(J, j);
    2451          931 :       long s = artin_dim(Jj, ch);
    2452          931 :       v += group_order(Jj) * (d - s);
    2453              :     }
    2454         2282 :     gel(C, i) = powiu(p, v/ndec);
    2455         2282 :     gel(B, i) = mkvec2(p, artin_ram(N, G, aut, pr, J, ch, sdec));
    2456              :   }
    2457         1379 :   return gc_GEN(av, mkvec2(ZV_prod(C), B));
    2458              : }
    2459              : 
    2460              : /* p does not divide nf.index */
    2461              : static GEN
    2462        52402 : idealfrobenius_easy(GEN nf, GEN gal, GEN aut, GEN T, GEN p)
    2463              : {
    2464        52402 :   long i, l = lg(aut), f = degpol(T);
    2465        52402 :   GEN D, Dzk, DzkT, DXp, grp = gal_get_group(gal);
    2466        52402 :   pari_sp av = avma;
    2467        52402 :   if (f==1) return gel(grp,1);
    2468        50596 :   Dzk = nf_get_zkprimpart(nf);
    2469        50594 :   D = modii(nf_get_zkden(nf), p);
    2470        50595 :   DzkT = RgV_to_RgM(FqV_red(Dzk, T, p), f);
    2471        50594 :   DXp = RgX_to_RgC(FpX_Frobenius(T, p), f);
    2472        50587 :   if (!equali1(D)) DXp = FpC_Fp_mul(DXp, D, p);
    2473       332138 :   for(i=1; i < l; i++)
    2474              :   {
    2475       332126 :     GEN g = gel(grp,i);
    2476       332126 :     if (perm_orderu(g) == (ulong)f)
    2477              :     {
    2478       170266 :       GEN A = FpM_FpC_mul(DzkT, gel(aut,g[1]), p);
    2479       170247 :       if (ZV_equal(A, DXp)) return gc_const(av, g);
    2480              :     }
    2481              :   }
    2482              :   return NULL; /* LCOV_EXCL_LINE */
    2483              : }
    2484              : /* true nf; p divides nf.index, pr/p unramified */
    2485              : static GEN
    2486         1596 : idealfrobenius_hard(GEN nf, GEN gal, GEN aut, GEN pr)
    2487              : {
    2488         1596 :   long i, l = lg(aut), f = pr_get_f(pr);
    2489         1596 :   GEN modpr, p, T, X, Xp, pi, grp = gal_get_group(gal);
    2490         1596 :   pari_sp av = avma;
    2491         1596 :   if (f==1) return gel(grp,1);
    2492         1344 :   pi = pr_get_gen(pr);
    2493         1344 :   modpr = zkmodprinit(nf, pr);
    2494         1344 :   p = modpr_get_p(modpr);
    2495         1344 :   T = modpr_get_T(modpr);
    2496         1344 :   X = modpr_genFq(modpr);
    2497         1344 :   Xp = FpX_Frobenius(T, p);
    2498         9188 :   for (i = 1; i < l; i++)
    2499              :   {
    2500         9188 :     GEN g = gel(grp,i);
    2501         9188 :     if (perm_orderu(g) == (ulong)f)
    2502              :     {
    2503         4372 :       GEN S = gel(aut,g[1]);
    2504         4372 :       GEN A = nf_to_Fq(nf, zk_galoisapplymod(nf,X,S,p), modpr);
    2505              :       /* sigma(X) = X^p (mod pr) and sigma(pi) in pr */
    2506         5828 :       if (ZX_equal(A, Xp) && (f == nf_get_degree(nf) ||
    2507         2800 :           ZC_prdvd(zk_galoisapplymod(nf,pi,S,p),pr))) return gc_const(av, g);
    2508              :     }
    2509              :   }
    2510              :   return NULL; /* LCOV_EXCL_LINE */
    2511              : }
    2512              : 
    2513              : /* true nf */
    2514              : static GEN
    2515        53992 : dirartin(GEN nf, GEN G, GEN V, GEN aut, GEN p, long n)
    2516              : {
    2517        53992 :   pari_sp av = avma;
    2518              :   GEN pr, frob;
    2519              :   /* pick one maximal ideal in the conjugacy class above p */
    2520        53992 :   GEN T = nf_get_pol(nf);
    2521        53992 :   if (!dvdii(nf_get_index(nf), p))
    2522              :   { /* simple case */
    2523        52396 :     GEN F = FpX_factor(T, p), P = gmael(F,1,1);
    2524        52402 :     frob = idealfrobenius_easy(nf, G, aut, P, p);
    2525              :   }
    2526              :   else
    2527              :   {
    2528         1596 :     pr = idealprimedec_galois(nf,p);
    2529         1596 :     frob = idealfrobenius_hard(nf, G, aut, pr);
    2530              :   }
    2531        53995 :   set_avma(av); return n ? RgXn_inv(gel(V, frob[1]), n): gel(V, frob[1]);
    2532              : }
    2533              : 
    2534              : GEN
    2535        15664 : dirartin_worker(GEN P, ulong X, GEN nf, GEN G, GEN V, GEN aut)
    2536              : {
    2537        15664 :   pari_sp av = avma;
    2538        15664 :   long i, l = lg(P);
    2539        15664 :   GEN W = cgetg(l, t_VEC);
    2540        69631 :   for(i = 1; i < l; i++)
    2541              :   {
    2542        53966 :     ulong p = uel(P,i);
    2543        53966 :     long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */
    2544        53964 :     gel(W,i) = dirartin(nf, G, V, aut, utoi(uel(P,i)), d);
    2545              :   }
    2546        15665 :   return gc_GEN(av, mkvec2(P,W));
    2547              : }
    2548              : 
    2549              : static GEN
    2550         2947 : vecan_artin(GEN an, long L, long prec)
    2551              : {
    2552         2947 :   GEN A, Sbad = gel(an,5);
    2553         2947 :   long n = itos(gel(an,6)), isreal = lg(an)<8 ? 0: !itos(gel(an,7));
    2554         2947 :   GEN worker = snm_closure(is_entry("_dirartin_worker"), vecslice(an,1,4));
    2555         2947 :   A = lift_shallow(pardireuler(worker, gen_2, stoi(L), NULL, Sbad));
    2556         2947 :   A = RgXV_RgV_eval(A, grootsof1(n, prec));
    2557         2947 :   if (isreal) A = real_i(A);
    2558         2947 :   return A;
    2559              : }
    2560              : 
    2561              : static GEN
    2562           28 : eulerf_artin(GEN an, GEN p, long prec)
    2563              : {
    2564           28 :   GEN nf = gel(an,1), G = gel(an,2), V = gel(an,3), aut = gel(an,4);
    2565           28 :   GEN Sbad = gel(an,5);
    2566           28 :   long n = itos(gel(an,6)), isreal = lg(an)<8 ? 0: !itos(gel(an,7));
    2567           28 :   GEN f = eulerf_bad(Sbad, p);
    2568           28 :   if (!f) f = mkrfrac(gen_1,dirartin(nf, G, V, aut, p, 0));
    2569           28 :   f = gsubst(liftpol(f),1, rootsof1u_cx(n, prec));
    2570           28 :   if (isreal) f = real_i(f);
    2571           28 :   return f;
    2572              : }
    2573              : 
    2574              : static GEN
    2575         2856 : char_expand(GEN conj, GEN ch)
    2576              : {
    2577         2856 :   long i, l = lg(conj);
    2578         2856 :   GEN V = cgetg(l, t_COL);
    2579        31409 :   for (i=1; i<l; i++) gel(V,i) = gel(ch, conj[i]);
    2580         2856 :   return V;
    2581              : }
    2582              : 
    2583              : static GEN
    2584         1596 : handle_zeta(long n, GEN ch, long *m)
    2585              : {
    2586              :   GEN c;
    2587         1596 :   long t, i, l = lg(ch);
    2588         1596 :   GEN dim = cyclotoi(vecsum(ch));
    2589         1596 :   if (typ(dim) != t_INT)
    2590            0 :     pari_err_DOMAIN("lfunartin","chi","is not a", strtoGENstr("character"), ch);
    2591         1596 :   t = itos(dim);
    2592         1596 :   if (t < 0 || t % n)
    2593            0 :     pari_err_DOMAIN("lfunartin","chi","is not a", strtoGENstr("character"), ch);
    2594         1596 :   if (t == 0) { *m = 0; return ch; }
    2595          224 :   *m = t / n;
    2596          224 :   c = cgetg(l, t_COL);
    2597         2065 :   for (i=1; i<l; i++)
    2598         1841 :     gel(c,i) = gsubgs(gel(ch,i), *m);
    2599          224 :   return c;
    2600              : }
    2601              : 
    2602              : static int
    2603         6496 : cyclo_is_real(GEN v, GEN ix)
    2604              : {
    2605         6496 :   pari_sp av = avma;
    2606         6496 :   GEN w = poleval(lift_shallow(v), ix);
    2607         6496 :   return gc_bool(av, gequal(w, v));
    2608              : }
    2609              : 
    2610              : static int
    2611         1379 : char_is_real(GEN ch, GEN mod)
    2612              : {
    2613         1379 :   long i, l = lg(ch);
    2614         1379 :   GEN ix = QXQ_inv(pol_x(varn(mod)), mod);
    2615         7014 :   for (i=1; i<l; i++)
    2616         6496 :     if (!cyclo_is_real(gel(ch,i), ix)) return 0;
    2617          518 :   return 1;
    2618              : }
    2619              : 
    2620              : GEN
    2621         1610 : lfunartin(GEN nf, GEN gal, GEN ch, long o, long bitprec)
    2622              : {
    2623         1610 :   pari_sp av = avma;
    2624         1610 :   GEN bc, V, aut, mod, Ldata = NULL, chx, cc, conj, repr;
    2625              :   long tmult, var;
    2626         1610 :   nf = checknf(nf);
    2627         1610 :   checkgal(gal);
    2628         1610 :   var = gvar(ch);
    2629         1610 :   if (var == 0) pari_err_PRIORITY("lfunartin",ch,"=",0);
    2630         1610 :   if (var < 0) var = 1;
    2631         1610 :   if (!is_vec_t(typ(ch))) pari_err_TYPE("lfunartin", ch);
    2632         1610 :   cc = group_to_cc(gal);
    2633         1610 :   conj = gel(cc,2);
    2634         1610 :   repr = gel(cc,3);
    2635         1610 :   mod = mkpolmod(gen_1, polcyclo(o, var));
    2636         1610 :   if (lg(ch)>1 && typ(gel(ch,1))==t_MAT)
    2637          119 :     chx = artin_charfromgens(gal, gmul(ch,mod));
    2638              :   else
    2639              :   {
    2640         1491 :     if (lg(repr) != lg(ch)) pari_err_DIM("lfunartin");
    2641         1477 :     chx = char_expand(conj, gmul(ch,mod));
    2642              :   }
    2643         1596 :   chx = handle_zeta(nf_get_degree(nf), chx, &tmult);
    2644         1596 :   ch = shallowextract(chx, repr);
    2645         1596 :   if (!gequal0(chx))
    2646              :   {
    2647         1379 :     GEN real = char_is_real(chx, gel(mod,1))? gen_0: gen_1;
    2648         1379 :     aut = nfgaloispermtobasis(nf, gal);
    2649         1379 :     V = gmul(char_expand(conj, galoischarpoly(gal, ch, o)), mod);
    2650         1379 :     bc = artin_badprimes(nf, gal, aut, chx);
    2651         2758 :     Ldata = mkvecn(6,
    2652         1379 :       tag(mkcoln(7, nf, gal, V, aut, gel(bc, 2), stoi(o), real), t_LFUN_ARTIN),
    2653         1379 :       real, artin_gamma(nf, gal, chx), gen_1, gel(bc,1), gen_0);
    2654              :   }
    2655         1596 :   if (tmult==0 && Ldata==NULL) pari_err_TYPE("lfunartin",ch);
    2656         1596 :   if (tmult)
    2657              :   {
    2658              :     long i;
    2659          224 :     if (Ldata==NULL) { Ldata = lfunzeta(); tmult--; }
    2660          231 :     for(i=1; i<=tmult; i++)
    2661            7 :       Ldata = lfunmul(Ldata, gen_1, bitprec);
    2662              :   }
    2663         1596 :   return gc_GEN(av, Ldata);
    2664              : }
    2665              : 
    2666              : /* true nf */
    2667              : static GEN
    2668           21 : lfunzetakinit_artin(GEN nf, GEN gal, GEN dom, long der, long bitprec)
    2669              : {
    2670           21 :   GEN F, E, M, domain, To = galoischartable(gal), T = gel(To, 1);
    2671           21 :   long i, o = itos(gel(To, 2)), l = lg(T);
    2672           21 :   F = cgetg(l, t_VEC);
    2673           21 :   E = cgetg(l, t_VECSMALL);
    2674           84 :   for (i = 1; i < l; ++i)
    2675              :   {
    2676           63 :     GEN L = lfunartin(nf, gal, gel(T,i), o, bitprec);
    2677           63 :     gel(F, i) = lfuninit(L, dom, der, bitprec);
    2678           63 :     E[i] = char_dim(gel(T,i));
    2679              :   }
    2680           21 :   domain = mkvec2(dom, mkvecsmall2(der, bitprec));
    2681           21 :   M = mkvec3(F, E, zero_zv(l-1));
    2682           21 :   return lfuninit_make(t_LDESC_PRODUCT, lfunzetak_i(nf), M, domain);
    2683              : }
    2684              : 
    2685              : /********************************************************************/
    2686              : /**                    High-level Constructors                     **/
    2687              : /********************************************************************/
    2688              : enum { t_LFUNMISC_POL, t_LFUNMISC_CHIQUAD, t_LFUNMISC_CHICONREY,
    2689              :        t_LFUNMISC_CHIGEN, t_LFUNMISC_ELLINIT, t_LFUNMISC_ETAQUO,
    2690              :        t_LFUNMISC_GCHAR, t_LFUNMISC_ABELREL };
    2691              : static long
    2692        18082 : lfundatatype(GEN data)
    2693              : {
    2694        18082 :   switch(typ(data))
    2695              :   {
    2696         4053 :     case t_INT: return t_LFUNMISC_CHIQUAD;
    2697          217 :     case t_INTMOD: return t_LFUNMISC_CHICONREY;
    2698          686 :     case t_POL: return t_LFUNMISC_POL;
    2699        13126 :     case t_VEC:
    2700        13126 :       switch(lg(data))
    2701              :       {
    2702         4088 :         case 17: return t_LFUNMISC_ELLINIT;
    2703            0 :         case 10: return t_LFUNMISC_POL;
    2704         9038 :         case 3:
    2705         9038 :           if (typ(gel(data,1)) != t_VEC) break;
    2706         9038 :           return is_gchar_group(gel(data,1))  ? t_LFUNMISC_GCHAR
    2707         9038 :                     : typ(gel(data,2))==t_MAT ? t_LFUNMISC_ABELREL
    2708              :                                               : t_LFUNMISC_CHIGEN;
    2709              :       }
    2710            0 :       break;
    2711              :   }
    2712            0 :   return -1;
    2713              : }
    2714              : static GEN
    2715       126630 : lfunmisc_to_ldata_i(GEN ldata, long shallow)
    2716              : {
    2717              :   GEN x;
    2718       126630 :   if (is_linit(ldata)) ldata = linit_get_ldata(ldata);
    2719       126630 :   if (is_ldata(ldata) && is_tagged(ldata))
    2720              :   {
    2721       108373 :     if (!shallow) ldata = gcopy(ldata);
    2722       108373 :     checkldata(ldata); return ldata;
    2723              :   }
    2724        18257 :   x = checknf_i(ldata); if (x) return lfunzetak(x);
    2725        18082 :   switch (lfundatatype(ldata))
    2726              :   {
    2727          686 :     case t_LFUNMISC_POL: return lfunzetak(ldata);
    2728         4053 :     case t_LFUNMISC_CHIQUAD: return lfunchiquad(ldata);
    2729          217 :     case t_LFUNMISC_CHICONREY:
    2730              :     {
    2731          217 :       GEN G = znstar0(gel(ldata,1), 1);
    2732          217 :       return lfunchiZ(G, gel(ldata,2));
    2733              :     }
    2734         8498 :     case t_LFUNMISC_CHIGEN:
    2735              :     {
    2736         8498 :       GEN G = gel(ldata,1), chi = gel(ldata,2);
    2737         8498 :       switch(nftyp(G))
    2738              :       {
    2739         8232 :         case typ_BIDZ: return lfunchiZ(G, chi);
    2740          259 :         case typ_BNR: return lfunchigen(G, chi);
    2741              :       }
    2742              :     }
    2743            7 :     break;
    2744          519 :     case t_LFUNMISC_GCHAR: return lfungchar(gel(ldata,1), gel(ldata,2));
    2745           21 :     case t_LFUNMISC_ABELREL:
    2746           21 :       return lfunabelrel(gel(ldata,1), gel(ldata,2),
    2747           21 :                          lg(ldata)==3? NULL: gel(ldata,3));
    2748         4088 :     case t_LFUNMISC_ELLINIT: return lfunell(ldata);
    2749              :   }
    2750            7 :   if (shallow != 2) pari_err_TYPE("lfunmisc_to_ldata",ldata);
    2751            0 :   return NULL;
    2752              : }
    2753              : 
    2754              : GEN
    2755         3521 : lfunmisc_to_ldata(GEN ldata)
    2756         3521 : { return lfunmisc_to_ldata_i(ldata, 0); }
    2757              : 
    2758              : GEN
    2759       101304 : lfunmisc_to_ldata_shallow(GEN ldata)
    2760       101304 : { return lfunmisc_to_ldata_i(ldata, 1); }
    2761              : 
    2762              : GEN
    2763        21805 : lfunmisc_to_ldata_shallow_i(GEN ldata)
    2764        21805 : { return lfunmisc_to_ldata_i(ldata, 2); }
    2765              : 
    2766              : /********************************************************************/
    2767              : /**                    High-level an expansion                     **/
    2768              : /********************************************************************/
    2769              : /* van is the output of ldata_get_an: return a_1,...a_L at precision prec */
    2770              : GEN
    2771        33390 : ldata_vecan(GEN van, long L, long prec)
    2772              : {
    2773        33390 :   GEN an = gel(van, 2);
    2774        33390 :   long t = mael(van,1,1);
    2775              :   pari_timer ti;
    2776        33390 :   if (DEBUGLEVEL >= 1)
    2777            0 :     err_printf("Lfun: computing %ld coeffs, prec %ld, type %ld\n", L, prec, t);
    2778        33390 :   if (DEBUGLEVEL >= 2) timer_start(&ti);
    2779        33390 :   if (L < 0) L = 0;
    2780        33390 :   switch (t)
    2781              :   {
    2782              :     long n;
    2783         1967 :     case t_LFUN_GENERIC:
    2784         1967 :       an = vecan_closure(an, L, prec);
    2785         1897 :       n = lg(an)-1;
    2786         1897 :       if (n < L)
    2787              :       {
    2788           14 :         pari_warn(warner, "#an = %ld < %ld, results may be imprecise", n, L);
    2789           14 :         an = shallowconcat(an, zerovec(L-n));
    2790              :       }
    2791         1897 :       break;
    2792            0 :     case t_LFUN_CLOSURE0:
    2793              :       pari_err_BUG("ldata_vecan: please call ldata_newprec");/*LCOV_EXCL_LINE*/
    2794         3255 :     case t_LFUN_ZETA: an = const_vecsmall(L, 1); break;
    2795         2100 :     case t_LFUN_NF:  an = dirzetak(an, stoi(L)); break;
    2796         6272 :     case t_LFUN_ELL:
    2797         6272 :       an = (ell_get_type(an) == t_ELL_Q) ? ellanQ_zv(an, L): ellan(an, L);
    2798         6272 :       break;
    2799         3668 :     case t_LFUN_KRONECKER: an = vecan_Kronecker(an, L); break;
    2800          168 :     case t_LFUN_ABELREL: an = vecan_abelrel(an, L); break;
    2801         3647 :     case t_LFUN_CHIZ: an = vecan_chiZ(an, L, prec); break;
    2802         1554 :     case t_LFUN_CHIGEN: an = vecan_chigen(an, L, prec); break;
    2803          840 :     case t_LFUN_HECKE: an = vecan_gchar(an, L, prec); break;
    2804         2947 :     case t_LFUN_ARTIN: an = vecan_artin(an, L, prec); break;
    2805          147 :     case t_LFUN_ETA: an = vecan_eta(an, L); break;
    2806          399 :     case t_LFUN_QF: an = vecan_qf(an, L); break;
    2807          630 :     case t_LFUN_DIV: an = vecan_div(an, L, prec); break;
    2808          413 :     case t_LFUN_MUL: an = vecan_mul(an, L, prec); break;
    2809          154 :     case t_LFUN_CONJ: an = vecan_conj(an, L, prec); break;
    2810          343 :     case t_LFUN_SYMPOW_ELL: an = vecan_ellsympow(an, L); break;
    2811          553 :     case t_LFUN_GENUS2: an = vecan_genus2(an, L); break;
    2812          168 :     case t_LFUN_HGM:
    2813          168 :       an = hgmcoefs(gel(an,1), gel(an,2), L); break;
    2814          420 :     case t_LFUN_MFCLOS:
    2815              :     {
    2816          420 :       GEN F = gel(an,1), E = gel(an,2), c = gel(an,3);
    2817          420 :       an = mfcoefs(F,L,1) + 1; /* skip a_0 */
    2818          420 :       an[0] = evaltyp(t_VEC)|_evallg(L+1);
    2819          420 :       an = mfvecembed(E, an);
    2820          420 :       if (!isint1(c)) an = RgV_Rg_mul(an,c);
    2821          420 :       break;
    2822              :     }
    2823         2884 :     case t_LFUN_TWIST: an = vecan_twist(an, L, prec); break;
    2824          861 :     case t_LFUN_SHIFT: an = vecan_shift(an, L, prec); break;
    2825            0 :     default: pari_err_TYPE("ldata_vecan", van);
    2826              :   }
    2827        33320 :   if (DEBUGLEVEL >= 2) timer_printf(&ti, "ldata_vecan");
    2828        33320 :   return an;
    2829              : }
    2830              : 
    2831              : /* shallow */
    2832              : GEN
    2833        34349 : ldata_newprec(GEN ldata, long prec)
    2834              : {
    2835        34349 :   GEN van = ldata_get_an(ldata), an = gel(van, 2);
    2836        34349 :   long t = mael(van,1,1);
    2837        34349 :   switch (t)
    2838              :   {
    2839          371 :     case t_LFUN_CLOSURE0: return closure2ldata(an, prec);
    2840         1134 :     case t_LFUN_HECKE:
    2841              :     {
    2842         1134 :       GEN gc = gel(an, 1), chiw = gel(an, 2);
    2843         1134 :       gc = gcharnewprec(gc, prec);
    2844         1134 :       return gchari_lfun(gc, chiw, gen_0); /* chi in internal format */
    2845              :     }
    2846          329 :     case t_LFUN_QF:
    2847              :     {
    2848          329 :       GEN eno = ldata_get_rootno(ldata);
    2849          329 :       if (typ(eno)==t_REAL && realprec(eno) < prec) return lfunqf(an, prec);
    2850          273 :       break;
    2851              :     }
    2852              :   }
    2853        32788 :   return ldata;
    2854              : }
    2855              : 
    2856              : /* not gc clean */
    2857              : GEN
    2858          952 : ldata_eulerf(GEN van, GEN p, long prec)
    2859              : {
    2860          952 :   GEN an = gel(van, 2), f = gen_0;
    2861          952 :   long t = mael(van,1,1);
    2862          952 :   switch (t)
    2863              :   {
    2864           70 :     case t_LFUN_GENERIC:
    2865           70 :       f = eulerf_closure(an, p, prec); break;
    2866            0 :     case t_LFUN_CLOSURE0:
    2867              :       pari_err_BUG("ldata_vecan: please call ldata_newprec");/*LCOV_EXCL_LINE*/
    2868          112 :     case t_LFUN_ZETA: f = mkrfrac(gen_1,deg1pol_shallow(gen_m1, gen_1,0)); break;
    2869          168 :     case t_LFUN_NF:  f = eulerf_zetak(an, p); break;
    2870           70 :     case t_LFUN_ELL: f = elleulerf(an, p); break;
    2871           70 :     case t_LFUN_KRONECKER:
    2872           70 :       f = mkrfrac(gen_1, deg1pol_shallow(stoi(-kronecker(an, p)), gen_1, 0)); break;
    2873           42 :     case t_LFUN_ABELREL: f = eulerf_abelrel(an, p); break;
    2874           42 :     case t_LFUN_CHIZ: f = eulerf_chiZ(an, p, prec); break;
    2875           28 :     case t_LFUN_CHIGEN: f = eulerf_chigen(an, p, prec); break;
    2876           28 :     case t_LFUN_HECKE: f = eulerf_gchar(an, p, prec); break;
    2877           28 :     case t_LFUN_ARTIN: f = eulerf_artin(an, p, prec); break;
    2878           14 :     case t_LFUN_DIV: f = eulerf_div(an, p, prec); break;
    2879           42 :     case t_LFUN_MUL: f = eulerf_mul(an, p, prec); break;
    2880            0 :     case t_LFUN_CONJ: f = eulerf_conj(an, p, prec); break;
    2881           28 :     case t_LFUN_SYMPOW_ELL: f = eulerf_ellsympow(an, p); break;
    2882            0 :     case t_LFUN_GENUS2: f = eulerf_genus2(an, p); break;
    2883           14 :     case t_LFUN_TWIST: f = eulerf_twist(an, p, prec); break;
    2884           70 :     case t_LFUN_SHIFT: f = eulerf_shift(an, p, prec); break;
    2885           84 :     case t_LFUN_HGM: f = eulerf_hgm(an, p); break;
    2886           42 :     default: f = NULL; break;
    2887              :   }
    2888          952 :   if (!f) pari_err_DOMAIN("lfuneuler", "L", "Euler product", strtoGENstr("unknown"), an);
    2889          840 :   return f;
    2890              : }
    2891              : 
    2892              : GEN
    2893          749 : lfuneuler(GEN ldata, GEN p, long prec)
    2894              : {
    2895          749 :   pari_sp av = avma;
    2896          749 :   if (typ(p)!=t_INT || signe(p)<=0) pari_err_TYPE("lfuneuler", p);
    2897          742 :   ldata = ldata_newprec(lfunmisc_to_ldata_shallow(ldata), prec);
    2898          742 :   return gc_GEN(av, ldata_eulerf(ldata_get_an(ldata), p, prec));
    2899              : }
        

Generated by: LCOV version 2.0-1