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 - nflist.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.14.0 lcov report (development 27775-aca467eab2) Lines: 3102 3216 96.5 %
Date: 2022-07-03 07:33:15 Functions: 312 318 98.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Copyright (C) 2020  The PARI group.
       2             : 
       3             : This file is part of the PARI/GP package.
       4             : 
       5             : PARI/GP is free software; you can redistribute it and/or modify it under the
       6             : terms of the GNU General Public License as published by the Free Software
       7             : Foundation. It is distributed in the hope that it will be useful, but WITHOUT
       8             : ANY WARRANTY WHATSOEVER.
       9             : 
      10             : Check the License for details. You should have received a copy of it, along
      11             : with the package; see the file 'COPYING'. If not, write to the Free Software
      12             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      13             : 
      14             : #include "pari.h"
      15             : #include "paripriv.h"
      16             : 
      17             : #define DEBUGLEVEL DEBUGLEVEL_nflist
      18             : 
      19             : /* Code s: if s >= 0 number of complex embeddings; s = -1: all signatures;
      20             :  * s = -2: all signatures separated.
      21             :  * Known groups: C1 = 1T1, C2 = 2T1, C3 = 3T1, S3 = 3T2, C4 = 4T1, V4 = 4T2,
      22             :  * D4 = 4T3, A4 = 4T4, S4 = 4T5, C5 = 5T1, D5 = 5T2, F5 = M20 = 5T3, A5 = 5T4,
      23             :  * C6 = 6T1, S36 = D66 = 6T2, D612 = 6T3, A46 = 6T4, S3C3 = 6T5,
      24             :  * A462 = 6T6, S46P = 6T7, S46M = 6T8, C32C4 = 6T10, S462 = 6T11,
      25             :  * A56 = PSL25 = 6T12, C32D4 = 6T13,
      26             :  * C7 = 7T1, D7 = 7T2, M21 = 7T3, M42 = 7T4, C9 = 9T1, C3C3 = 9T2,
      27             :  * CL and DL for L prime. A5cond is A5 ordered by twist-minimal conductor.
      28             :  *
      29             :  * For each group G:
      30             :  * - makeG(GEN N, GEN F, long s, long prec):
      31             :  * fields of given Galois group G, absolute discriminant N, signature s, and
      32             :  * auxiliary field (possibly NULL) F.
      33             :  * - makeGvec(GEN X, GEN Xinf, GEN F, long s, long prec):
      34             :  * fields of given Galois group G, absolute discriminant between Xinf and X,
      35             :  * signature s, and auxiliary field (possibly NULL) F.
      36             :  * - makeGresolvent(GEN pol, long flag)
      37             :  * - makeGsome(long s, long n, long prec): find n fields of given Galois group
      38             :  * G and signature s, not necessarily the smallest; n is assumed small. Useful
      39             :  * only when makeG/makeGvec take a long time. */
      40             : 
      41             : /* Relations between discriminants:
      42             : * D = disc of quadratic subfield or resolvent; Dk = disc subfield of degree k.
      43             : * f,g are integers, not necessarily conductors.
      44             : *
      45             : * C_ell: f^(ell-1), conductor f; ell odd prime
      46             : * D_ell: (Df^2)^((ell-1)/2), (f) = cond. over quad. subfield; ell odd prime
      47             : * C4: D^3f^2 (D sum of 2 squares); "conductor" Df
      48             : * V4: D^2f^2 (D for any of the 3 max. subfields); conductor lcm(D1,D2)
      49             : * D4: D^2f; "conductor" Df
      50             : * A4: Df^2, D = g^2
      51             : * S4: Df^2
      52             : * F5 = M20: Df^4 or 25D f^4 iff 125|D (what f's ?)
      53             : * C6: D^3D3^2/gcd(D,D3)^2; conductor lcm(D,D3)
      54             : * D6 = D6(12): D^3 D3^2 / gcd(D,D3)^2 * (1 or 4)
      55             : * S3(6) = D6(6): D^3 f^4 = D3^2 D
      56             : * A4(6), S4(6)+: D3 * D4
      57             : * S4(6)-: D*D3*D4 / gcd(g,D)^2*(1,4,16); D4 = D3*g^2, D3 = Df^2, D4 = D3g^2
      58             : *         D*D3*D4 = D^3f^4g^2 = D3^3(g/f)^2 = D3^2*D*g^2=D4^3/(g^4f^2)
      59             : *         Disc = D3^2 D * (g * (1,2,4) / gcd(g,D))^2
      60             : *         16 iff v(D2)=2 and v(g)=2 or 3.
      61             : *         4 iff v(g)=1 or (v(D2)=2 and v(g)=4)
      62             : *         1 or 4 if v(D2)=3 and v(g)=4.
      63             : * C32C4: D D4 f^2
      64             : * S32: disc of 2 S3 subfields: D1F1^2, D2F2^2, D1, D2 fund. disc
      65             : *      disc = (D1D2)^3 / gcd(D1,D2)^4 * lcm(F1,F2)^2 * g^2
      66             : * M21: D^2f^6 (D = g^2) or 7^4 D^2 f^6 iff 49|D
      67             : * M42: Df^6 or 7^2 Df^6 iff 7^4|D or 7^4 Df^6 iff 7^5|D
      68             : * C9: D^4f^6
      69             : * C3xC3: lcm(D3, D3')^3
      70             : * D9: D^4 g^2 f^6 (disc subic subfield = Dg^2)
      71             : *
      72             : * Minimimal discriminants for each group, by s
      73             : * C1: [1]
      74             : * C2: [5, 3]
      75             : * C3: [49, 0]
      76             : * S3: [148, 23]
      77             : * C4: [1125, 0, 125]
      78             : * V4: [1600, 0, 144]
      79             : * D4: [725, 275, 117]
      80             : * A4: [26569, 0, 3136]
      81             : * S4: [1957, 283, 229]
      82             : * C5: [14641, 0, 0]
      83             : * D5: [160801, 0, 2209]
      84             : * F5: [2382032, 0, 35152]
      85             : * A5: [3104644, 0, 18496]
      86             : * C6: [300125, 0, 0, 16807]
      87             : * S36: [810448, 0, 0, 12167]
      88             : * D612: [2738000, 0, 66125, 14283]
      89             : * A46: [25969216, 0, 153664, 0]
      90             : * S3C3: [722000, 0, 0, 9747]
      91             : * A462: [434581, 103243, 31213, 0]
      92             : * S46+: [3356224, 0, 33856, 0]
      93             : * S46-: [7495014493, 0, 3241792, 778688]
      94             : * S32: [27848000, 0, 242000, 309123]
      95             : * C32C4: [55130625, 0, 525625, 0]
      96             : * S462: [1387029, 309123, 28037, 10051]
      97             : * C7: [594823321, 0, 0]
      98             : * D7: [192100033, 0, 0, 357911]
      99             : * M21: [1817487424, 0, 0, 0]
     100             : * M42: [12431698517, 0, 0, 38014691]
     101             : * C9: [16983563041, 0, 0, 0, 0]
     102             : * C3C3: [62523502209, 0, 0, 0, 0]
     103             : * D9: [1624709678881, 0, 0, 0, 775511104]
     104             : * C11: [41426511213649, 0, 0, 0, 0]
     105             : * D11: [3670285774226257, 0, 0, 0, 0, 129891985607] */
     106             : 
     107             : /* FIXME: export */
     108             : static long
     109       34348 : RgVV_nb(GEN v)
     110             : {
     111       34348 :   long i, l = lg(v), n = 0;
     112       69354 :   for (i = 1; i < l; i++) n += lg(gel(v,i)) - 1;
     113       34348 :   return n;
     114             : }
     115             : /* FIXME: export */
     116             : static GEN
     117       37253 : gtoset_shallow(GEN x)
     118             : {
     119       37253 :   GEN p = gen_indexsort_uniq(x, (void*)&cmp_universal, cmp_nodata);
     120       37248 :   return vecpermute(x, p);
     121             : }
     122             : 
     123             : static GEN
     124        2905 : closure(const char *s, GEN v) { return snm_closure(is_entry(s), v); }
     125             : 
     126             : /**************************************************************************/
     127             : /*                        Utility functions                               */
     128             : /**************************************************************************/
     129             : static long
     130          49 : divissquareall(GEN x, GEN y, GEN *f)
     131          49 : { GEN r, q = dvmdii(x, y, &r); return r == gen_0 && Z_issquareall(q,f); }
     132             : static long
     133          21 : divissquare(GEN x, GEN y) { return divissquareall(x, y, NULL); }
     134             : static long
     135          21 : divispowerall(GEN x, GEN y, ulong k, GEN *f)
     136          21 : { GEN r, q = dvmdii(x, y, &r); return r == gen_0 && Z_ispowerall(q,k,f); }
     137             : /* x / y if y | x, else NULL */
     138             : static GEN
     139       27161 : divide(GEN x, GEN y)
     140       27161 : { GEN r, q = dvmdii(x, y, &r); return r == gen_0? q: NULL; }
     141             : 
     142             : /* ceil(X^(1/n)) */
     143             : static long
     144         245 : ceilsqrtn(GEN X, long n)
     145             : {
     146         245 :   pari_sp av = avma;
     147         245 :   ulong x = itou(sqrtnint(X, n));
     148         245 :   if (cmpii(powuu(x, n), X) < 0) x++;
     149         245 :   return gc_long(av, x);
     150             : }
     151             : static long
     152         189 : ceilsqrt(GEN X)
     153             : {
     154         189 :   pari_sp av = avma;
     155             :   GEN r;
     156         189 :   ulong x = itou(sqrtremi(X, &r));
     157         189 :   return gc_long(av, r==gen_0? x: x+1);
     158             : }
     159             : static GEN
     160        1162 : gceilsqrtn(GEN X, long n)
     161             : {
     162        1162 :   GEN x = sqrtnint(X, n);
     163        1162 :   if (cmpii(powiu(x, n), X) < 0) x = addiu(x, 1);
     164        1162 :   return x;
     165             : }
     166             : /* assume X >= 0 or n odd */
     167             : static long
     168         427 : sceilsqrtn(long X, long n)
     169             : {
     170             :   ulong x, Xa;
     171         427 :   if (!X) return 0;
     172         427 :   Xa = labs(X); x = usqrtn(Xa, n);
     173         427 :   if (X > 0 && upowuu(x, n) != Xa) x++;
     174         427 :   return X > 0? (long)x: -(long)x;
     175             : }
     176             : /* ceil((X/Y)^1/n)*/
     177             : static long
     178          84 : ceilsqrtndiv(GEN X, GEN Y, long n)
     179             : {
     180          84 :   pari_sp av = avma;
     181          84 :   ulong x = itou(sqrtnint(divii(X, Y), n));
     182          84 :   if (cmpii(mulii(powuu(x, n), Y), X) < 0) x++;
     183          84 :   return gc_long(av, x);
     184             : }
     185             : static long
     186        1603 : ceilsqrtdiv(GEN X, GEN Y)
     187             : {
     188        1603 :   pari_sp av = avma;
     189        1603 :   GEN r, q = dvmdii(X, Y, &r);
     190        1603 :   ulong x = itou((r == gen_0)? sqrtremi(q, &r): sqrti(q));
     191        1603 :   return gc_long(av, r==gen_0? x: x+1);
     192             : }
     193             : static GEN
     194          28 : gceilsqrtdiv(GEN X, GEN Y)
     195             : {
     196          28 :   GEN r, q = dvmdii(X, Y, &r);
     197          28 :   q = (r == gen_0)? sqrtremi(q, &r): sqrti(q);
     198          28 :   return r == gen_0? q: addiu(q, 1);
     199             : }
     200             : static GEN
     201       38234 : gfloorsqrtdiv(GEN X, GEN Y) { return sqrti(divii(X, Y)); }
     202             : /* floor(X^(1/n)) */
     203             : static long
     204        3318 : floorsqrtn(GEN X, long n)
     205        3318 : { pari_sp av = avma; return gc_long(av, itou(sqrtnint(X, n))); }
     206             : static long
     207         189 : floorsqrt(GEN X)
     208         189 : { pari_sp av = avma; return gc_long(av, itou(sqrti(X))); }
     209             : /* floor((X/Y)^(1/n)) */
     210             : static long
     211        1617 : floorsqrtndiv(GEN X, GEN Y, long n)
     212        1617 : { pari_sp av = avma; return gc_long(av, itou(sqrtnint(divii(X,Y), n))); }
     213             : static long
     214       35981 : floorsqrtdiv(GEN X, GEN Y)
     215       35981 : { pari_sp av = avma; return gc_long(av, itou(gfloorsqrtdiv(X, Y))); }
     216             : static GEN
     217        5705 : ceildiv(GEN X, GEN Y)
     218             : {
     219        5705 :   GEN r, q = dvmdii(X, Y, & r);
     220        5704 :   return (r == gen_0)? q: addiu(q, 1);
     221             : }
     222             : 
     223             : static GEN
     224          35 : nfY(GEN T)
     225          35 : { T = shallowcopy(T); setvarn(T,1); return nfinit(T, DEFAULTPREC); }
     226             : static GEN
     227       20159 : bnfY(GEN T)
     228       20159 : { T = shallowcopy(T); setvarn(T,1); return Buchall(T, nf_FORCE, DEFAULTPREC); }
     229             : static GEN
     230       12229 : bnf_get_disc(GEN b) { return nf_get_disc(bnf_get_nf(b)); }
     231             : 
     232             : /* Compute n s.t. d | n <=> d^k | N. Return [n, factor(n)] */
     233             : static GEN
     234        1022 : cored(GEN N, long k)
     235             : {
     236        1022 :   GEN fa = Z_factor(N), P = gel(fa,1), E = gel(fa,2), n = gen_1;
     237        1022 :   long i, c, l = lg(P);
     238             : 
     239        1855 :   for (i = c = 1; i < l; i++)
     240             :   {
     241         833 :     long e = itou(gel(E,i));
     242         833 :     if (e >= k)
     243             :     {
     244         539 :       e /= k; n = mulii(n, powiu(gel(P,i), e));
     245         539 :       gel(P,c) = gel(P,i); gel(E,c) = utoipos(e); c++;
     246             :     }
     247             :   }
     248        1022 :   setlg(P,c); setlg(E,c); return mkvec2(n, fa);
     249             : }
     250             : 
     251             : /* return D = nfdisc(T), set d = coredisc */
     252             : static GEN
     253      644728 : nfcoredisc(GEN T, GEN *pd)
     254             : {
     255      644728 :   GEN D = nfdiscfactors(T), d = core(D); /* d = core(|D|) */
     256      644738 :   D = gel(D,1); if (signe(D) < 0) togglesign_safe(&d);
     257      644737 :   if (Mod4(d) != 1) d = shifti(d,2); /* = coredisc(D) */
     258      644741 :   *pd = d; return D;
     259             : }
     260             : static GEN
     261      629202 : nfcoredisc2(GEN T, GEN *pd, GEN *pf)
     262             : {
     263      629202 :   GEN D = nfcoredisc(T, pd);
     264      629202 :   if (pf) *pf = sqrti(diviiexact(D, *pd));
     265      629202 :   return D;
     266             : }
     267             : 
     268             : /* \prod {pr | ell} pr */
     269             : static GEN
     270        2849 : getpell(GEN nf, long ell, long *pteell)
     271             : {
     272        2849 :   GEN P = idealprimedec(nf, utoipos(ell));
     273        2849 :   *pteell = pr_get_e(gel(P,1)); return idealfactorback(nf, P, NULL, 0);
     274             : }
     275             : 
     276             : static void
     277        2821 : checkfield_i(GEN F, long d)
     278        2821 : { if (F && degpol(F) != d) pari_err_TYPE("nflist", F); }
     279             : static GEN
     280         427 : checkfield(GEN F, long d) { checkfield_i(F, d); return nfdisc(F); }
     281             : 
     282             : static long
     283       12649 : pol2s(GEN T) { return (degpol(T) - ZX_sturm_irred(T)) >> 1; }
     284             : 
     285             : static GEN
     286        2884 : sturmseparate(GEN V, long s, long deg)
     287             : {
     288             :   GEN w, C;
     289             :   long l, ls , i;
     290             : 
     291        2884 :   if (s != -2) return V;
     292         266 :   l = lg(V); ls = (deg >> 1) + 2;
     293         266 :   w = cgetg(ls, t_VEC);
     294         266 :   C = cgetg(ls, t_VECSMALL);
     295        1288 :   for (i = 1; i < ls; i++) { gel(w, i) = cgetg(l, t_VEC); C[i] = 1; }
     296       12446 :   for (i = 1; i < l; i++)
     297             :   {
     298       12180 :     long k = pol2s(gel(V, i)) + 1;
     299       12180 :     gmael(w, k, C[k]++) = gel(V, i);
     300             :   }
     301        1288 :   for (i = 1; i < ls; i++) setlg(gel(w, i), C[i]);
     302         266 :   return w;
     303             : }
     304             : 
     305             : /* fa = factorization of positive integer N. Are +N and/or -N fundamental ? */
     306             : static void
     307        1855 : fa_is_fundamental_pm(GEN N, GEN fa, long s, int *p, int *m)
     308             : {
     309        1855 :   GEN P = gel(fa,1), E = gel(fa,2);
     310        1855 :   long l = lg(P), i;
     311             :   ulong r, r4;
     312             : 
     313        1855 :   if (l == 1) { *m = 0; *p = (s <= 0); return; }
     314        1855 :   r = Mod16(N); r4 = r & 3UL;
     315        1855 :   if (!r || r4 == 2) { *p = *m = 0; return; } /* v_2 > 3 or N=2 mod 4 */
     316        1064 :   *p = (s <= 0);
     317        1064 :   *m = s? 1: 0;
     318        1064 :   if (odd(r))
     319             :   {
     320         630 :     if (r4 == 1) { *m = 0; if (!*p) return; }
     321         105 :     else         { *p = 0; if (!*m) return; }
     322         567 :     i = 1;
     323             :   }
     324             :   else
     325             :   { /* P[1] = 2 => 4 | N */
     326         434 :     if (r == 4)       { *p = 0; if (!*m) return; }
     327         231 :     else if (r == 12) { *m = 0; if (!*p) return; }
     328         399 :     i = 2;
     329             :   }
     330        1841 :   for (; i < l; i++)
     331         973 :     if (itou(gel(E,i)) > 1) { *p = *m = 0; return; }
     332             : }
     333             : /* if flag is set assume the odd part of N is squarefree */
     334             : static void
     335      693246 : uis_fundamental_pm_i(ulong N, long s, int *p, int *m, long flag)
     336             : {
     337             :   ulong r, r4;
     338             : 
     339      693246 :   if (N == 1UL) { *m = 0; *p = (s <= 0); return; }
     340      693246 :   r = N & 15UL; r4 = r & 3UL;
     341      693246 :   if (!r || r4 == 2) { *p = *m = 0; return; } /* v_2 > 3 or N=2 mod 4 */
     342      592407 :   *p = (s <= 0);
     343      592407 :   *m = s? 1: 0;
     344      592407 :   if (odd(r))
     345             :   {
     346      392447 :     if (r4 == 1) { *m = 0; if (!*p) return; }
     347      196292 :     else         { *p = 0; if (!*m) return; }
     348             :   }
     349             :   else
     350             :   { /* P[1] = 2 => 4 | N */
     351      200289 :     if (r == 4)       { *p = 0; if (!*m) return; }
     352      128988 :     else if (r == 12) { *m = 0; if (!*p) return; }
     353      171637 :     N >>= (r == 8? 3: 2); /* odd part */
     354             :   }
     355      481508 :   if (!flag && !uissquarefree(N)) { *p = *m = 0; }
     356             : }
     357             : static void
     358      684220 : uis_fundamental_pm(ulong N, long s, int *p, int *m)
     359      684220 : { uis_fundamental_pm_i(N, s, p, m, 0); }
     360             : 
     361             : static void
     362      303674 : is_fundamental_pm(GEN N, long s, int *p, int *m)
     363             : {
     364             :   ulong r, r4;
     365             : 
     366      303674 :   if (lgefint(N) == 3) { uis_fundamental_pm(N[2], s, p, m); return; }
     367          42 :   r = Mod16(N); r4 = r & 3UL;
     368          42 :   if (!r || r4 == 2) { *p = *m = 0; return; } /* v_2 > 3 or N=2 mod 4 */
     369          35 :   *p = (s <= 0);
     370          35 :   *m = s? 1: 0;
     371          35 :   if (odd(r))
     372             :   {
     373          14 :     if (r4 == 1) { *m = 0; if (!*p) return; }
     374           7 :     else         { *p = 0; if (!*m) return; }
     375             :   }
     376             :   else
     377             :   { /* P[1] = 2 => 4 | N */
     378          21 :     if (r == 4)       { *p = 0; if (!*m) return; }
     379          14 :     else if (r == 12) { *m = 0; if (!*p) return; }
     380          21 :     N = shifti(N, r == 8? -3: -2); /* odd part */
     381             :   }
     382          35 :   if (!Z_issquarefree(N)) { *p = *m = 0; }
     383             : }
     384             : static GEN
     385        3493 : fund_pm(GEN N, int p, int m)
     386             : {
     387        3493 :   if (p && m) return mkvec2(N, negi(N));
     388        3276 :   if (p) return mkvec(N);
     389        2800 :   if (m) return mkvec(negi(N));
     390        2163 :   return NULL;
     391             : }
     392             : static GEN
     393        5243 : ufund_pm(ulong N, int p, int m)
     394             : {
     395        5243 :   if (p && m) return mkvec2(utoipos(N), utoineg(N));
     396        5103 :   if (p) return mkvec(utoipos(N));
     397        4123 :   if (m) return mkvec(utoineg(N));
     398        2849 :   return NULL;
     399             : }
     400             : 
     401             : static GEN
     402         798 : divisorsdisc(GEN N, long s)
     403             : {
     404             :   GEN D, V;
     405         798 :   long l, c = 1, i;
     406             : 
     407         798 :   if (typ(N) == t_VEC)
     408             :   { /* [n, factor(n)]; assume n > 0 */
     409         679 :     GEN n = gel(N,1), fa = gel(N,2);
     410         679 :     if (Mod4(n) == 2) N = mkvec2(shifti(n,-1), rowsplice(fa, 1));
     411             :   }
     412             :   else
     413         119 :     if (Mod4(N) == 2) N = shifti(N, -1);
     414         798 :   D = divisors_factored(N); l = lg(D);
     415         798 :   V = cgetg(2 * l - 1, t_VEC);
     416        2653 :   for (i = 2; i < l; i++)
     417             :   {
     418        1855 :     GEN d = gel(D, i);
     419             :     int p, m;
     420        1855 :     fa_is_fundamental_pm(gel(d,1), gel(d,2), s, &p, &m);
     421        1855 :     if (p) gel(V, c++) = gel(d,1);
     422        1855 :     if (m) gel(V, c++) = negi(gel(d,1));
     423             :   }
     424         798 :   setlg(V, c); return V;
     425             : }
     426             : 
     427             : static int
     428        7731 : usum2sq(ulong m)
     429             : {
     430        7731 :   pari_sp av = avma;
     431             :   GEN fa, P, E;
     432        7731 :   long i, v2 = vals(m);
     433        7731 :   if (v2)
     434             :   {
     435        3771 :     if (v2 != 3) return 0;
     436        1007 :     m >>= 3;
     437             :   }
     438        4967 :   if ((m & 3L) != 1) return 0;
     439        4492 :   fa = factoru(m); P = gel(fa, 1); E = gel(fa, 2);
     440        7081 :   for (i = 1; i < lg(P); i++)
     441        4681 :     if (E[i] >= 2 || (P[i] & 3L) == 3) { set_avma(av); return 0; }
     442        2400 :   set_avma(av); return 1;
     443             : }
     444             : static int
     445         203 : sum2sq(GEN m)
     446             : {
     447         203 :   pari_sp av = avma;
     448             :   GEN fa, P, E;
     449             :   long i, v2;
     450         203 :   if (lgefint(m) == 3) return usum2sq(m[2]);
     451          18 :   v2 = vali(m);
     452          18 :   if (v2)
     453             :   {
     454           9 :     if (v2 != 3) return 0;
     455           8 :     m = shifti(m, -3);
     456             :   }
     457          17 :   if (Mod4(m) != 1) return 0;
     458          16 :   fa = Z_factor(m); P = gel(fa, 1); E = gel(fa, 2);
     459          31 :   for (i = 1; i < lg(P); i++)
     460          23 :     if (!equali1(gel(E,i)) || Mod4(gel(P,i)) == 3) { set_avma(av); return 0; }
     461           8 :   set_avma(av); return 1;
     462             : }
     463             : 
     464             : static int
     465      565925 : ok_int(GEN d, GEN X, GEN Xinf)
     466      565925 : { return (abscmpii(d, X) <= 0 && abscmpii(d, Xinf) >= 0); }
     467             : static int
     468        1792 : ok_intu(GEN d, ulong X, ulong Xinf)
     469        1792 : { return (abscmpiu(d, X) <= 0 && abscmpiu(d, Xinf) >= 0); }
     470             : 
     471             : static int
     472         917 : ok_disc(GEN d, GEN X, GEN Xinf)
     473             : {
     474         917 :   if (!Xinf) return absequalii(d, X);
     475         889 :   return ok_int(d, X, Xinf);
     476             : }
     477             : 
     478             : /* G cyclic galoisinit */
     479             : static GEN
     480        2625 : cyclicgalois(GEN bnr, GEN G, long *o)
     481             : {
     482        2625 :   GEN g = galoispermtopol(G, gel(gal_get_gen(G), 1));
     483        2625 :   *o = gal_get_orders(G)[1];
     484        2625 :   return bnrautmatrix(bnr, g); /* order o */
     485             : }
     486             : /* Cl_f / H cyclic of prime order, return i s.t bnr.cyc[i] is generator */
     487             : static long
     488        1281 : cyclicprimegen(GEN H)
     489             : {
     490        1281 :   long i, l = lg(H);
     491        1295 :   for (i = 1; i < l; i++) if (!is_pm1(gcoeff(H,i,i))) return i;
     492             :   return -1;/*LCOV_EXCL_LINE*/
     493             : }
     494             : /* k/Q cyclic and M the bnrautmatrix for the generator s of its Galois group
     495             :  * (action on bnr = Cl_f(k)). vH a vector of congruence subgroups for bnr,
     496             :  * attached to abelian extensions K/k of prime degree, assumed to be Galois
     497             :  * over Q [sf = f and sH = H]. Filter out the H corresponding to K/Q abelian */
     498             : static void
     499        1253 : nonabelianfilter(GEN vH, GEN M)
     500             : {
     501        1253 :   long i, c, l = lg(vH);
     502        2534 :   for (i = c = 1; i < l; i++)
     503             :   {
     504        1281 :     GEN v, H = gel(vH,i);
     505        1281 :     long k = cyclicprimegen(H);
     506        1281 :     v = shallowcopy(gel(M,k));
     507        1281 :     gel(v,k) = subiu(gel(v,k), 1);
     508        1281 :     if (!hnf_invimage(H, v)) gel(vH, c++) = H;
     509             :   }
     510        1253 :   setlg(vH, c);
     511        1253 : }
     512             : 
     513             : 
     514             : /* bnf attached to K. Cyclic extensions L/K of degree d and exact conductor
     515             :  * F; if F = [F,Finf]~, check that Finf | conductor | F;
     516             :  * check that |disc L/Q| in [Xinf,X] if not NULL. If G != NULL,
     517             :  * then K/Q = <s> is cyclic, we assume s.F = F and
     518             :  * G = [galoisinit(bnf), flag], with flag > 0 (resp. 0) to insist L be
     519             :  * Galois / Q (resp. not Galois). If flag = 2, insist that L/Q is non abelian.
     520             :  * In the non-Galois case, keep only one among isomorphic extensions attached
     521             :  * to sigma.H; sigma in Gal(K/Q). For simplicity assume the base is cyclic;
     522             :  * will extend it later if needed. */
     523             : static GEN
     524      184501 : mybnrclassfield_X(GEN bnf, GEN F, long d, GEN X, GEN Xinf, GEN G)
     525             : {
     526      184501 :   GEN gd = utoipos(d), Finf = NULL, bnr, L;
     527             :   long i, j, c, l;
     528             : 
     529      184498 :   if (typ(F) == t_COL) { Finf = gel(F,1); F = gel(F,2); }
     530      184498 :   bnr = bnrinitmod(bnf, F, 0, gd);
     531      184544 :   L = subgrouplist0(bnr, mkvec(gd), Finf? 1: 0); l = lg(L);
     532      184536 :   if (Finf)
     533             :   {
     534        2135 :     GEN Fi = idealinv(bnr, Finf);
     535        2282 :     for (i = c = 1; i < l; i++)
     536             :     { /* for now assume that F and Finf are finite */
     537         147 :       GEN f = gel(bnrconductor_raw(bnr, gel(L,i)), 1);
     538         147 :       if (equali1(Q_denom(idealmul(bnr, f, Fi)))) gel(L,c++) = gel(L,i);
     539             :     }
     540        2135 :     setlg(L, c); l = c;
     541             :   }
     542      184536 :   if (l == 1) return L;
     543       38038 :   if (!uisprime(d))
     544             :   {
     545         189 :     for (i = j = 1; i < l; i++)
     546          98 :       if (lg(smithclean(ZM_snf(gel(L,i)))) == 2) gel(L,j++) = gel(L,i);
     547          91 :     setlg(L, l = j); if (l == 1) return L;
     548             :   }
     549       37996 :   if (G)
     550             :   {
     551             :     GEN M;
     552        8533 :     long o, gal = itou(gel(G,2));
     553        8533 :     if (l == 2)
     554             :     {  /* => L[1] is fixed: must be Galois */
     555        8064 :       if (!gal) { setlg(L,1); return L; }
     556        1204 :       if (gal == 2)
     557             :       {
     558        1204 :         M = cyclicgalois(bnr, gel(G,1), &o);
     559        1204 :         nonabelianfilter(L, M);
     560             :       }
     561             :     }
     562             :     else
     563             :     {
     564        1421 :       M = cyclicgalois(bnr, gel(G,1), &o); /* assume cyclic for now */
     565        1421 :       if (gal)
     566             :       {
     567         224 :         for (i = j = 1; i < l; i++)
     568             :         {
     569         175 :           GEN H = gel(L,i);
     570         175 :           if (ZM_equal(bnrgaloisapply(bnr, M, H), H)) gel(L,j++) = H;
     571             :         }
     572          49 :         setlg(L, l = j);
     573          49 :         if (gal == 2) nonabelianfilter(L, M);
     574             :       }
     575             :       else
     576             :       {
     577        3766 :         for (i = 1; i < l; i++)
     578             :         {
     579        2394 :           GEN H = gel(L,i), K = bnrgaloisapply(bnr, M, H);
     580             :           long k;
     581             : 
     582             :           /* \sigma H = H <=> Galois : delete */
     583        2394 :           if (ZM_equal(K, H)) { L = vecsplice(L,i--); l--; continue; }
     584             :           /* else delete the rest of Galois orbit */
     585         952 :           for (j = 1; j < o; j++)
     586             :           {
     587         476 :             for (k = i+1; k < l; k++)
     588         476 :               if (ZM_equal(K, gel(L,k))) { L = vecsplice(L,k); l--; break; }
     589         476 :             if (j != o-1) K = bnrgaloisapply(bnr, M, K);
     590             :           }
     591             :         }
     592             :       }
     593             :     }
     594        2625 :     if ((l = lg(L)) == 1) return L;
     595             :   }
     596       31136 :   if (X)
     597             :   {
     598        1834 :     for (i = j = 1; i < l; i++)
     599             :     {
     600         917 :       GEN D = gel(bnrdisc(bnr, gel(L,i), 0), 3);
     601         917 :       if (ok_disc(D, X, Xinf)) gel(L,j++) = gel(L,i);
     602             :     }
     603         917 :     setlg(L, j); if (j == 1) return L;
     604             :   }
     605       30884 :   return shallowconcat1(bnrclassfield(bnr, L, 0, DEFAULTPREC));
     606             : }
     607             : static GEN
     608          28 : mybnrclassfield_N(GEN bnf, GEN F, GEN N, long d)
     609          28 : { return mybnrclassfield_X(bnf, F, d, N, NULL, NULL); }
     610             : static GEN
     611      145140 : mybnrclassfield(GEN bnf, GEN F, long d)
     612      145140 : { return mybnrclassfield_X(bnf, F, d, NULL, NULL, NULL); }
     613             : 
     614             : /* N > 1 */
     615             : static int
     616        6286 : checkcondell_i(GEN N, long ell, GEN D2, GEN *pP)
     617             : {
     618             :   GEN fa, P, E;
     619             :   long l, i, e;
     620             : 
     621        6286 :   if (typ(N) == t_VEC)
     622             :   {
     623        3887 :     fa = gel(N,2); P = gel(fa, 1); E = gel(fa, 2);
     624        3887 :     i = ZV_search(P, utoipos(ell));
     625        3895 :     if (!i) e = 0;
     626             :     else
     627             :     {
     628         796 :       e = itou(gel(E,i)); if (e != 2) return 0;
     629         126 :       P = vecsplice(P, i);
     630         126 :       E = vecsplice(E, i);
     631             :     }
     632             :   }
     633             :   else
     634             :   {
     635        2399 :     e = Z_lvalrem(N, ell, &N);
     636        2401 :     if (e != 0 && e != 2) return 0;
     637        2051 :     fa = Z_factor(N); P = gel(fa, 1); E = gel(fa, 2);
     638             :   }
     639        5269 :   l = lg(P);
     640        6500 :   for (i = 1; i < l; i++)
     641             :   {
     642        5385 :     GEN p = gel(P,i);
     643             :     long r;
     644        5385 :     if (!equaliu(gel(E,i), 1)) return 0;
     645        4905 :     r = umodiu(p, ell);
     646        4925 :     if (!D2) { if (r != 1) return 0; }
     647             :     else
     648             :     {
     649        2023 :       r -= kronecker(D2, p);
     650        2030 :       if (r && r != ell) return 0;
     651             :     }
     652             :   }
     653        1115 :   *pP = P; return 1;
     654             : }
     655             : /* ell odd prime, N potential conductor for C_ell field, *pP contains
     656             :  * the prime divisors of N different from ell */
     657             : static int
     658        4056 : checkcondCL(GEN N, long ell, GEN *pP)
     659        4056 : { GEN n = typ(N) == t_VEC? gel(N, 1): N;
     660        4056 :   return odd(Mod4(n)) && !equali1(n) && checkcondell_i(N, ell, NULL, pP); }
     661             : /* D2 fundamental discriminant, ell odd prime, N potential conductor for
     662             :  * D_ell field over Q(sqrt(D2)) */
     663             : static int
     664       10430 : checkcondDL(GEN D2, GEN N, long ell, GEN *pP)
     665             : {
     666             :   ulong N4;
     667       10430 :   if (!umodiu(D2, ell))
     668             :   {
     669        1771 :     long v = Z_lvalrem(N, ell, &N);
     670        1771 :     if (v && v > 2) return 0;
     671             :   }
     672       10430 :   if (equali1(N)) { *pP = cgetg(1,t_VEC); return 1; }
     673        3850 :   N4 = Mod4(N);
     674        3850 :   return N4 && (N4 != 2 || ell == 3) && checkcondell_i(N, ell, D2, pP);
     675             : }
     676             : 
     677             : static GEN
     678       57434 : myshallowconcat1(GEN V)
     679             : {
     680       57434 :   if (lg(V) == 1) return V;
     681       16505 :   return shallowconcat1(V);
     682             : }
     683             : 
     684             : static GEN
     685       31645 : _nfsubfields(GEN pol, long d) { return nfsubfields0(pol, d, 1); }
     686             : static GEN
     687       28439 : _nfsubfields1(GEN pol, long d) { return gel(_nfsubfields(pol, d), 1); }
     688             : static GEN
     689          63 : mynfsubfields(GEN pol, long d)
     690             : {
     691          63 :   GEN V = _nfsubfields(pol, d), W;
     692          63 :   long l = lg(V), i;
     693          63 :   W = cgetg(l, t_VEC);
     694         273 :   for (i = 1; i < l; i++) gel(W,i) = polredabs(gel(V,i));
     695          63 :   return W;
     696             : }
     697             : static GEN
     698         217 : mynfsubfield(GEN pol, long d)
     699             : {
     700         217 :   if (d == 2 && (degpol(pol) & 3) == 2)
     701          70 :     return quadpoly_i(quaddisc(ZX_disc(pol)));
     702         147 :   return polredabs(gel(_nfsubfields(pol, d), 1));
     703             : }
     704             : 
     705             : /* global checks to be done:
     706             : -- in nflist: if s > deg / 2, return empty.
     707             : -- in nfresolvent: check polynomial of correct degree.
     708             : */
     709             : 
     710             : /***************************************************************/
     711             : 
     712             : static GEN
     713          63 : makeC1(GEN N, GEN field, long s)
     714             : {
     715          63 :   checkfield_i(field, 1);
     716          63 :   if (!equali1(N)) return NULL;
     717          63 :   return mkvec(s != -2? pol_x(0): mkvec(pol_x(0)));
     718             : }
     719             : static GEN
     720          21 : makeC1resolvent(long flag)
     721          21 : { return odd(flag)? mkvec2(pol_x(0), gen_1): pol_x(0); }
     722             : static GEN
     723          28 : makeC1vec(GEN Xinf, GEN field, long s) { return makeC1(Xinf, field, s); }
     724             : 
     725             : /**********************************************************************/
     726             : /*                                 C2                                 */
     727             : /**********************************************************************/
     728             : static GEN
     729         140 : makeC2(GEN N, GEN field, long s)
     730             : {
     731         140 :   GEN V = NULL;
     732             :   long l, i;
     733             :   int p, m;
     734             : 
     735         140 :   checkfield_i(field, 1);
     736         140 :   if (equali1(N) || Mod4(N) == 2) return NULL;
     737         112 :   is_fundamental_pm(N, s, &p, &m);
     738         112 :   if (!(V = fund_pm(N, p, m))) return NULL;
     739          98 :   l = lg(V);
     740         238 :   for (i = 1; i < l; i++) gel(V, i) = quadpoly_i(gel(V, i));
     741          98 :   return sturmseparate(V, s, 2);
     742             : }
     743             : 
     744             : static GEN
     745          14 : makeC2resolvent(GEN pol, long flag)
     746          14 : { return odd(flag)? mkvec2(pol_x(0), absi_shallow(nfdisc(pol))): pol_x(0); }
     747             : 
     748             : static GEN
     749         161 : makeC2vec(GEN X, GEN Xinf, GEN field, long s)
     750             : {
     751         161 :   long M, cv, cw, l = itou(subii(X, Xinf)) + 1;
     752             :   GEN v, w;
     753             : 
     754         161 :   checkfield_i(field, 1);
     755         161 :   v = (s <= 0)? cgetg(l, t_VEC): NULL;
     756         161 :   w = s? cgetg(l, t_VEC): NULL;
     757      300342 :   for (M = equali1(Xinf)? 2: 1, cv = cw = 1; M < l; M++)
     758             :   {
     759      300181 :     GEN N = addiu(Xinf, M);
     760             :     int p, m;
     761      300181 :     is_fundamental_pm(N, s, &p, &m);
     762      300181 :     if (p) gel(v, cv++) = quadpoly_i(N);
     763      300181 :     if (m) gel(w, cw++) = quadpoly_i(negi(N));
     764             :   }
     765         161 :   if (cv == 1 && cw == 1) return NULL;
     766         161 :   switch (s)
     767             :   {
     768          49 :     case 0:  setlg(v, cv); return v;
     769          49 :     case 1:  setlg(w, cw); return w;
     770          56 :     case -1: setlg(v, cv); setlg(w, cw); return shallowconcat(v, w);
     771           7 :     default: setlg(v, cv); setlg(w, cw); return mkvec2(v, w);
     772             :   }
     773             : }
     774             : 
     775             : /**********************************************************************/
     776             : /*                                 C3                                 */
     777             : /**********************************************************************/
     778             : /* \prod x[i]^e[i], e[i] in {0,1} */
     779             : static GEN
     780       23954 : eltlist2(GEN nf, GEN x)
     781             : {
     782       23954 :   long i, j, c, l = lg(x);
     783             :   GEN v;
     784       23954 :   if (l == 1) return mkvec(gen_1);
     785       23954 :   v = cgetg((1 << (l-1))+1, t_VEC);
     786       23954 :   gel(v,1) = gen_1;
     787       23954 :   gel(v,2) = gel(x,1);
     788       33733 :   for (i = c = 2; i < l; i++, c <<= 1)
     789       30163 :     for (j = 1; j <= c; j++) gel(v, c + j) = nfmul(nf, gel(v,j), gel(x,i));
     790       23954 :   return v;
     791             : }
     792             : /* { x[1][1] * \prod_i>=2 x[i][e_i], (e) in {1,2}^(#x-1)} */
     793             : static GEN
     794         112 : mullist2(GEN x)
     795             : {
     796         112 :   long i, j, c, l = lg(x);
     797             :   GEN v;
     798         112 :   if (l == 2) return mkvec(gmael(x,1,1));
     799          14 :   v = cgetg((1 << (l-2))+1, t_VEC);
     800          14 :   gel(v,1) = gel(v,2) = gmael(x,1,1);
     801          28 :   for (i = 2, c = 1; i < l; i++, c <<= 1)
     802          28 :     for (j = 1; j <= c; j++)
     803             :     {
     804          14 :       gel(v, c + j) = gmul(gel(v, j), gmael(x,i,2));
     805          14 :       gel(v, j) = gmul(gel(v, j), gmael(x,i,1));
     806             :     }
     807          14 :   return v;
     808             : }
     809             : 
     810             : static GEN
     811         126 : makepolC3(GEN n, GEN u, long fl3)
     812             : {
     813         126 :   GEN T = cgetg(6, t_POL), n3, nu27;
     814         126 :   T[1] = evalsigne(1) | evalvarn(0);
     815         126 :   gel(T, 5) = gen_1;
     816         126 :   gel(T, 4) = fl3 ? gen_m1 : gen_0;
     817         126 :   if (!fl3)
     818          49 :   { n3 = divis(n, -3); nu27 = mulii(n, u); }
     819             :   else
     820          77 :   { n3 = divis(subiu(n, 1), -3); nu27 = addiu(mulii(n, subiu(u, 3)), 1); }
     821         126 :   gel(T, 3) = n3;
     822         126 :   gel(T, 2) = divis(nu27, -27); return T;
     823             : }
     824             : 
     825             : static GEN
     826         126 : decp(GEN Q, GEN t, GEN p)
     827             : {
     828             :   GEN u, v, z;
     829         126 :   if (equaliu(p, 3)) { u = utoineg(3); v = utoipos(3); }
     830             :   else
     831             :   {
     832          91 :     GEN uv = qfbsolve(Q, shifti(p, 2), 2);
     833          91 :     u = gel(uv,1); if (umodiu(u, 3) == 1) togglesign(u);
     834          91 :     v = muliu(gel(uv,2), 3); if (signe(v) < 0) togglesign(v);
     835             :   }
     836         126 :   z = gadd(gmul(v, t), shifti(subii(u, v), -1));
     837         126 :   return mkvec2(z, conj_i(z));
     838             : }
     839             : 
     840             : static int
     841         371 : checkcondC3(GEN n, GEN *pP)
     842             : {
     843         371 :   GEN fa = NULL, P, E;
     844             :   long l, i, n27;
     845             : 
     846         371 :   *pP = NULL;
     847         371 :   if (typ(n) == t_VEC) { fa = gel(n,2); n = gel(n,1); }
     848         371 :   if (cmpiu(n, 7) < 0 || !mpodd(n)) return 0;
     849         133 :   n27 = umodiu(n, 27);
     850         133 :   switch(n27 % 3)
     851             :   {
     852           7 :     case 2: return 0;
     853          77 :     case 1: i = 1; break;
     854          49 :     default: i = 2; if (n27 != 9 && n27 != 18) return 0;
     855             :   }
     856         112 :   if (!fa) fa = Z_factor(n);
     857         112 :   P = gel(fa, 1); E = gel(fa, 2); l = lg(P);
     858         203 :   for (; i < l; i++)
     859          91 :     if (umodiu(gel(P,i), 3) != 1 || !equali1(gel(E,i))) return 0;
     860         112 :   *pP = P; return 1;
     861             : }
     862             : 
     863             : static GEN
     864         112 : makeC3_i(GEN sqN, GEN P)
     865             : {
     866         112 :   GEN v, t, Q = mkqfb(gen_1, gen_0, utoipos(27), utoineg(108));
     867         112 :   long i, j, l, n = lg(P)-1, fl3 = umodiu(gel(P,1), 3);
     868             : 
     869         112 :   t = quadgen0(utoineg(3), 1); v = cgetg(n+1, t_VEC);
     870         238 :   for (i = 1; i <= n; i++) gel(v,i) = decp(Q, t, gel(P,i));
     871         112 :   v = mullist2(v); l = lg(v);
     872         238 :   for (j = 1; j < l; j++) gel(v,j) = makepolC3(sqN, gtrace(gel(v,j)), fl3);
     873         112 :   return v;
     874             : }
     875             : /* makeC3(f^2, 0) */
     876             : static GEN
     877         336 : makeC3_f(GEN f)
     878             : {
     879             :   GEN P;
     880         336 :   return checkcondC3(f, &P)? makeC3_i(f, P): cgetg(1, t_VEC);
     881             : }
     882             : static GEN
     883          70 : vecs(long ns, GEN x)
     884          70 : { GEN v = const_vec(ns, cgetg(1,t_VEC)); gel(v,1) = x; return v; }
     885             : static GEN
     886          14 : vecs14(GEN x, GEN y) { GEN v = cgetg(1,t_VEC); return mkvec4(x,v,v,y); }
     887             : 
     888             : static GEN
     889          77 : makeC3(GEN N, GEN field, long s)
     890             : {
     891             :   GEN v, f, P;
     892             : 
     893          77 :   checkfield_i(field, 1);
     894          77 :   if (s > 0 || cmpiu(N, 49) < 0 || !Z_issquareall(N, &f)
     895          77 :       || !checkcondC3(f, &P)) return NULL;
     896          14 :   v = makeC3_i(f, P); return s == -2 ? vecs(2, v): v;
     897             : }
     898             : 
     899             : static GEN
     900          14 : makeC3resolvent(GEN pol, long flag)
     901          14 : { return odd(flag)? mkvec2(pol_x(0), sqrti(nfdisc(pol))): pol_x(0); }
     902             : 
     903             : GEN
     904        4161 : nflist_C3_worker(GEN gv, GEN T)
     905             : {
     906        4161 :   long v = itos(gv), sX = T[1], sXinf = T[2], c, r, u;
     907        4162 :   long v227 = 27 * v * v, limu = usqrt((sX << 2) - v227);
     908        4162 :   GEN V = cgetg(limu + 2, t_VEC);
     909             : 
     910        4164 :   if (odd(limu - v)) limu--; /* make sure u = v (mod 2) */
     911     1528456 :   for (u = -limu, r = smodss(u, 9), c = 1; u <= limu; u += 2, r += 2)
     912             :   {
     913     1524528 :     if (r >= 9) r -= 9; /* r = u % 9 */
     914     1524528 :     if (r == 2 || r == 5 || r == 6 || r == 8) /* u = 2 (mod 3) or 6 (mod 9) */
     915             :     {
     916             :       long e;
     917      687753 :       if (ugcd(labs(u), v) > 2) continue;
     918      500099 :       e = (u * u + v227) >> 2; /* conductor, disc = e^2 */
     919      500099 :       if (e < sXinf) continue;
     920      500099 :       if (r == 6) e /= 9; /* 9 | e */
     921      500099 :       if (!uissquarefree(e)) continue;
     922      405773 :       gel(V, c++) = r==6? mkvecsmall4(1, 0, -3 * e, -e * u / 3)
     923      392755 :                         : mkvecsmall4(1, -1, (1-e) / 3, -(1 + e * (u-3)) / 27 );
     924             :     }
     925             :   }
     926        3928 :   setlg(V, c); return V;
     927             : }
     928             : 
     929             : static GEN
     930         210 : zvV_to_ZXV(GEN v)
     931             : {
     932         210 :   long i, l = lg(v);
     933         210 :   GEN w = cgetg(l, t_VEC);
     934      336770 :   for (i = 1; i < l; i++) gel(w,i) = gtopoly(gel(v,i), 0);
     935         210 :   return w;
     936             : }
     937             : static GEN
     938         189 : C3vec(GEN V, long s)
     939             : {
     940         189 :   if (s != -2) return zvV_to_ZXV(V);
     941           7 :   retmkvec2(zvV_to_ZXV(V), cgetg(1,t_VEC));
     942             : }
     943             : 
     944             : /* t a C3 t_VECSMALL generated by C3_worker. Return its conductor f */
     945             : static long
     946      414904 : uC3pol_f(GEN t) { return - t[2] - 3 * t[3]; }
     947             : /* t a C3 t_POL = gtopoly(C3_worker t_VECSMALL) */
     948             : static GEN
     949         860 : C3pol_f(GEN t) { return subii(mulsi(-3, gel(t,3)), gel(t,4)); }
     950             : /* C3vec for discriminant f^2, f in [sX,sXinf] */
     951             : static GEN
     952         224 : C3vec_F(long sX, long sXinf, GEN *pF)
     953             : {
     954         224 :   GEN v, F, perm, T = mkvecsmall2(sX, sXinf);
     955         224 :   long i, l, lim = usqrt((sX << 2) / 27);
     956         224 :   v = gen_parapply(closure("_nflist_C3_worker", mkvec(T)), identity_ZV(lim));
     957         224 :   v = myshallowconcat1(v); l = lg(v); if (l == 1) return NULL;
     958         224 :   F = cgetg(l, t_VECSMALL);
     959      415128 :   for (i = 1; i < l; i++) F[i] = uC3pol_f(gel(v,i));
     960         224 :   perm = vecsmall_indexsort(F);
     961         224 :   if (pF) *pF = vecsmallpermute(F, perm);
     962         224 :   return vecpermute(v, perm);
     963             : }
     964             : static GEN
     965         217 : makeC3vec(GEN X, GEN Xinf, GEN field, long s)
     966             : {
     967             :   GEN v;
     968         217 :   checkfield_i(field, 1);
     969         217 :   if (s > 0 || !(v = C3vec_F(floorsqrt(X), ceilsqrt(Xinf), NULL))) return NULL;
     970         189 :   return C3vec(v, s);
     971             : }
     972             : 
     973             : /**********************************************************************/
     974             : /*                                 S3                                 */
     975             : /**********************************************************************/
     976             : /* Quadratic resolvent field. */
     977             : 
     978             : static GEN makeDL(long ell, GEN N, GEN field, long s);
     979             : static GEN makeDLvec(long ell, GEN X, GEN Xinf, GEN field, long s);
     980             : 
     981             : /* Cubic programs from KB and HC */
     982             : #define min(a, b) ((a) >= (b) ? b : a)
     983             : #define max(a, b) ((a) >= (b) ? a : b)
     984             : 
     985             : static GEN
     986     1087216 : checkU(long a, long b, long c, long d, long P, long Q, long R, long D)
     987             : {
     988     1087216 :   long t, f = cgcd(cgcd(P, Q), R);
     989             :   GEN F;
     990             : 
     991     1083106 :   if (odd(f)) { long e = D & 15L; if (e == 0 || e == 12) return NULL; }
     992      237346 :   else if ((D & 7L) == 0) return NULL;
     993      815375 :   if (f % 3 == 0)
     994             :   {
     995       86020 :     if ((a % 9 == 0) || (a % 3 && (d % 9 == 0))) return NULL;
     996       77468 :     if ((a % 3) && (d % 3))
     997             :     {
     998       47918 :       long e = (a - d) % 3 ? - 1 : 1;
     999       47918 :       if ((a + c - e * (b + d)) % 9 == 0) return NULL;
    1000             :     }
    1001       62196 :     if (!uissquarefree(f / 9)) return NULL;
    1002             :   }
    1003      729355 :   else if (D % 27 == 0 || !uissquarefree(f)) return NULL;
    1004     1570633 :   t = labs(D) / (f * f); t >>= vals(t); while (t % 3 == 0) t /= 3;
    1005      729630 :   if (cgcd(t, f) > 1 || !uissquarefree(t)) return NULL;
    1006      689134 :   F = cgetg(6, t_POL); F[1] = evalsigne(1)|evalvarn(0);
    1007      689229 :   gel(F,2) = stoi(d * a * a);
    1008      688688 :   gel(F,3) = stoi(c * a);
    1009      688241 :   gel(F,4) = stoi(b);
    1010      688389 :   gel(F,5) = gen_1; return F;
    1011             : }
    1012             : 
    1013             : /* ceil(m/d), assume d != 0 */
    1014             : static long
    1015     2135507 : sceildiv(long m, long d)
    1016             : {
    1017             :   long q;
    1018     2135507 :   if (d == 1) return m;
    1019     1893349 :   if (!m) return 0;
    1020     1891586 :   if (d < 0) { d = -d; m = -m; }
    1021     1891586 :   if (m < 0) return -((-m) / d);
    1022      368263 :   q = m / d; return m%d? q+1: q;
    1023             : }
    1024             : /* floor(m/d), assume d != 0 */
    1025             : static long
    1026     1180190 : sfloordiv(long m, long d)
    1027             : {
    1028             :   long q;
    1029     1180190 :   if (d == 1) return m;
    1030     1060532 :   if (!m) return 0;
    1031     1045863 :   if (d < 0) { d = -d; m = -m; }
    1032     1045863 :   if (m > 0) return m / d;
    1033      125617 :   q = -((-m) / d); return (-m)%d? q-1: q;
    1034             : }
    1035             : 
    1036             : GEN
    1037         427 : nflist_S3R_worker(GEN ga, GEN S)
    1038             : {
    1039         427 :   long a = itos(ga), a3 = 3 * a, a9 = 9 * a, b, c, d, ct = 1;
    1040         427 :   long x = S[1], xinf = S[2], sqx = S[3], cplus = S[4], cminus = S[5];
    1041         427 :   long cmin = S[6], Dmin = S[7], Dsup = S[8], bsup = S[9], binf = S[10];
    1042         427 :   long csupa = usqrtn(cplus / a, 3), cinfa = sceilsqrtn(sceildiv(cminus, a), 3);
    1043         427 :   long dsupa = Dsup / a, dinfa = sceildiv(Dmin, a);
    1044         427 :   GEN RET = cgetg(x / 3, t_VEC);
    1045             : 
    1046       10772 :   for (b = binf; b <= bsup; b++)
    1047             :   {
    1048       10345 :     long cinf = cinfa, csup = csupa, dinfb = dinfa, dsupb = dsupa;
    1049       10345 :     long bb = b * b, b3 = 3 * b, gcdab = cgcd(a, b);
    1050       10352 :     if (b)
    1051             :     {
    1052        9929 :       long bbb = bb * b, sqxb = sqx / labs(b), m, M;
    1053        9929 :       if (b < 0)
    1054             :       {
    1055        4664 :         cinf = -sqxb; csup = -1;
    1056        4664 :         M = sfloordiv(cminus,bbb);
    1057        4664 :         m = sceildiv(cplus, bbb);
    1058             :       }
    1059             :       else
    1060             :       {
    1061        5265 :         cinf = cmin; csup = minss(csup, sqxb);
    1062        5265 :         M = cplus / bbb;
    1063        5265 :         m = sceildiv(cminus, bbb);
    1064             :       }
    1065        9930 :       dsupb = minss(dsupb, M);
    1066        9928 :       dinfb = maxss(dinfb, m); cinf = maxss(cinfa, cinf);
    1067             :     }
    1068      240710 :     for (c = cinf; c <= csup; c++)
    1069             :     {
    1070      229890 :       long dsup, dinf, gcdabc = cgcd(gcdab, c);
    1071      229713 :       long bc = b * c, cc = c * c, P = bb - a3 * c;
    1072      229713 :       dsup = minss(dsupb, sfloordiv(bc, a9)); /* Q >= 0 */
    1073             :       /* bc-9ad <= 4x / 3c^2 */
    1074      230225 :       dinf = c? maxss(dinfb, sceildiv(bc - ((4 * x) / (cc * 3)), a9)): dinfb;
    1075     2802075 :       for (d = dinf; d <= dsup; d++)
    1076             :       {
    1077             :         long Q, R, D, DF;
    1078             :         GEN F;
    1079     2571718 :         if (cgcd(gcdabc, d) > 1) continue;
    1080     2421298 :         Q = bc - a9 * d; if (Q < 0 || Q > P) continue;
    1081      877593 :         if (Q == 0 && b <= 0) continue;
    1082      868743 :         R = cc - b3 * d; if (P > R) continue;
    1083      514251 :         D = 4 * P * R - Q * Q; DF = D / 3; if (DF > x || DF < xinf) continue;
    1084      229840 :         if (P == Q && (Q == R || labs(b) >= labs(3 * a - b))) continue;
    1085      221429 :         if (P == R && (a > labs(d) || (a == labs(d) && labs(b) >= labs(c))))
    1086        2463 :           continue;
    1087      218966 :         if ((F = checkU(a, b, c, d, P, Q, R, D))) gel(RET, ct++) = F;
    1088             :       }
    1089             :     }
    1090             :   }
    1091         427 :   setlg(RET, ct); return RET;
    1092             : }
    1093             : 
    1094             : /* x >= xinf >= 1 */
    1095             : static GEN
    1096         203 : cubicreal(long x, long xinf)
    1097             : {
    1098             :   double sqx, sqx4, sq13, sq3x;
    1099             :   long A, bsup, binf, cmin, cplus, cminus, Dmin, Dsup;
    1100             :   GEN V, S;
    1101             : 
    1102         203 :   if (x < 148) return NULL;
    1103         182 :   sqx = sqrt((double)x); sq3x = sqrt((double)(3 * x)); sqx4 = sqrt(sqx);
    1104         182 :   sq13 = sqrt(13.);
    1105         182 :   cplus = ((-35 + 13 * sq13) * x) / 216;
    1106         182 :   cminus = ceil((-(35 + 13 * sq13) * x) / 216);
    1107         182 :   cmin = ceil(-sq3x / 4);
    1108         182 :   Dmin = ceil(-4./27 * sqx);
    1109         182 :   Dsup = sq3x / 36;
    1110         182 :   A = floor(sqx4 * 2. / sqrt(27));
    1111         182 :   bsup = floor(sqx4 * 2. / sqrt(3));
    1112         182 :   binf = ceil(-sqx4);
    1113         182 :   S = mkvecsmalln(10, x, xinf, (long)sqx, cplus, cminus, cmin, Dmin, Dsup,
    1114             :                   bsup, binf);
    1115         182 :   V = gen_parapply(closure("_nflist_S3R_worker", mkvec(S)), identity_ZV(A));
    1116         182 :   V = myshallowconcat1(V); return lg(V) == 1? NULL: V;
    1117             : }
    1118             : 
    1119             : GEN
    1120        1029 : nflist_S3I_worker(GEN ga, GEN S)
    1121             : {
    1122        1029 :   long a = itos(ga), a3 = a * 3, a9 = a * 9, b, c, d, ct = 1;
    1123        1029 :   long x = S[1], xinf = S[2], cplus = S[3], Dsup = S[4], limb = S[5];
    1124        1029 :   long x4 = x * 4, csupa = usqrtn(cplus / a, 3), dsupa = Dsup / a;
    1125        1029 :   GEN RET = cgetg(x, t_VEC);
    1126             : 
    1127       19440 :   for (b = 0; b <= limb; b++)
    1128             :   {
    1129       18411 :     long b3 = b * 3, bb = b * b, gcdab = cgcd(a, b);
    1130       18420 :     long apb = a + b, amb = a - b;
    1131       18420 :     long dsupb = b? minuu(dsupa, cplus / (bb * b)): dsupa;
    1132       18423 :     long csup = b? min(csupa, 4 * Dsup / b): csupa;
    1133      973750 :     for (c = -csup; c <= csup; c++)
    1134             :     {
    1135      957877 :       long dsup = dsupb, dinf = b? -dsupb: 1, gcdabc = cgcd(gcdab, c);
    1136      958089 :       long bc = b * c, cc = c * c, P = bb - a3 * c;
    1137      958089 :       if (c)
    1138             :       { /* c^2|bc-9ad| <= 4x */
    1139      942392 :         long t = x4 / cc;
    1140      942392 :         dsup = minss(dsup, sfloordiv(bc + t, a));
    1141      945234 :         dinf = maxss(dinf, sceildiv(bc - t, a));
    1142             :       }
    1143      963136 :       dinf = maxss(dinf, sceildiv(-amb * (amb + c) + 1, a));
    1144      963751 :       dsup = minss(dsup, (apb * (apb + c) - 1) / a);
    1145    21158441 :       for (d = dinf; d <= dsup; d++)
    1146             :       {
    1147             :         GEN F;
    1148             :         long Q, R, D, DF;
    1149    20203114 :         if (!d || cgcd(gcdabc, d) > 1) continue;
    1150    18506358 :         if (d * (d - b) + a * (c - a) <= 0) continue;
    1151    12308537 :         Q = bc - a9 * d;
    1152    12308537 :         R = cc - b3 * d; D = 4 * P * R - Q * Q; DF = D / 3;
    1153    12308537 :         if (DF > -xinf || DF < -x) continue;
    1154      866546 :         if ((F = checkU(a, b, c, d, P, Q, R, D))) gel(RET, ct++) = F;
    1155             :       }
    1156             :     }
    1157             :   }
    1158        1029 :   setlg(RET, ct); return RET;
    1159             : }
    1160             : 
    1161             : static GEN
    1162         175 : cubicimag(long x, long xinf)
    1163             : {
    1164             :   double sqx, sqx4;
    1165             :   long lima, limb, Dsup, cplus;
    1166             :   GEN V, S;
    1167             : 
    1168         175 :   if (x < 31) return NULL;
    1169         168 :   sqx = sqrt((double)x / 27); sqx4 = sqrt(sqx);
    1170         168 :   cplus = (11 + 5 * sqrt(5.)) / 8 * x;
    1171         168 :   Dsup = 3 * sqx;
    1172         168 :   lima = 2 * sqx4;
    1173         168 :   limb = sqrt(3.) * 2 * sqx4;
    1174         168 :   S = mkvecsmall5(x, xinf, cplus, Dsup, limb);
    1175         168 :   V = gen_parapply(closure("_nflist_S3I_worker", mkvec(S)), identity_ZV(lima));
    1176         168 :   V = myshallowconcat1(V); return lg(V) == 1? NULL: V;
    1177             : }
    1178             : 
    1179             : static GEN
    1180          14 : makeS3resolvent(GEN T, long flag)
    1181             : {
    1182          14 :   GEN P, d, f = NULL;
    1183          14 :   (void)nfcoredisc2(T, &d, odd(flag)? &f: NULL);
    1184          14 :   P = quadpoly_i(d); return f? mkvec2(P, f): P;
    1185             : }
    1186             : 
    1187             : static GEN
    1188        1316 : makeS3vec(GEN X, GEN Xinf, GEN field, long s)
    1189             : {
    1190             :   GEN R, I;
    1191             :   long x, xinf;
    1192             : 
    1193        1316 :   if (field) return makeDLvec(3, X, Xinf, field, s);
    1194         245 :   x = itos(X); xinf = itos(Xinf);
    1195         245 :   R = (s <= 0)? cubicreal(x, xinf): NULL;
    1196         245 :   I = s? cubicimag(x, xinf): NULL;
    1197         245 :   switch (s)
    1198             :   {
    1199          70 :     case 0: return R;
    1200          42 :     case 1: return I;
    1201         119 :     case -1: return R? (I? shallowconcat(R, I): R): I;
    1202          14 :     default: if (!R && !I) return NULL; /* -2 */
    1203          14 :              return mkvec2(R? R: cgetg(1,t_VEC), I? I: cgetg(1,t_VEC));
    1204             :   }
    1205             : }
    1206             : 
    1207             : /**********************************************************************/
    1208             : /*                                 C4                                 */
    1209             : /**********************************************************************/
    1210             : 
    1211             : static GEN
    1212       23640 : makepolC4(GEN S, GEN T)
    1213             : {
    1214       23640 :   GEN V = cgetg(7, t_POL);
    1215       23658 :   V[1] = evalsigne(1)|evalvarn(0);
    1216       23658 :   gel(V, 6) = gen_1;
    1217       23658 :   gel(V, 5) = gen_0;
    1218       23658 :   gel(V, 4) = S;
    1219       23658 :   gel(V, 3) = gen_0;
    1220       23658 :   gel(V, 2) = T; return V;
    1221             : }
    1222             : 
    1223             : static GEN
    1224       27677 : C4qfbsolve(GEN Q, GEN D)
    1225             : {
    1226       27677 :   GEN v = qfbsolve(Q, D, 1), w;
    1227       27684 :   long i, c, n = lg(v) - 1;
    1228             : 
    1229       27684 :   w = cgetg(2 * n + 1, t_VEC);
    1230       82423 :   for (i = c = 1; i <= n; i++)
    1231             :   {
    1232       54753 :     GEN BC = gel(v, i), B = gel(BC,1), C = gel(BC,2);
    1233       54753 :     gel(w, c++) = absi_shallow(B);
    1234       54765 :     if (!absequalii(B, C)) gel(w, c++) = absi_shallow(C);
    1235             :   }
    1236       27670 :   setlg(w, c); return gtoset_shallow(w);
    1237             : }
    1238             : 
    1239             : /* D squarefree in [D,factor(D)] form, D = B^2 + C^2,
    1240             :  * A*(odd part of D) = n2 = prod_{odd p | n} p, v2 = v2(n) */
    1241             : static GEN
    1242       27674 : polsubC4_D(GEN Q, GEN A, GEN Dfa, GEN n2, long v2, long s, long fli)
    1243             : {
    1244       27674 :   GEN v, S, mS, AD, A2D, D = gel(Dfa,1), vB = C4qfbsolve(Q, Dfa);
    1245       27665 :   long i, c, l = lg(vB), A4 = Mod4(A); /* 1 or 3 */
    1246             : 
    1247       27665 :   AD = mpodd(D)? n2: shifti(n2, 1);
    1248       27670 :   A2D = mulii(A, AD);
    1249       27625 :   S = mulsi(-2, AD); mS = negi(S);
    1250       27668 :   v = cgetg(2 * l - 1, t_VEC);
    1251       82433 :   for (i = c = 1; i < l; i++)
    1252             :   {
    1253       54763 :     GEN B = gel(vB, i), T;
    1254       54763 :     long B4 = Mod4(B);
    1255       54765 :     int p = (s <= 0), m = !!s;
    1256       54765 :     if (v2 <= 2 && odd(B4)) continue;
    1257       31114 :     if (!v2)
    1258       19176 :     { if (((A4 + B4) & 3) == 1) m = 0; else p = 0; }
    1259       11938 :     else if (fli)
    1260             :     {
    1261       11938 :       if (v2 == 3)
    1262        4543 :       { if (!odd(B4)) continue; }
    1263        7395 :       else if (v2 == 2)
    1264        4473 :       { if (((A4 + B4) & 3) == 1) p = 0; else m = 0; }
    1265             :     }
    1266       28853 :     if (!p && !m) continue;
    1267       21791 :     T = mulii(A2D, subii(D, sqri(B)));
    1268       21736 :     if (p) gel(v, c++) = makepolC4(S, T);
    1269       21749 :     if (m) gel(v, c++) = makepolC4(mS, T);
    1270             :   }
    1271       27670 :   setlg(v, c); return v;
    1272             : }
    1273             : 
    1274             : 
    1275             : /* vector of distinct primes -> squarefree famat */
    1276             : static GEN
    1277        7987 : P2fa(GEN P) { return mkmat2(P, const_col(lg(P)-1, gen_1)); }
    1278             : /* vector of distinct primes -> [factorback, P2fa] */
    1279             : static GEN
    1280         294 : P2Nfa(GEN P) { return mkvec2(ZV_prod(P), P2fa(P)); }
    1281             : /* P = prime divisors of f different from ell; nf = Q or quadratic */
    1282             : static GEN
    1283        7217 : Pell2prfa(GEN nf, GEN P, long ell, GEN f)
    1284             : {
    1285        7217 :   long v = Z_lval(f, ell);
    1286        7217 :   if (v) P = ZV_sort(vec_append(P, utoipos(ell)));
    1287        7217 :   P = nf_pV_to_prV(nf, P); settyp(P, t_COL); P = P2fa(P);
    1288        7217 :   if (v)
    1289             :   { /* add pr^{2e} for all pr | ell */
    1290         196 :     long i, l = lg(gel(P,1));
    1291         420 :     for (i = 1; i < l; i++)
    1292             :     {
    1293         224 :       GEN pr = gcoeff(P,i,1);
    1294         224 :       if (equaliu(pr_get_p(pr), ell)) gcoeff(P,i,2) = utoipos(v * pr_get_e(pr));
    1295             :     }
    1296             :   }
    1297        7217 :   return P;
    1298             : }
    1299             : static int
    1300       45826 : ZV_is_1(GEN x, long i0)
    1301             : {
    1302       45826 :   long i, l = lg(x);
    1303      117662 :   for (i = i0; i < l; i++) if (!equali1(gel(x,i))) return 0;
    1304       35127 :   return 1;
    1305             : }
    1306             : static int
    1307       41461 : zv_is_1(GEN x, long i0)
    1308             : {
    1309       41461 :   long i, l = lg(x);
    1310       51380 :   for (i = i0; i < l; i++) if (x[i] != 1) return 0;
    1311       40467 :   return 1;
    1312             : }
    1313             : 
    1314             : /* n > 0, D sqfree, sum2sq(odd(D)? D: 4*D) is true */
    1315             : static GEN
    1316       60347 : polsubcycloC4_i(GEN n, long s, long fli, GEN D)
    1317             : {
    1318       60347 :   GEN fa = NULL, P, Q, v, n2;
    1319             :   long v2;
    1320             : 
    1321       60347 :   if (typ(n) == t_VEC) { fa = gel(n,2); n = gel(n,1); }
    1322       60347 :   if (s == 1 || equali1(n)) return NULL;
    1323             :   /* s = -1, 0 or 2 */
    1324       60373 :   v2 = vali(n); if (fli && (v2 == 1 || v2 > 4)) return NULL;
    1325       44251 :   if (!fa) fa = Z_factor(n);
    1326       44392 :   P = gel(fa,1);
    1327       44392 :   if (fli && !ZV_is_1(gel(fa,2), v2? 2: 1)) return NULL;
    1328       33733 :   n2 = ZV_prod(v2? vecsplice(P, 1): P); /* odd part of rad(n) */
    1329       33708 :   Q = mkqfb(gen_1, gen_0, gen_1, utoineg(4));
    1330       33709 :   if (D)
    1331             :   {
    1332             :     GEN A, PD, LD;
    1333       33415 :     if (fli && mpodd(D) == (v2 == 4)) return NULL;
    1334       27039 :     if (!(A = divide(n2, mpodd(D) ? D : gmul2n(D, -1)))) return NULL;
    1335       27018 :     (void)Z_smoothen(D, P, &PD, &LD);
    1336       27057 :     D = mkvec2(D, mkmat2(PD, LD));
    1337       27050 :     v = polsubC4_D(Q, A, D, n2, v2, s, fli);
    1338             :   }
    1339             :   else
    1340             :   {
    1341         294 :     long c, i, lv, l = lg(P);
    1342         294 :     GEN M2 = NULL;
    1343         294 :     c = (v2 && v2 < 4)? 2:  1; /* leave 2 in P if 16 | n */
    1344         294 :     if (c == 2) M2 = mkmat2(mkcol(gen_2),mkcol(gen_1));
    1345         672 :     for (i = v2? 2: 1; i < l; i++) /* odd prime divisors of n */
    1346         378 :       if (Mod4(gel(P,i)) == 1) gel(P, c++) = gel(P,i);
    1347         294 :     setlg(P, c);
    1348         294 :     v = divisors_factored(P2Nfa(P)); lv = lg(v);
    1349        1169 :     for (i = c = 1; i < lv; i++)
    1350             :     {
    1351         875 :       GEN A, D = gel(v,i), d = gel(D,1);
    1352         875 :       if (M2) /* replace (odd) D by 2*D */
    1353             :       {
    1354          84 :         gel(D,1) = shifti(d,1);
    1355          84 :         gel(D,2) = famat_mul(M2, gel(D,2));
    1356         791 :       } else if (i == 1) continue; /* ommit D = 1 */
    1357         623 :       A = diviiexact(n2, mpodd(d)? d: shifti(d,-1));
    1358         623 :       gel(v,c++) = polsubC4_D(Q, A, D, n2, v2, s, fli);
    1359             :     }
    1360         294 :     if (c == 1) return NULL;
    1361         245 :     setlg(v, c); v = shallowconcat1(v);
    1362             :   }
    1363       27294 :   return v;
    1364             : }
    1365             : static GEN
    1366          63 : polsubcycloC4(GEN n, long s)
    1367             : {
    1368             :   long i, l, c;
    1369          63 :   GEN D = divisors_factored(n);
    1370          63 :   l = lg(D);
    1371         357 :   for (i = 2, c = 1; i < l; i++)
    1372             :   {
    1373         294 :     GEN v = polsubcycloC4_i(gel(D,i), s, 1, NULL);
    1374         294 :     if (v) gel(D,c++) = v;
    1375             :   }
    1376          63 :   setlg(D, c); return myshallowconcat1(D);
    1377             : }
    1378             : 
    1379             : /* x^2 + a */
    1380             : static GEN
    1381        6299 : X2p(GEN a) { return deg2pol_shallow(gen_1, gen_0, a, 0); }
    1382             : /* x^2 - a */
    1383             : static GEN
    1384        1881 : X2m(GEN a) { return deg2pol_shallow(gen_1, gen_0, negi(a), 0); }
    1385             : /* y^2 - a */
    1386             : static GEN
    1387        4905 : Y2m(GEN a) { return deg2pol_shallow(gen_1, gen_0, negi(a), 1); }
    1388             : 
    1389             : static GEN
    1390         329 : makeC4(GEN N, GEN field, long s)
    1391             : {
    1392             :   GEN D;
    1393             :   long i, c;
    1394             : 
    1395         329 :   if (s == 1) return NULL;
    1396         315 :   if (field)
    1397             :   {
    1398           7 :     GEN d = checkfield(field, 2);
    1399           7 :     if (signe(d) < 0 || !divissquare(N, powiu(d,3))) return NULL;
    1400           7 :     D = mkvec(d);
    1401             :   }
    1402         308 :   else D = divisorsdisc(cored(N, 3), 0);
    1403         511 :   for (i = c = 1; i < lg(D); i++)
    1404             :   {
    1405         196 :     GEN cond, v, d = gel(D, i);
    1406         196 :     if (sum2sq(d) && Z_issquareall(divii(N, powiu(d, 3)), &cond)
    1407          84 :         && (v = polsubcycloC4_i(mulii(d,cond),s,1, mpodd(d)? d: shifti(d,-2))))
    1408          70 :           gel(D, c++) = v;
    1409             :   }
    1410         315 :   if (c == 1) return NULL;
    1411          70 :   setlg(D, c); return sturmseparate(myshallowconcat1(D), s, 4);
    1412             : }
    1413             : 
    1414             : static GEN
    1415         210 : condrel_i(GEN P, GEN pol)
    1416             : {
    1417         210 :   GEN bnf = bnfY(P), T = gcoeff(nffactor(bnf, pol), 1, 1);
    1418         210 :   GEN f = gel(rnfconductor0(bnf, T, 2), 1);
    1419         210 :   GEN id = gel(f, 1), arch = gel(f, 2), co = gcoeff(id, 1, 1);
    1420         210 :   if (ZM_isscalar(id, co)) id = co;
    1421         210 :   return mkvec2(P, gequal0(arch) ? id : mkvec2(id, arch));
    1422             : }
    1423             : static GEN
    1424         196 : condrel(GEN P, GEN pol, long flag)
    1425         196 : { return odd(flag)? condrel_i(P, pol): P; }
    1426             : static GEN
    1427          21 : condrel_dummy(GEN P, long flag)
    1428          21 : { return odd(flag)? mkvec2(P, gen_1): P; }
    1429             : static GEN
    1430         112 : condrelresolvent(GEN pol, long d, long flag)
    1431         112 : { return condrel(mynfsubfield(pol, d), pol, flag); }
    1432             : 
    1433             : 
    1434             : static GEN
    1435          14 : makeC4resolvent(GEN pol, long flag)
    1436             : {
    1437          14 :   GEN d; (void)nfcoredisc(pol, &d);
    1438          14 :   return condrel(quadpoly_i(d), pol, flag);
    1439             : }
    1440             : 
    1441             : static GEN
    1442        2254 : C4vec(GEN X, GEN Xinf, GEN m, long s)
    1443             : {
    1444        2254 :   GEN v, M, inf, m3 = powiu(m, 3), limf = gfloorsqrtdiv(X, m3);
    1445             :   long l, n, c;
    1446             :   pari_sp av;
    1447        2250 :   inf = cmpiu(Xinf, 500) >= 0? gceilsqrtdiv(Xinf, m3): gen_1;
    1448        2251 :   l = itos(subii(limf, inf)) + 2;
    1449        2251 :   M = mpodd(m)? m: shifti(m, -2); av = avma;
    1450             : 
    1451        2253 :   v = const_vec(l-1, cgetg(1,t_VEC));
    1452       62342 :   for (n = c = 1; n < l; n++)
    1453             :   {
    1454       60090 :     GEN w, cond = addui(n-1, inf);
    1455       59963 :     if ((w = polsubcycloC4_i(mulii(m, cond), s, 1, M))) gel(v, c++) = w;
    1456       60089 :     if ((n & 0xfff) == 0 && gc_needed(av, 3))
    1457             :     { /* let parisizemax handle some of it */
    1458           0 :       if (DEBUGMEM>1) pari_warn(warnmem,"C4vec, n = %ld/%ld", n, l-1);
    1459           0 :       v = gerepilecopy(av, v);
    1460             :     }
    1461             :   }
    1462        2252 :   setlg(v, c); return myshallowconcat1(v);
    1463             : }
    1464             : 
    1465             : GEN
    1466        2247 : nflist_C4vec_worker(GEN m, GEN X, GEN Xinf, GEN gs)
    1467             : {
    1468        2247 :   pari_sp av = avma;
    1469        2247 :   return gerepilecopy(av, C4vec(X, Xinf, m, itos(gs)));
    1470             : }
    1471             : 
    1472             : static GEN
    1473         133 : makeC4vec_i(GEN X, GEN Xinf, GEN field, long s)
    1474             : {
    1475             :   GEN v;
    1476         133 :   long limD = floorsqrtn(X,3), m, c, snew = s == -2 ? -1 : s;
    1477         133 :   if (s == 1) return NULL;
    1478         119 :   if (field)
    1479             :   {
    1480           7 :     GEN gm = checkfield(field, 2);
    1481           7 :     return sum2sq(gm)? C4vec(X, Xinf, gm, snew): NULL;
    1482             :   }
    1483         112 :   v = cgetg(limD >> 1, t_VEC);
    1484        7658 :   for (m = 5, c = 1; m <= limD; m += odd(m) ? 3 : 1)
    1485        7546 :     if (usum2sq(m)) gel(v, c++) = utoipos(m);
    1486         112 :   setlg(v, c);
    1487         112 :   v = gen_parapply(closure("_nflist_C4vec_worker", mkvec3(X, Xinf, stoi(snew))), v);
    1488         112 :   return myshallowconcat1(v);
    1489             : }
    1490             : static GEN
    1491         133 : makeC4vec(GEN X, GEN Xinf, GEN field, long s)
    1492             : {
    1493         133 :   GEN v = makeC4vec_i(X, Xinf, field, s);
    1494         133 :   return v? sturmseparate(v, s, 4): NULL;
    1495             : }
    1496             : 
    1497             : /**********************************************************************/
    1498             : /*                                 V4                                 */
    1499             : /**********************************************************************/
    1500             : 
    1501             : static GEN
    1502          49 : makeV4(GEN N, GEN field, long s)
    1503             : {
    1504             :   GEN V, R;
    1505          49 :   long lV, i1, i2, c = 1;
    1506          49 :   if (s == 1) return NULL;
    1507          42 :   if (field)
    1508             :   {
    1509           7 :     GEN D = checkfield(field, 2);
    1510           7 :     if (signe(D) < 0) pari_err_TYPE("makeV4 [real quadratic subfield]", field);
    1511           7 :     V = mkvec(D);
    1512             :   }
    1513          35 :   else V = divisorsdisc(N, -1);
    1514          42 :   lV = lg(V); R = cgetg((lV - 1) * (lV - 2) >> 1, t_VEC);
    1515          98 :   for (i1 = 1; i1 < lV; i1++)
    1516             :   {
    1517          56 :     GEN V2, D1 = gel(V, i1);
    1518          56 :     if (s == 0 && signe(D1) < 0) continue;
    1519          56 :     if (cmpii(sqri(D1), N) > 0) continue;
    1520          56 :     V2 = divisorsdisc(diviiexact(N, absi_shallow(D1)), -1);
    1521         448 :     for (i2 = 1; i2 < lg(V2); i2++)
    1522             :     {
    1523         392 :       GEN D2 = gel(V2, i2), D3, D12;
    1524         392 :       if (s == 0 && signe(D2) < 0) continue;
    1525         392 :       if (s > 0 && signe(D1) > 0 && signe(D2) > 0) continue;
    1526         392 :       if ((!field && cmpii(D1, D2) >= 0) || equalii(D1, D2)) continue;
    1527         189 :       D12 = mulii(D1, D2); D3 = coredisc(D12);
    1528         189 :       if (cmpii(D2, D3) < 0 && !equalii(D1, D3)
    1529          70 :           && absequalii(mulii(D12, D3), N))
    1530          21 :         gel(R, c++) = mkpoln(5, gen_1, gen_0, mulsi(-2, addii(D1, D2)),
    1531             :                               gen_0, sqri(subii(D1, D2)));
    1532             :     }
    1533             :   }
    1534          42 :   if (c == 1) return NULL;
    1535          14 :   setlg(R, c); return sturmseparate(R, s, 4);
    1536             : }
    1537             : 
    1538             : static GEN
    1539          21 : makeV4resolvent(GEN pol, long flag)
    1540             : {
    1541          21 :   GEN P, V = mynfsubfields(pol, 2);
    1542             :   long i;
    1543          21 :   if (lg(V) != 4) pari_err_BUG("makeV4resolvent");
    1544          21 :   if (flag >= 2)
    1545             :   {
    1546          14 :     if (flag == 2) return V;
    1547           7 :     return mkvec3(condrel_i(gel(V, 1), pol),
    1548           7 :                   condrel_i(gel(V, 2), pol),
    1549           7 :                   condrel_i(gel(V, 3), pol));
    1550             :   }
    1551           7 :   for (i = 1; i <= 3; i++) { P = gel(V, i); if (signe(ZX_disc(P)) > 0) break; }
    1552           7 :   return condrel(P, pol, flag);
    1553             : }
    1554             : 
    1555             : static GEN
    1556      225499 : polV4(long d1, long d2)
    1557      225499 : { return mkpoln(5, gen_1, gen_0, mulss(-2, d1+d2), gen_0, sqrs(d1-d2)); }
    1558             : 
    1559             : GEN
    1560        5025 : nflist_V4_worker(GEN D1, GEN X, GEN Xinf, GEN gs)
    1561             : {
    1562        5025 :   pari_sp av = avma, av2;
    1563             :   GEN V, W;
    1564        5025 :   long d2a, e1 = signe(D1), d1 = itos(D1), d1a = labs(d1);
    1565        5023 :   long limg, limg2, s2 = -1, s = itos(gs);
    1566        5023 :   long limD2 = itos(sqrti(divis(X, d1a)));
    1567        5021 :   long limQ = floorsqrtdiv(X, sqru(d1a));
    1568             : 
    1569        5016 :   limg2 = limg = usqrt(d1a);
    1570        5016 :   if (!odd(d1a))
    1571             :   { /* limg2 = sqrt(d1a * 4), to be used when d2 is also even */
    1572        1728 :     long r = d1a - limg*limg;
    1573        1728 :     limg2 *= 2; if (r >= limg) limg2++;
    1574             :   }
    1575             : 
    1576        5014 :   if (s == 2 && e1 > 0) s2 = 1; /* forbid d2 > 0 */
    1577        4028 :   else if (!s) s2 = 0; /* forbid d2 < 0 */
    1578        5014 :   W = vectrunc_init(2 * limD2);
    1579        5012 :   V = e1 < 0? W: vectrunc_init(2 * limD2); av2 = avma;
    1580     2889135 :   for (d2a = d1a; d2a <= limD2; d2a++, set_avma(av2))
    1581             :   {
    1582             :     long g, d2ag, LIMg;
    1583             :     GEN D3, d1d2a, d3;
    1584             :     int p, m;
    1585     2864502 :     if (odd(d2a)) LIMg = limg;
    1586             :     else
    1587             :     {
    1588     3206995 :       if ((d2a & 3) == 2 || !(d2a & 15)) continue; /* v2(d2) = 1 or >= 4 */
    1589      560095 :       LIMg = limg2;
    1590             :     }
    1591     2004763 :     g = ugcd(d2a, d1a); if (g > LIMg) continue;
    1592     1844578 :     d2ag = d2a / g; if (d2ag > limQ) continue;
    1593      322260 :     uis_fundamental_pm(d2a, s2, &p, &m);
    1594      362200 :     if (!p && !m) continue;
    1595      243396 :     d3 = muluu(d1a / g, d2ag); d1d2a = muluu(d1a, d2a);
    1596      241694 :     if (p)
    1597             :     { /* D2 = d2a is fundamental */
    1598      136195 :       setsigne(d3, e1);
    1599      136195 :       D3 = Mod4(d3) > 1? shifti(d3, 2): d3; /* now D3 = coredisc(D1*D2) */
    1600      137586 :       if (abscmpiu(D3, d2a) > 0 && ok_int(mulii(d1d2a, D3), X, Xinf))
    1601      113293 :       { vectrunc_append(V,  polV4(d1, d2a)); av2 = avma; }
    1602             :     }
    1603      243350 :     if (m)
    1604             :     { /* D2 = - d2a is fundamental */
    1605             :       int fl;
    1606      134220 :       setsigne(d3, -e1);
    1607      134220 :       D3 = Mod4(d3) > 1? shifti(d3, 2): d3; /* now D3 = coredisc(D1*D2) */
    1608      135563 :       fl = abscmpiu(D3, d2a);
    1609      135566 :       if (fl < 0 || (!fl && e1 > 0)) continue;
    1610      126571 :       if (ok_int(mulii(d1d2a, D3), X, Xinf))
    1611      115255 :       { set_avma(av2); vectrunc_append(W, polV4(d1, -d2a)); av2 = avma; }
    1612             :     }
    1613             :   }
    1614        4974 :   return gerepilecopy(av, mkvec2(e1 < 0? cgetg(1, t_VEC): V, W));
    1615             : }
    1616             : 
    1617             : static GEN
    1618         280 : Sextract(GEN v, long ind)
    1619             : {
    1620             :   long j, l;
    1621         280 :   GEN w = cgetg_copy(v, &l);
    1622       14525 :   for (j = 1; j < l; j++) gel(w, j) = gmael(v, j, ind);
    1623         280 :   return myshallowconcat1(w);
    1624             : }
    1625             : static GEN
    1626          42 : makeV4vec(GEN X, GEN Xinf, GEN field, long s)
    1627             : {
    1628             :   long s2, d, dinf, dsup, l, c;
    1629             :   GEN v;
    1630             : 
    1631          42 :   if (s == 1) return NULL;
    1632          35 :   if (field)
    1633             :   {
    1634           7 :     GEN D = checkfield(field, 2), DSQ = sqri(D);
    1635           7 :     if (signe(D) < 0) pari_err_TYPE("makeV4 [real quadratic subfield]", field);
    1636           7 :     if (cmpii(DSQ, X) > 0) return NULL;
    1637           7 :     dinf = itos(D); dsup = dinf; l = 2; s2 = 0;
    1638             :   }
    1639             :   else
    1640          28 :   { dinf = 3; dsup = floorsqrtn(X,3); l = dsup << 1; s2 = s? -1: 0; }
    1641          35 :   v = cgetg(l, t_VEC); c = 1;
    1642        9800 :   for (d = dinf; d <= dsup; d++)
    1643             :   {
    1644             :     int p, m;
    1645        9765 :     uis_fundamental_pm(d, s2, &p, &m);
    1646        9765 :     if (m) gel(v, c++) = utoineg(d);
    1647        9765 :     if (p) gel(v, c++) = utoipos(d);
    1648             :   }
    1649          35 :   setlg(v, c);
    1650          35 :   v = gen_parapply(closure("_nflist_V4_worker", mkvec3(X, Xinf, stoi(s))), v);
    1651          35 :   switch (s)
    1652             :   {
    1653           7 :     case 0: return Sextract(v,1);
    1654           7 :     case 2: return Sextract(v,2);
    1655          14 :     case -1: return shallowconcat(Sextract(v,1), Sextract(v,2));
    1656           7 :     default: return mkvec3(Sextract(v,1), cgetg(1, t_VEC), Sextract(v,2));
    1657             :   }
    1658             : }
    1659             : 
    1660             : /**********************************************************************/
    1661             : /*                                 D4                                 */
    1662             : /**********************************************************************/
    1663             : static GEN
    1664         175 : archD40() { return mkvec(cgetg(1, t_VECSMALL)); }
    1665             : 
    1666             : static GEN
    1667         175 : archD41() { return mkvec2(mkvecsmall(2), mkvecsmall(1)); }
    1668             : 
    1669             : static GEN
    1670         182 : archD42() { return mkvec(mkvecsmall2(1, 2)); }
    1671             : 
    1672             : static GEN
    1673         238 : getarchD4(long s)
    1674             : {
    1675         238 :   switch (s)
    1676             :   {
    1677          28 :     case 0: return archD40();
    1678          28 :     case 1: return archD41();
    1679          35 :     case 2: return archD42();
    1680         147 :     default: return shallowconcat1(mkvec3(archD40(), archD41(), archD42()));
    1681             :   }
    1682             :   return gen_0;
    1683             : }
    1684             : 
    1685             : /* x = [N, a;0, m] quadratic ideal in HNF, apply quadratic automorphism */
    1686             : static GEN
    1687       42236 : aut2(GEN x, long oddD)
    1688             : {
    1689       42236 :   GEN N = gcoeff(x,1,1), t = subii(N, gcoeff(x,1,2)), m = gcoeff(x,2,2);
    1690       42236 :   if (oddD) t = addii(t, m);
    1691       42235 :   return mkmat2(gel(x,1), mkcol2(modii(t, N), m));
    1692             : }
    1693             : /* I a vector of quadratic ideals of same norm */
    1694             : static GEN
    1695      177333 : authI(GEN nf, GEN I, GEN *pstable, GEN D)
    1696             : {
    1697      177333 :   long l = lg(I), i, oddD;
    1698             :   GEN v, w;
    1699             : 
    1700      177333 :   if (l == 1) { *pstable = NULL; return I; }
    1701       84780 :   if (l == 2) { *pstable = mkvecsmall(1); return I; }
    1702       66714 :   if (l == 3) { *pstable = mkvecsmall2(0,0); gel(I,2) = NULL; return I; }
    1703       18828 :   v = w = shallowcopy(I); *pstable = zero_zv(l-1); oddD = mpodd(D);
    1704       18830 :   if (typ(gcoeff(gel(I,1), 1, 1)) != t_INT) /* vector of factorizations */
    1705             :   {
    1706           7 :     w = cgetg(l, t_VEC);
    1707          28 :     for (i = 1; i < l; i++) gel(w,i) = idealfactorback(nf,gel(v,i),NULL,0);
    1708             :   }
    1709             : 
    1710       98741 :   for (i = 1; i < l; i++)
    1711             :   {
    1712       79911 :     GEN a = gel(w, i), b;
    1713             :     long j;
    1714       79911 :     if (!a) continue;
    1715       42237 :     b = aut2(a, oddD);
    1716       42237 :     if (ZM_equal(b, a)) { (*pstable)[i] = 1; continue; }
    1717       90983 :     for (j = i + 1; j < l; j++)
    1718       90983 :       if (ZM_equal(b, gel(w,j))) { gel(v,j) = gel(w,j) = NULL; break;}
    1719       37673 :     if (j == l) pari_err_BUG("makeD4 [conjugate not found]");
    1720             :   }
    1721       18830 :   return v;
    1722             : }
    1723             : 
    1724             : /* kronecker(D, cond) != -1, Arch a vector of arch in t_VECSMALL form */
    1725             : static GEN
    1726      177332 : polD4onecond(GEN bnf, GEN G, GEN D, GEN I, GEN Arch)
    1727             : {
    1728             :   GEN stable, v0, v1, v2;
    1729      177332 :   long j, k, m, l, lA, ok = 0, r1 = signe(D) > 0? 2: 0;
    1730             : 
    1731      177332 :   v0 = v1 = v2 = cgetg(1,t_VEC);
    1732      177333 :   I = authI(bnf, I, &stable, D); l = lg(I); lA = lg(Arch);
    1733      371082 :   for (j = 1; j < l; j++)
    1734             :   {
    1735      193749 :     GEN id = gel(I, j);
    1736      193749 :     if (!id) continue;
    1737      246477 :     for (k = 1; k < lA; k++)
    1738             :     {
    1739      138283 :       GEN arch = gel(Arch, k), R = NULL;
    1740      138283 :       long st = lg(arch)-1, lR;
    1741      138283 :       if (stable[j])
    1742             :       {
    1743       33046 :         if (st == 1 && arch[1] == 1) continue;
    1744       27992 :         if (st != 1) R = mybnrclassfield_X(bnf, mkvec2(id,arch), 2,NULL,NULL,G);
    1745             :       }
    1746      133234 :       if (!R) R = mybnrclassfield(bnf, mkvec2(id, arch), 2);
    1747      133233 :       lR = lg(R); if (lR == 1) continue;
    1748       26495 :       ok = 1;
    1749       54404 :       for (m = 1; m < lR; m++)
    1750             :       {
    1751       27909 :         GEN P = rnfequation(bnf, gel(R, m));
    1752       27909 :         if (st == 0 && r1) v0 = vec_append(v0, P);
    1753       26460 :         else if (st == 1) v1 = vec_append(v1, P);
    1754       21987 :         else v2 = vec_append(v2, P);
    1755             :       }
    1756             :     }
    1757             :   }
    1758      177333 :   return ok? mkvec3(v0, v1, v2): NULL;
    1759             : }
    1760             : 
    1761             : static GEN
    1762         154 : makeD4(GEN N, GEN field, long s)
    1763             : {
    1764             :   pari_sp av2;
    1765         154 :   GEN vD, v, v0, v1, v2, archempty, listarch = getarchD4(s);
    1766             :   long l, i;
    1767             : 
    1768         154 :   if (field)
    1769             :   {
    1770          21 :     GEN D = checkfield(field, 2);
    1771          21 :     if ((signe(D) < 0 && (s == 0 || s == 1)) || !dvdii(N, sqri(D)))
    1772           7 :       return NULL;
    1773          14 :     vD = mkvec(D);
    1774             :   }
    1775             :   else
    1776         133 :     vD = divisorsdisc(cored(N,2), (s == 0 || s == 1)? 0 : -1);
    1777         147 :   archempty = mkvec(cgetg(1, t_VECSMALL));
    1778         147 :   l = lg(vD); av2 = avma;
    1779         147 :   v0 = const_vec(l-1, cgetg(1,t_VEC));
    1780         147 :   v1 = const_vec(l-1, cgetg(1,t_VEC));
    1781         147 :   v2 = const_vec(l-1, cgetg(1,t_VEC));
    1782         196 :   for (i = 1; i < l; i++)
    1783             :   {
    1784          49 :     GEN bnf, G, I, Arch, RET, D = gel(vD, i);
    1785          49 :     pari_sp av3 = avma;
    1786          49 :     long cond = itou(divii(N, sqri(D)));
    1787             : 
    1788          49 :     set_avma(av3);
    1789          49 :     if (kroiu(D, cond) == -1) continue;
    1790          49 :     bnf = Buchall(Y2m(D), nf_FORCE, DEFAULTPREC);
    1791          49 :     I = ideals_by_norm(bnf_get_nf(bnf), utoipos(cond));
    1792          49 :     Arch = signe(D) > 0 ? listarch : archempty;
    1793             :     /* restrict to fields which are not Galois over Q [eliminate V4/C4] */
    1794          49 :     G = s != 1? mkvec2(galoisinit(bnf, NULL), gen_0): NULL;
    1795          49 :     if (!(RET = polD4onecond(bnf, G, D, I, Arch)))
    1796          21 :     { set_avma(av3); continue; }
    1797          28 :     gel(v0,i) = gel(RET,1);
    1798          28 :     gel(v1,i) = gel(RET,2);
    1799          28 :     gel(v2,i) = gel(RET,3);
    1800          28 :     if (gc_needed(av2, 2))
    1801             :     {
    1802           0 :       if (DEBUGMEM>1) pari_warn(warnmem,"makeD4");
    1803           0 :       gerepileall(av2, 3, &v0,&v1,&v2);
    1804             :     }
    1805             :   }
    1806         147 :   if      (s == 0) v = myshallowconcat1(v0);
    1807         133 :   else if (s == 1) v = myshallowconcat1(v1);
    1808         119 :   else if (s == 2) v = myshallowconcat1(v2);
    1809             :   else
    1810             :   {
    1811         105 :     v0 = myshallowconcat1(v0);
    1812         105 :     v1 = myshallowconcat1(v1);
    1813         105 :     v2 = myshallowconcat1(v2); v = mkvec3(v0, v1, v2);
    1814         105 :     if (s == -1) v = myshallowconcat1(v);
    1815             :   }
    1816         147 :   return v;
    1817             : }
    1818             : 
    1819             : GEN
    1820        3701 : nflist_D4_worker(GEN D, GEN X, GEN Xinf, GEN listarch)
    1821             : {
    1822        3701 :   pari_sp av = avma, av2;
    1823        3701 :   GEN bnf, G, vI, v0, v1, v2, Arch, D2 = sqri(D);
    1824        3695 :   long c0, c1, c2, cond, l = itos(divii(X, D2)) + 1;
    1825        3701 :   long lmin = itos(ceildiv(Xinf, D2));
    1826             : 
    1827        3699 :   bnf = Buchall(Y2m(D), nf_FORCE, DEFAULTPREC);
    1828        3703 :   vI = ideallist(bnf, l-1);
    1829        3703 :   Arch = signe(D) > 0 ? listarch : mkvec(cgetg(1,t_VECSMALL));
    1830        3703 :   G = lg(Arch) != 3? mkvec2(galoisinit(bnf, NULL), gen_0): NULL;
    1831        3703 :   av2 = avma;
    1832        3703 :   v0 = const_vec(l-1, cgetg(1,t_VEC));
    1833        3703 :   v1 = const_vec(l-1, cgetg(1,t_VEC));
    1834        3703 :   v2 = const_vec(l-1, cgetg(1,t_VEC)); c0 = c1 = c2 = 1;
    1835      265664 :   for (cond = lmin; cond < l; cond++)
    1836             :   {
    1837      261961 :     pari_sp av3 = avma;
    1838             :     GEN R, R1, R2, R3;
    1839      261961 :     if (kroiu(D, cond) == -1) continue;
    1840      177279 :     if (!(R = polD4onecond(bnf, G, D, gel(vI, cond), Arch)))
    1841      155819 :     { set_avma(av3); continue; }
    1842       21467 :     R1 = gel(R,1); if (lg(R1) > 1) gel(v0, c0++) = R1;
    1843       21467 :     R2 = gel(R,2); if (lg(R2) > 1) gel(v1, c1++) = R2;
    1844       21467 :     R3 = gel(R,3); if (lg(R3) > 1) gel(v2, c2++) = R3;
    1845       21467 :     if (gc_needed(av,1))
    1846             :     {
    1847           0 :       if (DEBUGMEM>1) pari_warn(warnmem,"makeD4vec, cond = %ld/%ld",cond,l-1);
    1848           0 :       gerepileall(av2, 3, &v0,&v1,&v2);
    1849             :     }
    1850             :   }
    1851        3703 :   setlg(v0,c0); v0 = myshallowconcat1(v0);
    1852        3703 :   setlg(v1,c1); v1 = myshallowconcat1(v1);
    1853        3703 :   setlg(v2,c2); v2 = myshallowconcat1(v2);
    1854        3703 :   return gerepilecopy(av, mkvec3(v0, v1, v2));
    1855             : }
    1856             : 
    1857             : static GEN
    1858          84 : makeD4vec(GEN X, GEN Xinf, GEN field, long s)
    1859             : {
    1860             :   long s2, limdinf, limdsup, c, da;
    1861             :   GEN v, D;
    1862             : 
    1863          84 :   if (field)
    1864             :   {
    1865           7 :     GEN D = checkfield(field, 2);
    1866           7 :     if (cmpii(sqri(D), X) > 0) return NULL;
    1867           7 :     limdsup = limdinf = labs(itos(D));
    1868           7 :     s2 = signe(D) < 0? 1: 0;
    1869             :   }
    1870             :   else
    1871             :   {
    1872          77 :     limdinf = 3; limdsup = itou(sqrti(X));
    1873          77 :     s2 = (s == 0 || s == 1) ? 0 : -1;
    1874             :   }
    1875          84 :   D = cgetg(2 * limdsup + 1, t_VEC); c = 1;
    1876        7378 :   for (da = limdinf; da <= limdsup; da++)
    1877             :   {
    1878             :     int p, m;
    1879        7294 :     uis_fundamental_pm(da, s2, &p, &m);
    1880        7294 :     if (p) gel(D, c++) = utoipos(da);
    1881        7294 :     if (m) gel(D, c++) = utoineg(da);
    1882             :   }
    1883          84 :   setlg(D, c);
    1884          84 :   v = gen_parapply(closure("_nflist_D4_worker", mkvec3(X, Xinf, getarchD4(s))), D);
    1885          84 :   if (s >= 0) v = Sextract(v,s+1);
    1886             :   else
    1887             :   {
    1888          35 :     v = mkvec3(Sextract(v,1), Sextract(v,2), Sextract(v,3));
    1889          35 :     if (s == -1) v = shallowconcat1(v);
    1890             :   }
    1891          84 :   return v;
    1892             : }
    1893             : 
    1894             : /**********************************************************************/
    1895             : /*                              A4 and S4                             */
    1896             : /**********************************************************************/
    1897             : /* FIXME: export */
    1898             : static GEN
    1899      110112 : to_principal_unit(GEN nf, GEN x, GEN pr, GEN sprk)
    1900             : {
    1901      110112 :   if (pr_get_f(pr) != 1)
    1902             :   {
    1903       33235 :     GEN prk = gel(sprk,3);
    1904       33235 :     x = nfpowmodideal(nf, x, gmael(sprk,5,1), prk);
    1905             :   }
    1906      110115 :   return x;
    1907             : }
    1908             : static long
    1909      110097 : ZV_iseven(GEN zlog)
    1910             : {
    1911      110097 :   long i, l = lg(zlog);
    1912      166763 :   for (i = 1; i < l; i++)
    1913      140303 :     if (mpodd(gel(zlog,i))) return 0;
    1914       26460 :   return 1;
    1915             : }
    1916             : 
    1917             : /* x^2 = t (mod bid) solvable ? */
    1918             : static int
    1919      110113 : issolvable(GEN nf, GEN t, GEN sprk)
    1920             : {
    1921      110113 :   GEN pr = sprk_get_pr(sprk);
    1922      110113 :   (void)nfvalrem(nf, t, pr, &t);
    1923      110112 :   t = to_principal_unit(nf, t, pr, sprk);
    1924      110115 :   return ZV_iseven(sprk_log_prk1(nf, t, sprk));
    1925             : }
    1926             : 
    1927             : /* true nf, cubic field */
    1928             : static GEN
    1929       23954 : makeGid(GEN nf)
    1930             : {
    1931       23954 :   GEN P = idealprimedec(nf, gen_2), Sprk;
    1932       23954 :   GEN bid4 = cgetg(1, t_VEC), bid6 = cgetg(1, t_VEC);
    1933       23954 :   long l = lg(P), i, parity = mpodd(nf_get_disc(nf));
    1934       23954 :   if (l == 3)
    1935             :   {
    1936       11991 :     if (parity) /* ensure f(P[1]/2) = 2 */
    1937        6293 :     { swap(gel(P,1), gel(P,2)); }
    1938             :     else /* make sure e(P[1]/2) = 2 */
    1939        5698 :     { if (pr_get_e(gel(P,1)) == 1) swap(gel(P,1), gel(P,2)); }
    1940             :   }
    1941       23954 :   Sprk = cgetg(l, t_VEC);
    1942       62921 :   for (i = 1; i < l; i++) gel(Sprk, i) = log_prk_init(nf, gel(P,i), 2, gen_2);
    1943       23952 :   if (!parity)
    1944             :   {
    1945        9604 :     bid4 = log_prk_init(nf, gel(P,1), 4, gen_2);
    1946        9604 :     if (l == 2) bid6 = log_prk_init(nf, gel(P,1), 6, gen_2);
    1947             :   }
    1948       23952 :   return mkvecn(3, Sprk, bid4, bid6);
    1949             : }
    1950             : 
    1951             : static long
    1952       58303 : r2(GEN v)
    1953             : {
    1954       58303 :   long i, l = lg(v);
    1955       63553 :   for (i = 1; i < l; i++) if (mpodd(gel(v,i))) break;
    1956       58303 :   return i - 1;
    1957             : }
    1958             : 
    1959             : /* list of virtual units whose norm is a square */
    1960             : static GEN
    1961       23953 : makevunits(GEN bnf)
    1962             : {
    1963       23953 :   GEN cyc = bnf_get_cyc(bnf), G = bnf_get_gen(bnf), nf = bnf_get_nf(bnf), v;
    1964       23954 :   long rc = r2(cyc), l, i;
    1965             : 
    1966       23954 :   v = cgetg(rc + 1, t_VEC);
    1967       26432 :   for (i = 1; i <= rc; i++)
    1968             :   {
    1969        2478 :     GEN g = idealpows(nf, gel(G, i), itos(gel(cyc, i)) >> 1);
    1970        2478 :     g = idealsqr(nf, idealred(nf, g));
    1971        2478 :     g = bnfisprincipal0(bnf, g, nf_GEN | nf_FORCE);
    1972        2478 :     gel(v, i) = gel(g, 2);
    1973             :   }
    1974       23954 :   v = shallowconcat(v, bnf_get_fu(bnf)); l = lg(v);
    1975       57686 :   for (i = 1; i < l; i++)
    1976             :   {
    1977       33732 :     GEN u = gel(v,i);
    1978       33732 :     if (signe(nfnorm(nf, u)) < 0) gel(v,i) = gneg(u); /*norm is a square now*/
    1979             :   }
    1980       23954 :   return eltlist2(nf, v);
    1981             : }
    1982             : 
    1983             : static GEN
    1984         707 : A4clean3(GEN v, long c)
    1985             : {
    1986         707 :   if (c)
    1987             :   {
    1988         266 :     GEN w = gtoset_shallow(vecslice(v, 1, c)); /* #w /= 3 */
    1989         266 :     if (c != lg(v)-1) w = shallowconcat(w, vecslice(v, c+1, lg(v)-1));
    1990         266 :     v = w;
    1991             :   }
    1992         707 :   return v;
    1993             : }
    1994             : 
    1995             : /* nf cubic field, possible local factors for ideals of square norm p^2 */
    1996             : static GEN
    1997       11389 : cubictypedec(GEN nf, GEN p)
    1998             : {
    1999       11389 :   GEN P = idealprimedec(nf, p);
    2000       11389 :   switch (lg(P))
    2001             :   {
    2002        7616 :     case 2: return NULL;
    2003        2716 :     case 3: if (pr_get_f(gel(P,2)) == 2)
    2004        1568 :               return mkvec(idealhnf_shallow(nf, gel(P,2)));
    2005        1148 :             return mkvec(idealmul(nf, gel(P, 1), gel(P, 2)));
    2006        1057 :     default: return mkvec3(idealmul(nf, gel(P, 1), gel(P, 2)),
    2007        1057 :                            idealmul(nf, gel(P, 2), gel(P, 3)),
    2008        1057 :                            idealmul(nf, gel(P, 3), gel(P, 1)));
    2009             :   }
    2010             : }
    2011             : 
    2012             : /* x = gen_1 or in HNF */
    2013             : static int
    2014       27418 : oddnorm(GEN x) { return typ(x) == t_INT || mpodd(gcoeff(x,1,1)); }
    2015             : 
    2016             : /* return k < 4, s.t 2^(2k) = discriminant of quadratic extension over cubic */
    2017             : static long
    2018       57608 : quadcubpow(GEN bnf, GEN Gid, GEN ideal, GEN a)
    2019             : {
    2020       57608 :   GEN nf = bnf_get_nf(bnf), Sprk = gel(Gid,1);
    2021             :   long t;
    2022       57608 :   if (mpodd(nf_get_disc(nf)))
    2023       37547 :     switch (lg(Sprk))
    2024             :     { /* 2 = P3, P2*P1, P1*P1*P1 */
    2025       20587 :       case 2: return issolvable(nf, a, gel(Sprk,1))? 0: 3; /* ideal is odd */
    2026       13138 :       case 3:
    2027       13138 :         t = issolvable(nf, a, gel(Sprk,2))? 2: 3;
    2028       13138 :         if (oddnorm(ideal) && issolvable(nf, a, gel(Sprk,1))) t -= 2;
    2029       13139 :         return t;
    2030        3822 :       default:
    2031        3822 :         t = 3;
    2032        3822 :         if (oddnorm(ideal))
    2033             :         {
    2034        3374 :           if (issolvable(nf,a,gel(Sprk,1))) t--;
    2035        3374 :           if (issolvable(nf,a,gel(Sprk,2))) t--;
    2036        3374 :           if (issolvable(nf,a,gel(Sprk,3))) t--;
    2037             :         }
    2038             :         else
    2039             :         { /* exactly 2 of the 3 primes divide ideal, test solvability by 3rd */
    2040         448 :           if (!idealval(nf,ideal,sprk_get_pr(gel(Sprk,1))))
    2041          28 :           { if (issolvable(nf,a,gel(Sprk,1))) t--; }
    2042         420 :           else if (!idealval(nf,ideal,sprk_get_pr(gel(Sprk,2))))
    2043          28 :           { if (issolvable(nf,a,gel(Sprk,2))) t--; }
    2044             :           else
    2045         392 :           { if (issolvable(nf,a,gel(Sprk,3))) t--; }
    2046             :         }
    2047        3822 :         return t;
    2048             :     }
    2049       20062 :   if (lg(Sprk) == 3)
    2050             :   { /* 2 = P1^2 P2 */
    2051       10458 :     if (!oddnorm(ideal)) return 3;
    2052        9926 :     t = issolvable(nf, a, gel(Sprk,2))? 2: 3;
    2053        9926 :     if (issolvable(nf, a, gel(Gid,2))) t -= 2; /* solvable mod P1^4 */
    2054        9106 :     else if (issolvable(nf, a, gel(Sprk,1))) t--; /* solvable mod P1^2 */
    2055        9926 :     return t;
    2056             :   }
    2057             :   else
    2058             :   { /* 2 = P1^3, ideal must be odd */
    2059        9604 :     if (issolvable(nf, a, gel(Gid,3)))  return 0; /* solvable mod pr^6 */
    2060        8568 :     if (issolvable(nf, a, gel(Gid,2)))  return 1; /* solvable mod pr^4 */
    2061        6041 :     if (issolvable(nf, a, gel(Sprk,1))) return 2; /* solvable mod pr^2 */
    2062        6041 :     return 3;
    2063             :   }
    2064             : }
    2065             : 
    2066             : /* idealfactorback for { I } x W[1] x ... assuming all W[i] have d entries */
    2067             : static GEN
    2068       34349 : idlist(GEN nf, GEN I, GEN W)
    2069             : {
    2070       34349 :   long i, j, d, l = lg(W);
    2071             :   GEN v, w;
    2072       34349 :   if (l == 1) return mkvec(I? I: gen_1);
    2073          63 :   w = gel(W,1); d = lg(w)-1;
    2074          63 :   if (!I) v = w;
    2075             :   else
    2076             :   {
    2077           7 :     v = cgetg(d + 1, t_VEC);
    2078          28 :     for (j = 1; j <= d; j++) gel(v,j) = idealmul(nf, I, gel(w,j));
    2079             :   }
    2080          98 :   for (i = 2; i < l; i++)
    2081             :   {
    2082          35 :     long nv = lg(v)-1, c, k;
    2083          35 :     GEN V = cgetg(d*nv + 1, t_VEC);
    2084          35 :     w = gel(W,i);
    2085         224 :     for (j = c = 1; j <= nv; j++)
    2086         756 :       for (k = 1; k <= d; k++) gel(V, c++) = idealmul(nf, gel(v,j), gel(w,k));
    2087          35 :     v = V;
    2088             :   }
    2089          63 :   return v;
    2090             : }
    2091             : 
    2092             : static GEN
    2093        4165 : issquareclass(GEN bnf, GEN x, long rc)
    2094             : {
    2095        4165 :   GEN v, d, cyc = bnf_get_cyc(bnf), nf = bnf_get_nf(bnf);
    2096        4165 :   GEN e = isprincipal(bnf, x);
    2097        4165 :   long l = lg(cyc), j;
    2098             : 
    2099        4165 :   v = cgetg(l, t_VEC);
    2100        4270 :   for (j = 1; j <= rc; j++)
    2101             :   {
    2102         287 :     if (mpodd(gel(e,j))) return NULL;
    2103         105 :     gel(v, j) = subii(gel(cyc,j), gel(e,j));
    2104             :   }
    2105        4074 :   for (; j < l; j++)
    2106             :   {
    2107          91 :     GEN t = subii(gel(cyc,j), gel(e,j));
    2108          91 :     if (mpodd(t)) t = addii(t, gel(cyc,j));
    2109          91 :     gel(v, j) = t;
    2110             :   }
    2111             :   /* all exponents are even */
    2112        3983 :   x = isprincipalfact(bnf, x, bnf_get_gen(bnf), v, nf_GENMAT | nf_FORCE);
    2113             :   /* reduce generator mod squares */
    2114        3983 :   x = gel(x,2); x = nffactorback(nf, gel(x,1), ZV_to_Flv(gel(x,2), 2));
    2115        3983 :   x = nfmul(nf, x, nfsqr(nf, idealredmodpower(nf, x, 2, 0)));
    2116        3983 :   x = Q_remove_denom(x, &d); return d? gmul(x, d): x;
    2117             : }
    2118             : /* v a vector of ideals of same norm */
    2119             : static GEN
    2120       35007 : S4makeidclass(GEN bnf, GEN v, long rc)
    2121             : {
    2122       35007 :   long j, c, l = lg(v);
    2123       35007 :   GEN w = cgetg(l, t_VEC);
    2124       70546 :   for (j = c = 1; j < l; j++)
    2125             :   {
    2126       35539 :     GEN N, a, I = gel(v,j);
    2127       35539 :     if (typ(I) == t_INT) a = gen_1;
    2128             :     else
    2129             :     {
    2130        4165 :       if (!(a = issquareclass(bnf, I, rc))) continue; /* I^2 = (a)(mod K^*)^2 */
    2131        3983 :       N = nfnorm(bnf,a);
    2132        3983 :       if (signe(N) < 0) a = gneg(a);/* Norm(a)=|N| is a square */
    2133             :     }
    2134       35357 :     gel(w, c++) = mkvec2(I, a);
    2135             :   }
    2136       35007 :   setlg(w, c); return w;
    2137             : }
    2138             : 
    2139             : /* L squarefree outside of 2, v2(L) <= 4, P = prime divisors of L.
    2140             :  * Write L = N*2^v2, v2 <= 4, N odd sqfree.
    2141             :  * List of squarefree ideals A of norm N^2 (and 4N^2 if v2 > 1) */
    2142             : static GEN
    2143       40411 : S4makeid(GEN bnf, long isA4, long v2, GEN P)
    2144             : {
    2145       40411 :   GEN V, V3, v, id, w, d2, nf = bnf_get_nf(bnf);
    2146             :   long c, c3, i, k, l, n2, rc;
    2147             : 
    2148       40411 :   l = lg(P); V = cgetg(l, t_VEC); V3 = cgetg(l, t_VEC);
    2149       43526 :   for (i = v2? 2: 1, c = c3 = 1; i < l; i++)
    2150             :   {
    2151        9177 :     GEN p = gel(P, i), d = cubictypedec(nf, p);
    2152        9177 :     if (!d) return NULL;
    2153        3115 :     if (lg(d) == 4) gel(V3, c3++) = d; else gel(V,c++) = gel(d, 1);
    2154             :   }
    2155       34349 :   d2 = (v2 > 1)? cubictypedec(nf, gen_2): NULL;
    2156       34349 :   if (isA4)
    2157             :   { /* choose representative in C3 orbit */
    2158        3899 :     if (c3 > 1) gel(V, c++) = gmael(V3, --c3, 1);
    2159        3073 :     else if (d2 && lg(d2) == 4) d2 = mkvec(gel(d2,1));
    2160             :   }
    2161       34349 :   setlg(V,c); setlg(V3,c3);
    2162       34349 :   id = c > 1? idealfactorback(nf, V, NULL, 0): NULL;
    2163       34349 :   v = idlist(nf, id, V3); rc = r2(bnf_get_cyc(bnf));
    2164       34349 :   if (!d2) return mkvec(S4makeidclass(bnf, v, rc));
    2165         658 :   n2 = lg(d2)-1; l = lg(v); w = cgetg(n2 * (l-1) + 1, t_VEC);
    2166        1316 :   for (i = c = 1; i < l; i++)
    2167        1344 :     for (k = 1; k <= n2; k++) gel(w, c++) = idealmul(nf, gel(v,i), gel(d2,k));
    2168         658 :   return mkvec2(v2 == 4? cgetg(1,t_VEC): S4makeidclass(bnf, v, rc),
    2169             :                 S4makeidclass(bnf, w, rc));
    2170             : }
    2171             : 
    2172             : static int
    2173       65775 : checkS4data(GEN x)
    2174       65775 : { return lg(x) == 6 && typ(gel(x, 5)) == t_VECSMALL; }
    2175             : 
    2176             : static GEN
    2177       65776 : S4data(GEN pol, long s)
    2178             : {
    2179             :   GEN bnf, nf, lvunit, Gid, sgnu;
    2180             :   long isA4;
    2181             : 
    2182       65776 :   if (checkS4data(pol)) return pol;
    2183       23949 :   bnf = Buchall(pol, nf_FORCE, DEFAULTPREC);
    2184       23954 :   nf = bnf_get_nf(bnf); Gid = makeGid(nf);
    2185       23953 :   lvunit = makevunits(bnf); isA4 = Z_issquare(nf_get_disc(nf));
    2186       23954 :   sgnu = (s != -1 && nf_get_r1(nf) == 3)? nfsign(nf, lvunit): gen_0;
    2187       23954 :   return mkvecn(5, bnf, lvunit, Gid, sgnu, mkvecsmall(isA4));
    2188             : }
    2189             : static GEN
    2190       23849 : S4_get_disc(GEN S) { return nf_get_disc(bnf_get_nf(gel(S,1))); }
    2191             : 
    2192             : static int
    2193        2541 : cmp2(void *E,GEN x,GEN y)
    2194        2541 : { (void)E; return cmpii(gel(x,2), gel(y,2)); }
    2195             : 
    2196             : /* Find quartic A4 or S4-extensions of Q with resolvent pol and square root of
    2197             :  * norm of relative discriminant = L; disc(K/Q) = L^2 nfdisc(pol).
    2198             :  * Here s = -1 or (0, 1, 2) */
    2199             : static GEN
    2200       41930 : makeA4S4(GEN pol, GEN L, long s)
    2201             : {
    2202       41930 :   GEN DATA = S4data(pol, s), bnf = gel(DATA, 1), nf = bnf_get_nf(bnf);
    2203       41930 :   GEN lvunit = gel(DATA, 2), Gid = gel(DATA, 3), sgnunit = gel(DATA, 4);
    2204       41930 :   GEN sgnal0 = NULL, vI, V, P, L2;
    2205       41930 :   long nu, l, c, c1, i, j, k, v2, r1 = nf_get_r1(nf), isA4 = gel(DATA, 5)[1];
    2206             : 
    2207       41930 :   if (s != -1 && ((r1 == 1 && s != 1) || (r1 == 3 && s == 1))) return NULL;
    2208       40453 :   if (typ(L) == t_VEC)
    2209       38990 :   { P = gel(L,1); L = gel(L,2); v2 = vali(L); }
    2210             :   else
    2211             :   {
    2212             :     GEN fa;
    2213        1463 :     v2 = vali(L); if (v2 > 4) return NULL;
    2214        1463 :     fa = Z_factor(L); if (!ZV_is_1(gel(fa,2), v2? 2: 1)) return NULL;
    2215        1421 :     P = gel(fa,1);
    2216             :   }
    2217       40411 :   L2 = v2? shifti(L, -v2): L;
    2218       40411 :   vI = S4makeid(bnf, isA4, v2, P); if (!vI) return NULL;
    2219       34349 :   l = lg(vI); nu = lg(lvunit) - 1;
    2220       34349 :   V = cgetg(RgVV_nb(vI) * nu + 1, t_VEC); c = 1; c1 = 0;
    2221       69355 :   for (k = 1; k < l; k++) /* l = 2 or 3 */
    2222             :   {
    2223       35007 :     GEN I = gel(vI, k);
    2224       35007 :     int norm1 = k == 1 && equali1(L2);
    2225       70364 :     for (j = 1; j < lg(I); j++)
    2226             :     {
    2227       35356 :       GEN ideal = gmael(I, j, 1), al0 = gmael(I, j, 2);
    2228       35356 :       if (s != -1 && r1 == 3) sgnal0 = nfsign(nf, al0);
    2229      103647 :       for (i = norm1? 2 : 1; i <= nu; i++)
    2230             :       {
    2231             :         GEN T, a1, a2, a3, a;
    2232       68290 :         if (sgnal0 && !!s == zv_equal0(Flv_add(sgnal0, gel(sgnunit,i), 2)))
    2233       10682 :           continue;
    2234       57609 :         a = nfmul(nf, al0, gel(lvunit, i));
    2235       57608 :         if (v2 != quadcubpow(bnf, Gid, ideal, a) + (k == 1? 0 : 1)) continue;
    2236        7350 :         if (isA4 && norm1) c1++;
    2237        7350 :         a = nf_to_scalar_or_alg(nf, a);
    2238        7350 :         T = QXQ_charpoly(a, nf_get_pol(nf), 0);
    2239        7350 :         a1 = gel(T,4); a2 = gel(T,3); a3 = negi(gel(T,2));
    2240        7350 :         T = mkpoln(5, gen_1, gen_0, shifti(a1,1), mulsi(-8,sqrti(a3)),
    2241             :                    subii(sqri(a1), shifti(a2, 2)));
    2242        7350 :         gel(V, c++) = isA4? polredabs(T): T;
    2243             :       }
    2244             :     }
    2245             :   }
    2246       34348 :   if (c == 1) return NULL;
    2247        6166 :   setlg(V, c); return isA4? A4clean3(V, c1): V;
    2248             : }
    2249             : 
    2250             : /* A4 fields of square root discriminant = N and "signature" s */
    2251             : static GEN
    2252          49 : makeA4_i(GEN N2, GEN field, long s)
    2253             : {
    2254             :   GEN N, v;
    2255          49 :   if (s == 1 || !Z_issquareall(N2, &N)) return NULL;
    2256          42 :   if (field)
    2257             :   {
    2258           7 :     GEN D = checkfield(field, 3), d, cond;
    2259           7 :     if (!Z_issquareall(D, &d) || !(cond = divide(N,d))
    2260           7 :         || !(v = makeA4S4(field, cond, s))) return NULL;
    2261             :   }
    2262             :   else
    2263             :   {
    2264          35 :     GEN D = divisors(N);
    2265          35 :     long i, cv, l = lg(D);
    2266          35 :     v = cgetg(l, t_VEC);
    2267         119 :     for (i = cv = 1; i < l; i++)
    2268             :     {
    2269          84 :       GEN w, m = gel(D, i), n = gel(D, l-i), C = makeC3_f(m);
    2270          84 :       long j, c, lC = lg(C);
    2271          91 :       for (j = c = 1; j < lC; j++)
    2272           7 :         if ((w = makeA4S4(gel(C,j), n, s))) gel(C,c++) = w;
    2273          84 :       if (c == 1) continue;
    2274           7 :       setlg(C,c); gel(v,cv++) = shallowconcat1(C);
    2275             :     }
    2276          35 :     setlg(v,cv); v = myshallowconcat1(v);
    2277             :   }
    2278          42 :   return v;
    2279             : }
    2280             : static GEN
    2281          49 : makeA4(GEN N, GEN field, long s)
    2282             : {
    2283          49 :   GEN v = makeA4_i(N, field, maxss(s, -1));
    2284          49 :   return v? sturmseparate(v, s, 4): NULL;
    2285             : }
    2286             : 
    2287             : static GEN
    2288          77 : makeS4_i(GEN N, GEN field, long s)
    2289             : {
    2290             :   GEN v;
    2291          77 :   if (field)
    2292             :   {
    2293          28 :     GEN q, f, D = checkfield(field, 3);
    2294          28 :     if (!(q = divide(N, D))) return NULL;
    2295          28 :     setsigne(q, s == 2? -signe(q): 1);
    2296          28 :     if (!Z_issquareall(q, &f) || !(v = makeA4S4(field, f, s))) return NULL;
    2297             :   }
    2298             :   else
    2299             :   {
    2300          49 :     GEN f, M = divisors(N);
    2301          49 :     long i, cv, l = lg(M);
    2302          49 :     v = cgetg(l, t_VEC); if (!odd(s)) s = 0;
    2303         112 :     for (i = cv = 1; i < l; i++)
    2304          63 :       if (Z_issquareall(gel(M, l-i), &f))
    2305             :       {
    2306             :         GEN w, D;
    2307             :         long j, c, lD;
    2308          49 :         if (!(D = makeDL(3, gel(M,i), NULL, s))) continue;
    2309           7 :         lD = lg(D);
    2310          14 :         for (j = c = 1; j < lD; j++)
    2311           7 :           if ((w = makeA4S4(gel(D,j), f, s))) gel(D, c++) = w;
    2312           7 :         if (c == 1) continue;
    2313           7 :         setlg(D, c); gel(v, cv++) = shallowconcat1(D);
    2314             :       }
    2315          49 :     if (cv == 1) return NULL;
    2316           7 :     setlg(v,cv); v = shallowconcat1(v);
    2317             :   }
    2318          35 :   return v;
    2319             : }
    2320             : static GEN
    2321          77 : makeS4(GEN N, GEN field, long s)
    2322             : {
    2323          77 :   GEN v = makeS4_i(N, field, maxss(s, -1));
    2324          77 :   return v? sturmseparate(v, s, 4): NULL;
    2325             : }
    2326             : 
    2327             : static long
    2328          63 : gal_get_order(GEN G) { return degpol(gal_get_pol(G)); }
    2329             : 
    2330             : /* P is monic */
    2331             : static GEN
    2332          28 : makeA4S4resolvent(GEN P, long flag)
    2333             : {
    2334          28 :   GEN R, a0 = gel(P,2), a1 = gel(P,3), a2 = gel(P,4), a3 = gel(P,5);
    2335          28 :   GEN b0 = subii(mulii(a0, subii(shifti(a2,2), sqri(a3))), sqri(a1));
    2336          28 :   GEN b1 = subii(mulii(a3, a1), shifti(a0,2));
    2337          28 :   R = mkpoln(4, gen_1, negi(a2), b1, b0); setvarn(R, varn(P));
    2338          28 :   R = polredabs(R);
    2339          28 :   return flag? mkvec2(R, sqrti(divii(nfdisc(P), nfdisc(R)))): R;
    2340             : }
    2341             : 
    2342             : static GEN
    2343       41594 : A4S4_fa(GEN DATA, GEN fa, long cond, long s)
    2344             : {
    2345       41594 :   pari_sp av = avma;
    2346       41594 :   GEN w, P = gel(fa,1), E = gel(fa,2);
    2347       41594 :   if (odd(cond))
    2348       30548 :   { if (!zv_is_1(E, 1)) return gc_NULL(av); }
    2349             :   else
    2350       11045 :     if (E[1] > 4 || !zv_is_1(E, 2)) return gc_NULL(av);
    2351       40467 :   if (!(w = makeA4S4(DATA, mkvec2(Flv_to_ZV(P), utoipos(cond)), s)))
    2352       34594 :     return gc_NULL(av);
    2353        5873 :   return gerepilecopy(av, w);
    2354             : }
    2355             : static GEN
    2356       22713 : nflist_A4S4_worker_i(GEN P3, GEN X, GEN Xinf, long s)
    2357             : {
    2358       22713 :   GEN v, w, F, DATA = S4data(P3, s), D3 = absi_shallow(S4_get_disc(DATA));
    2359       22715 :   long i, c, f, linf, limf = floorsqrtdiv(X, D3);
    2360             : 
    2361       22715 :   linf = cmpii(Xinf, shifti(D3, 2)) >= 0? ceilsqrtdiv(Xinf, D3): 1;
    2362       22714 :   v = cgetg(limf - linf + 2, t_VEC);
    2363       22714 :   F = vecfactoru_i(linf, limf);
    2364       59577 :   for (f = linf, i = c = 1; f <= limf; f++, i++)
    2365       36862 :     if ((w = A4S4_fa(DATA, gel(F,i), f, s))) gel(v, c++) = w;
    2366       22715 :   setlg(v, c); return myshallowconcat1(v);
    2367             : }
    2368             : GEN
    2369       22698 : nflist_A4S4_worker(GEN P3, GEN X, GEN Xinf, GEN gs)
    2370             : {
    2371       22698 :   pari_sp av = avma;
    2372       22698 :   return gerepilecopy(av, nflist_A4S4_worker_i(P3, X, Xinf, gs[1]));
    2373             : }
    2374             : 
    2375             : static GEN
    2376          91 : makeA4S4vec(long A4, GEN X, GEN Xinf, GEN field, long s)
    2377             : {
    2378          91 :   long snew = s == -2? -1: s;
    2379             :   GEN v;
    2380             : 
    2381          91 :   if (field)
    2382             :   {
    2383          21 :     GEN D = checkfield(field, 3);
    2384          21 :     long sD = signe(D);
    2385          21 :     if (A4 != Z_issquare(D) || abscmpii(D, X) > 0 ||
    2386          14 :         (sD > 0 && snew == 1) || (sD < 0 && !odd(snew)))
    2387           7 :           return NULL;
    2388          14 :     v = nflist_A4S4_worker_i(field, X, Xinf, snew);
    2389             :   }
    2390             :   else
    2391             :   {
    2392          35 :     v = A4? makeC3vec(X, gen_1, NULL, 0)
    2393          70 :           : makeS3vec(X, gen_1, NULL, odd(snew)? snew: 0);
    2394          70 :     if (!v) return NULL;
    2395          70 :     v = gen_parapply(closure("_nflist_A4S4_worker",
    2396             :                              mkvec3(X,Xinf,mkvecsmall(snew))), v);
    2397          70 :     v = myshallowconcat1(v);
    2398             :   }
    2399          84 :   return sturmseparate(v, s, 4);
    2400             : }
    2401             : 
    2402             : /**********************************************************************/
    2403             : /*                                 C5                                 */
    2404             : /**********************************************************************/
    2405             : /* elements in B have the same norm */
    2406             : static void
    2407         427 : C5cleanB(GEN nf, GEN aut, GEN B)
    2408             : {
    2409         427 :   long l = lg(B), c, i, j, k;
    2410         427 :   GEN W = const_vecsmall(l - 1, 1);
    2411        2135 :   for (i = c = 1; i < l; i++)
    2412             :   {
    2413             :     GEN bi, d;
    2414        1708 :     if (!W[i]) continue;
    2415         427 :     gel(B, c++) = gel(B,i);
    2416         427 :     bi = Q_remove_denom(nfinv(nf, gel(B,i)), &d); /*1/b = bi / d */
    2417        1708 :     for (j = 1; j <= 3; j++)
    2418             :     {
    2419        1281 :       bi = galoisapply(nf, aut, bi);
    2420        2561 :       for (k = i + 1; k < l; k++)
    2421             :       {
    2422             :         GEN a;
    2423        2561 :         if (!W[k]) continue;
    2424        2015 :         a = nfmuli(nf, bi, gel(B,k)); /* bi/d * B[k] has norm 1 or -1 */
    2425        2015 :         if (absequalii(content(a), d)) { W[k] = 0; break; }
    2426             :       }
    2427             :     }
    2428             :   }
    2429         427 :   setlg(B, c);
    2430         427 : }
    2431             : 
    2432             : static GEN
    2433        1820 : makepolC5(GEN nf, GEN e, GEN b, GEN aut)
    2434             : {
    2435        1820 :   GEN b1 = galoisapply(nf, aut, b), t1 = nfmuli(nf, b, b1);
    2436        1818 :   GEN b2 = galoisapply(nf, aut, b1);
    2437        1820 :   GEN t2 = nfmuli(nf, t1, nfmuli(nf, b1, b2));
    2438        1819 :   GEN v = cgetg(8, t_POL);
    2439        1819 :   v[1] = evalsigne(1) | evalvarn(0);
    2440        1819 :   gel(v, 7) = gen_1;
    2441        1819 :   gel(v, 6) = gen_0;
    2442        1819 :   gel(v, 5) = mulsi(-10, e);
    2443        1820 :   gel(v, 4) = mulsi(-5, mulii(e, nftrace(nf, t1)));
    2444        1819 :   gel(v, 3) = mului(5, mulii(e, subii(e, nftrace(nf,t2))));
    2445        1819 :   gel(v, 2) = mulii(negi(e), nftrace(nf, nfmuli(nf, t1, t2)));
    2446        1817 :   if (umodiu(e, 5)) v = ZX_translate(v, gen_m1);
    2447        1820 :   return ZX_Z_divexact(ZX_z_unscale(v, 5), utoipos(3125));
    2448             : }
    2449             : 
    2450             : /* b a pr-unit; multiply by a unit so that z u = 1 (mod pr5^2) */
    2451             : static GEN
    2452        1820 : C5prim(GEN nf, GEN pr5, GEN z, GEN eps, GEN b)
    2453             : {
    2454        1820 :   GEN pol = nf_get_pol(nf);
    2455             :   long k, j;
    2456        1820 :   if (typ(b) != t_POL) b = scalarpol_shallow(b, varn(pol));
    2457        3114 :   for (j = 0; j <= 1; j++)
    2458             :   {
    2459        3106 :     GEN g = j ? b : ZXQ_mul(b, eps, pol);
    2460       23110 :     for (k = 0; k <= 9; k++)
    2461             :     {
    2462       21816 :       if (idealval(nf, gsubgs(g, 1), pr5) > 1) return g;
    2463       19944 :       if (k < 9) g = ZXQ_mul(g, z, pol);
    2464             :     }
    2465             :   }
    2466           8 :   pari_err_BUG("C5prim");
    2467             :   return NULL; /* LCOV_EXCL_LINE */
    2468             : }
    2469             : 
    2470             : static GEN
    2471          56 : C5bnf()
    2472             : {
    2473          56 :   GEN bnf = Buchall(polcyclo(5,1), nf_FORCE, DEFAULTPREC), nf = bnf_get_nf(bnf);
    2474          56 :   GEN aut = poltobasis(nf, pol_xn(2, 1));
    2475          56 :   GEN p5 = idealprimedec_galois(nf, utoipos(5));
    2476          56 :   return mkvec3(bnf, aut, p5);
    2477             : }
    2478             : 
    2479             : static GEN
    2480        3956 : polsubcycloC5_i(GEN N, GEN T)
    2481             : {
    2482             :   GEN bnf, nf, pol, B, aut, z, eps, p5, N5, P;
    2483             :   long fl5, i, l, v;
    2484             : 
    2485        3956 :   if (!checkcondCL(N, 5, &P)) return NULL;
    2486         466 :   if (typ(N) == t_VEC) N = gel(N,1);
    2487         466 :   if (!T) T = C5bnf();
    2488         466 :   bnf = gel(T, 1); nf = bnf_get_nf(bnf); pol = nf_get_pol(nf);
    2489         476 :   aut = gel(T, 2);
    2490         476 :   p5 = gel(T, 3); v = varn(pol);
    2491         476 :   z = monomial(gen_m1, 1, v); /* tu */
    2492         476 :   eps = deg1pol_shallow(gen_1, gen_1, v); /* fu */
    2493         476 :   N5 = divis_rem(N, 25, &fl5); if (fl5) N5 = N; /* fl5 is set if 5 \nmid N */
    2494         476 :   N5 = mkvec2(N5, P2fa(P));
    2495         476 :   B = bnfisintnorm(bnf, N5); l = lg(B);
    2496        2296 :   for (i = 1; i < l; i++) gel(B, i) = C5prim(nf, p5, z, eps, gel(B, i));
    2497         476 :   if (fl5)
    2498             :   {
    2499         427 :     B = matalgtobasis(nf, B);
    2500         427 :     C5cleanB(nf, aut, B);
    2501             :   }
    2502             :   else
    2503             :   {
    2504          49 :     GEN b5 =  mkpoln(4, gen_m1, gen_1, gen_1, gen_m1); /* norm 25 */
    2505          49 :     setvarn(b5, v); B = matalgtobasis(nf, RgXQV_RgXQ_mul(B, b5, pol));
    2506             :   }
    2507        2294 :   for (i = 1; i < l; i++) gel(B, i) = makepolC5(nf, N, gel(B, i), aut);
    2508         474 :   return B;
    2509             : }
    2510             : 
    2511             : static GEN
    2512          49 : makeC5(GEN N, GEN field, long s)
    2513             : {
    2514             :   GEN sqN, v;
    2515          49 :   checkfield_i(field, 1);
    2516          49 :   if (s > 0 || !Z_ispowerall(N, 4, &sqN)
    2517          49 :      || !(v = polsubcycloC5_i(sqN, NULL))) return NULL;
    2518          14 :   return s == -2? vecs(3,v): v;
    2519             : }
    2520             : 
    2521             : GEN
    2522        3907 : nflist_C5_worker(GEN N, GEN T)
    2523             : {
    2524        3907 :   pari_sp av = avma;
    2525        3907 :   GEN v = polsubcycloC5_i(N, T);
    2526        3896 :   if (!v) { set_avma(av); return cgetg(1, t_VEC); }
    2527         448 :   return gerepilecopy(av, v);
    2528             : }
    2529             : 
    2530             : static GEN
    2531          42 : makeC5vec(GEN X, GEN Xinf, GEN field, long s)
    2532             : {
    2533             :   GEN v, F, bnfC5;
    2534             :   long x, xinf, i, l;
    2535             : 
    2536          42 :   checkfield_i(field, 1); if (s > 0) return NULL;
    2537          28 :   xinf = ceilsqrtn(Xinf, 4);
    2538          28 :   x = floorsqrtn(X, 4); bnfC5 = C5bnf();
    2539          28 :   if (!odd(xinf)) xinf++;
    2540          28 :   if (!odd(x)) x--;
    2541          28 :   F = vecfactoroddu_i(xinf, x); l = lg(F);
    2542        3983 :   for (i = 1; i < l; i++)
    2543        3955 :     gel(F,i) = mkvec2(utoipos(xinf + ((i - 1) << 1)), zm_to_ZM(gel(F,i)));
    2544          28 :   v = gen_parapply(closure("_nflist_C5_worker", mkvec(bnfC5)), F);
    2545          28 :   v = myshallowconcat1(v); return s == -2? vecs(3, v): v;
    2546             : }
    2547             : 
    2548             : /**********************************************************************/
    2549             : /*                            CL (ell prime)                          */
    2550             : /**********************************************************************/
    2551             : /* polredabs iff |nfdisc(pol)| = N */
    2552             : static GEN
    2553         105 : ZX_red_disc(GEN pol, GEN N)
    2554             : {
    2555         105 :   GEN d, B = nfbasis(mkvec2(pol, utoipos(500000)), &d);
    2556         105 :   return absequalii(d, N)? polredabs(mkvec2(pol,B)): NULL;
    2557             : }
    2558             : /* polredabs iff Xinf <= |nfdisc(pol)| <= X */
    2559             : static GEN
    2560         749 : ZX_red_disc2(GEN pol, GEN Xinf, GEN X)
    2561             : {
    2562         749 :   GEN d, B = nfbasis(mkvec2(pol, utoipos(500000)), &d);
    2563         749 :   if (abscmpii(d, X) > 0 || abscmpii(d, Xinf) < 0) return NULL;
    2564         504 :   return polredabs(mkvec2(pol,B));
    2565             : }
    2566             : 
    2567             : /* make CL(f^(ell-1), 0) */
    2568             : static GEN
    2569          98 : makeCL_f(long ell, GEN F)
    2570             : {
    2571          98 :   GEN bnf, P, f = typ(F) == t_VEC? gel(F,1): F;
    2572          98 :   if (!checkcondCL(F, ell, &P)) return cgetg(1,t_VEC);
    2573          56 :   bnf = bnfY(pol_x(1));
    2574          56 :   P = Pell2prfa(bnf_get_nf(bnf), P, ell, f);
    2575          56 :   return mybnrclassfield(bnf, P, ell);
    2576             : }
    2577             : /* ell odd prime */
    2578             : static GEN
    2579         105 : makeCL(long ell, GEN N, GEN field, long s)
    2580             : {
    2581             :   GEN F, v;
    2582         105 :   checkfield_i(field, 1);
    2583         105 :   if (s > 0 || !Z_ispowerall(N, ell-1, &F)) return NULL;
    2584          77 :   v = makeCL_f(ell, F); return s != -2? v: vecs((ell-1)/2, v);
    2585             : }
    2586             : 
    2587             : static GEN
    2588          49 : makeCLresolvent(long ell, GEN pol, long flag)
    2589             : {
    2590          49 :   if (!odd(flag)) return pol_x(0);
    2591          28 :   return mkvec2(pol_x(0), sqrtnint(checkfield(pol, ell), ell-1));
    2592             : }
    2593             : 
    2594             : static GEN
    2595       11410 : RgXV_polred(GEN x)
    2596       11711 : { pari_APPLY_same(polredabs(gel(x,i))); }
    2597             : 
    2598             : GEN
    2599       11375 : nflist_CL_worker(GEN f, GEN bnf, GEN gell)
    2600             : {
    2601       11375 :   pari_sp av = avma;
    2602       11375 :   return gerepileupto(av, RgXV_polred(mybnrclassfield(bnf, f, gell[1])));
    2603             : }
    2604             : 
    2605             : static GEN
    2606         238 : makeCLvec(long ell, GEN X, GEN Xinf, GEN field, long s)
    2607             : {
    2608         238 :   long em1 = ell - 1, x, xinf, f;
    2609             :   GEN v, bnf, F;
    2610             : 
    2611         238 :   checkfield_i(field, 1); if (s > 0) return NULL;
    2612         196 :   xinf = ceilsqrtn(Xinf, em1);
    2613         196 :   x = floorsqrtn(X, em1); bnf = bnfY(pol_x(1));
    2614         196 :   F = cgetg(x - xinf + 2, t_VEC);
    2615       11613 :   for (f = xinf; f <= x; f++)
    2616       11417 :     gel(F, f - xinf + 1) = utoipos(f);
    2617         196 :   v = gen_parapply(closure("_nflist_CL_worker", mkvec2(bnf, mkvecsmall(ell))), F);
    2618         196 :   v = myshallowconcat1(v); return s == -2? vecs(em1>>1, v): v;
    2619             : }
    2620             : 
    2621             : /**********************************************************************/
    2622             : /*                            DL (ell prime)                          */
    2623             : /**********************************************************************/
    2624             : /* For metacyclic groups; assume G is Galois and non-abelian */
    2625             : static GEN
    2626         945 : getpol(GEN nf, GEN T)
    2627             : {
    2628         945 :   GEN G = galoisinit(rnfequation(nf, T), NULL);
    2629         945 :   return galoisfixedfield(G, vecsplice(gal_get_gen(G), 1), 1, 0);
    2630             : }
    2631             : 
    2632             : static GEN
    2633        1421 : makeDL(long ell, GEN N, GEN field, long s)
    2634             : {
    2635        1421 :   GEN v, vD, F = N;
    2636        1421 :   long i, l, c, si = 0, pow = (ell - 1) >> 1;
    2637             : 
    2638        1421 :   if (s > 0 && s != pow) return NULL;
    2639        1386 :   if (ell != 3 && !Z_ispowerall(N, pow, &F)) return NULL;
    2640        1386 :   if (field)
    2641             :   {
    2642          42 :     GEN q, D = checkfield(field, 2);
    2643          42 :     si = signe(D);
    2644          42 :     if ((s > 0 && si > 0) || (!s && si < 0)) return NULL;
    2645          42 :     D = absi_shallow(D);
    2646          42 :     if (!(q = divide(F, D))) return NULL;
    2647          42 :     vD = mkvec2(q, D);
    2648             :   }
    2649        1344 :   else vD = divisors(F);
    2650        1386 :   l = lg(vD); v = cgetg(2 * l, t_VEC);
    2651       14462 :   for (i = 2, c = 1; i < l; i++) /* omit 1 */
    2652             :   {
    2653       13076 :     GEN LD, f, M = gel(vD, i);
    2654             :     int p, m;
    2655             :     long j;
    2656       15225 :     if (!Z_issquareall(gel(vD, l-i), &f)) continue;
    2657        3381 :     is_fundamental_pm(M, s, &p, &m);
    2658        3381 :     if (si < 0) p = 0;
    2659        3381 :     if (si > 0) m = 0;
    2660        3381 :     if (!(LD = fund_pm(M, p, m))) continue;
    2661        2639 :     for (j = 1; j < lg(LD); j++)
    2662             :     {
    2663        1407 :       GEN D = gel(LD, j), R, bnf, P, G, pol;
    2664             :       long k, lR;
    2665        1883 :       if (!checkcondDL(D, f, ell, &P)) continue;
    2666         728 :       pol = Y2m(gel(LD,j)); bnf = bnfY(pol);
    2667         728 :       G = mkvec2(galoisinit(pol,NULL), gen_2);
    2668         728 :       P = Pell2prfa(bnf_get_nf(bnf), P, ell, f);
    2669         728 :       R = mybnrclassfield_X(bnf, P, ell, NULL, NULL, G);
    2670         728 :       lR = lg(R); if (lR == 1) continue;
    2671             :       /* L/Q degree ell subfield of R; d(L) = F^pow, F = D f^2 */
    2672         504 :       for (k = 1; k < lR; k++) gel(R,k) = polredabs(getpol(bnf, gel(R,k)));
    2673         252 :       gel(v, c++) = R;
    2674             :     }
    2675             :   }
    2676        1386 :   if (c == 1) return NULL;
    2677         238 :   setlg(v, c); return sturmseparate(myshallowconcat1(v), s, ell);
    2678             : }
    2679             : /* ell >= 5 prime */
    2680             : static GEN
    2681          35 : makeDLresolvent(long ell, GEN pol, long flag)
    2682             : {
    2683          35 :   GEN Dpow = checkfield(pol, ell), D, DF, F;
    2684          35 :   long d4, pow = (ell - 1) >> 1, si = signe(Dpow);
    2685          35 :   D = si > 0 ? sqrtnint(Dpow, pow) : negi(sqrtnint(negi(Dpow), pow));
    2686          35 :   d4 = Mod4(D);
    2687          35 :   if (d4 == 3 || (d4 == 0 && si > 0 && pol2s(pol))) D = negi(D);
    2688          21 :   else if (d4 == 2) D = shifti(D, 2);
    2689          35 :   DF = coredisc2(D); D = quadpoly_i(gel(DF, 1)); F = gel(DF, 2);
    2690          35 :   return flag? mkvec2(D, F): D;
    2691             : }
    2692             : 
    2693             : GEN
    2694        6433 : nflist_DL_worker(GEN P2, GEN X1pow, GEN X0pow, GEN X2, GEN Xinf2, GEN gell)
    2695             : {
    2696        6433 :   pari_sp av = avma;
    2697        6433 :   GEN X, Xinf, G, D, Da, V, bnf = bnfY(P2), nf = bnf_get_nf(bnf);
    2698        6433 :   long f, c, limf, linf, ell = gell[1];
    2699             : 
    2700        6433 :   G = mkvec2(galoisinit(nf_get_pol(nf),NULL), gen_2);
    2701        6433 :   D = bnf_get_disc(bnf);
    2702        6433 :   Da = absi_shallow(D);
    2703        6433 :   limf = floorsqrtdiv(X1pow, Da);
    2704        6432 :   linf = cmpii(X0pow, shifti(Da, 2)) >= 0? ceilsqrtdiv(X0pow, Da): 1;
    2705        6431 :   V = cgetg(limf + 1, t_VEC);
    2706             :   /* K/Q degree l with D_l Galois closure L/Q and k/Q quadratic resolvent
    2707             :    * Then d_k = D, d_K = D^(l-1)/2 f^(l-1), d_L = D^l f^(2l-2).
    2708             :    * Want d_K in [Xinf,X], i.e. d_L in D [Xinf^2,X^2] */
    2709        6432 :   Xinf = mulii(Da, Xinf2); X = mulii(Da, X2);
    2710       15456 :   for (f = linf, c = 1; f <= limf; f++)
    2711             :   {
    2712        9023 :     pari_sp av2 = avma;
    2713        9023 :     GEN P, R, F = utoipos(f);
    2714             :     long lR, k;
    2715       15070 :     if (!checkcondDL(D, F, ell, &P)) { set_avma(av2); continue; }
    2716        6433 :     P = Pell2prfa(nf, P, ell, F);
    2717        6433 :     R = mybnrclassfield_X(bnf, P, ell, X, Xinf, G);
    2718        6433 :     lR = lg(R); if (lR == 1) { set_avma(av2); continue; }
    2719         770 :     for (k = 1; k < lR; k++) gel(R,k) = polredabs(getpol(bnf, gel(R,k)));
    2720         385 :     gel(V, c++) = R;
    2721             :   }
    2722        6433 :   setlg(V,c); return gerepilecopy(av, myshallowconcat1(V));
    2723             : }
    2724             : 
    2725             : static GEN
    2726        1211 : makeDLvec(long ell, GEN X, GEN Xinf, GEN field, long s)
    2727             : {
    2728             :   GEN v, X1pow, X0pow, V2;
    2729        1211 :   long pow = (ell - 1) >> 1;
    2730             : 
    2731        1211 :   checkfield_i(field, 2); if (s > 0 && s != pow) return NULL;
    2732        1162 :   if (s == pow) s = 1;
    2733        1162 :   X1pow = sqrtnint(X, pow);
    2734        1162 :   X0pow = gceilsqrtn(Xinf, pow);
    2735        1162 :   V2 = field? mkvec(field): makeC2vec(X1pow, gen_1, NULL, s == -2? -1: s);
    2736        1162 :   if (!V2) return NULL;
    2737        1162 :   v = gen_parapply(closure("_nflist_DL_worker", mkvec5(X1pow, X0pow, sqri(X),
    2738             :                            sqri(Xinf), mkvecsmall(ell))), V2);
    2739        1162 :   return sturmseparate(myshallowconcat1(v), s, ell);
    2740             : }
    2741             : /**********************************************************************/
    2742             : /*                                 D9                                 */
    2743             : /**********************************************************************/
    2744             : /* disc = D^4 g^2 f^6 (quad. subfield: D, cubic subfield: D g^2) */
    2745             : static GEN
    2746          63 : makeD9(GEN N, GEN field, long s)
    2747             : {
    2748             :   GEN v, LD, D, D4;
    2749             :   long i, j, si;
    2750             : 
    2751          63 :   if ((s > 0 && s != 4) || !Z_issquare(N)) return NULL;
    2752          49 :   if (field)
    2753             :   {
    2754           7 :     D = checkfield(field, 2); D4 = powiu(D, 4);
    2755           7 :     si = signe(D);
    2756           7 :     if ((s > 0 && si > 0) || (s == 0 && si < 0) || !dvdii(N, D4)) return NULL;
    2757           7 :     LD = mkvec(field);
    2758             :   }
    2759             :   else
    2760             :   {
    2761          42 :     GEN t = divisorsdisc(cored(N, 4), s);
    2762          42 :     long l = lg(t);
    2763          42 :     LD = cgetg(l, t_VEC);
    2764         105 :     for (j = 1; j < l; j++) gel(LD, j) = quadpoly_i(gel(t, j));
    2765             :   }
    2766          49 :   v = cgetg(1, t_VEC);
    2767         119 :   for (i = 1; i < lg(LD); i++)
    2768             :   {
    2769          70 :     GEN bnf = bnfY(gel(LD, i)), Q, F, G;
    2770          70 :     G = mkvec2(galoisinit(bnf, NULL), gen_2);
    2771          70 :     D4 = powiu(bnf_get_disc(bnf), 4); Q = divii(N, D4);
    2772          70 :     F = divisors(cored(Q, 6));
    2773         182 :     for (j = 1; j < lg(F); j++)
    2774             :     {
    2775         112 :       GEN R = mybnrclassfield_X(bnf, gel(F,j), 9, NULL, NULL, G);
    2776             :       long k;
    2777         140 :       for (k = 1; k < lg(R); k++)
    2778             :       {
    2779          28 :         GEN pol = getpol(bnf, gel(R, k));
    2780          28 :         if (pol && (pol = ZX_red_disc(pol, N))) v = shallowconcat(v, pol);
    2781             :       }
    2782             :     }
    2783             :   }
    2784          49 :   return sturmseparate(v, s, 9);
    2785             : }
    2786             : 
    2787             : GEN
    2788        1533 : nflist_D9_worker(GEN P2, GEN X, GEN Xinf)
    2789             : {
    2790        1533 :   pari_sp av = avma;
    2791        1533 :   GEN v, bnf = bnfY(P2), D2 = bnf_get_disc(bnf);
    2792        1533 :   GEN G = mkvec2(galoisinit(bnf, NULL), gen_2);
    2793             :   long l, f, c;
    2794             : 
    2795        1533 :   l = floorsqrtndiv(X, powiu(D2, 4), 6) + 1;
    2796        1533 :   v = cgetg(l, t_VEC); c = 1;
    2797        4697 :   for (f = 1; f < l; f++)
    2798             :   {
    2799        3164 :     GEN R = mybnrclassfield_X(bnf, utoipos(f), 9, NULL, NULL, G);
    2800        3164 :     long k, ci, lR = lg(R);
    2801        3185 :     for (k = ci = 1; k < lR; k++)
    2802             :     {
    2803          21 :       GEN pol = getpol(bnf, gel(R, k));
    2804          21 :       if ((pol = ZX_red_disc2(pol, Xinf, X))) gel(R, ci++) = pol;
    2805             :     }
    2806        3164 :     if (ci > 1) { setlg(R, ci); gel(v, c++) = R; }
    2807             :   }
    2808        1533 :   setlg(v,c); return gerepilecopy(av, myshallowconcat1(v));
    2809             : }
    2810             : 
    2811             : static GEN
    2812          14 : makeD9resolvent(GEN G, long flag)
    2813             : {
    2814          14 :   GEN R = polredabs(galoisfixedfield(G, vecsplice(gal_get_gen(G), 2), 1, 0));
    2815          14 :   return condrel(R, gal_get_pol(G), flag);
    2816             : }
    2817             : 
    2818             : static GEN
    2819          49 : makeD9vec(GEN X, GEN Xinf, GEN field, long s)
    2820             : {
    2821             :   GEN X1pow, V2, v;
    2822             : 
    2823          49 :   checkfield_i(field,2); if (s > 0 && s != 4) return NULL;
    2824          28 :   if (s == 4) s = 1;
    2825          28 :   X1pow = sqrtnint(X, 4);
    2826          28 :   V2 = field? mkvec(field): makeC2vec(X1pow, gen_1, NULL, s == -2? -1: s);
    2827          28 :   if (!V2) return NULL;
    2828          28 :   v = gen_parapply(closure("_nflist_D9_worker", mkvec2(X, Xinf)), V2);
    2829          28 :   return sturmseparate(myshallowconcat1(v), s, 9);
    2830             : }
    2831             : /**********************************************************************/
    2832             : /* Metacyclic C_a \rtimes C_ell groups with ell prime and a | ell - 1 */
    2833             : /*                includes F5 = M20, M21, and M42                     */
    2834             : /**********************************************************************/
    2835             : /* C_a resolvent field. */
    2836             : static GEN nfmakenum(long n, long t, GEN N, GEN field, long s);
    2837             : static GEN nfmakevecnum(long n, long t, GEN X, GEN Xinf, GEN field, long s);
    2838             : 
    2839             : static GEN
    2840         462 : MgenF(long ell, GEN d, GEN Fn, long *vell)
    2841             : {
    2842             :   GEN F;
    2843         462 :   if (umodiu(d, ell)) *vell = 0;
    2844             :   else
    2845             :   {
    2846         182 :     *vell = Z_lval(Fn, ell) % (ell - 1);
    2847         182 :     if (*vell) Fn = diviiexact(Fn, powuu(ell, *vell));
    2848             :   }
    2849         462 :   return Z_ispowerall(Fn, ell - 1, &F)? F: NULL;
    2850             : }
    2851             : 
    2852             : static int
    2853        2870 : okgal(GEN P, GEN g)
    2854             : {
    2855        2870 :   GEN G = polgalois(P, DEFAULTPREC);
    2856        5236 :   return equaliu(gel(G,1), g[1]) && equalis(gel(G,2), g[2])
    2857        5236 :                                  && equaliu(gel(G,3), g[3]);
    2858             : }
    2859             : static int
    2860        2401 : okgal1(GEN P, long d)
    2861        2401 : { GEN G = polgalois(P, DEFAULTPREC); return equaliu(gel(G,1), d); }
    2862             : static int
    2863          21 : okgal2(GEN P, long d, long p)
    2864             : {
    2865          21 :   GEN G = polgalois(P, DEFAULTPREC);
    2866          21 :   return equaliu(gel(G,1), d) && equalis(gel(G,2), p);
    2867             : }
    2868             : static int
    2869         742 : ok_s(GEN P, long s) { return s < 0 || pol2s(P) == s; }
    2870             : 
    2871             : /* a | ell - 1, (Z/aZ)^* cyclic, F^(ell-1)*D^((ell-1)/a) */
    2872             : static GEN
    2873         126 : makeMgen(long ell, long a, GEN N, GEN field, long s)
    2874             : {
    2875             :   GEN v, Fn, F;
    2876         126 :   long i, lv, c, vell, deg = ell * a, drel = (ell - 1) / a;
    2877             : 
    2878         126 :   if (field)
    2879             :   {
    2880           7 :     GEN d = absi_shallow(checkfield(field, a));
    2881           7 :     Fn = gdiv(N, powiu(d, drel));
    2882           7 :     if (typ(Fn) != t_INT || !(F = MgenF(ell, d, Fn, &vell))) return NULL;
    2883           7 :     v = mkvec(mkvec3(mkvec(field), F, utoi(vell)));
    2884             :   }
    2885             :   else
    2886             :   {
    2887         119 :     long s2 = maxss(s, -1);
    2888         119 :     v = divisors(cored(N, drel)); lv = lg(v);
    2889         574 :     for (i = c = 1; i < lv; i++)
    2890             :     {
    2891         455 :       GEN R, d = gel(v, i); Fn = diviiexact(N, powiu(d, drel));
    2892         455 :       if ((F = MgenF(ell, d, Fn, &vell))
    2893         189 :            && (R = nfmakenum(a, 1, d, NULL, s2))) /* C_a, disc d */
    2894          49 :         gel(v, c++) = mkvec3(R, F, utoi(vell));
    2895             :     }
    2896         119 :     setlg(v, c);
    2897             :   }
    2898         126 :   lv = lg(v);
    2899         182 :   for (i = 1; i < lv; i++)
    2900             :   {
    2901          56 :     GEN T = gel(v, i), R = gel(T, 1), F0 = gel(T, 2);
    2902          56 :     long vell = itou(gel(T, 3)), lR = lg(R), j;
    2903          91 :     for (j = c = 1; j < lR; j++)
    2904             :     {
    2905          35 :       GEN nf = nfY(gel(R,j)), F = F0, K, G;
    2906             :       long k, ck, l;
    2907          35 :       if (vell)
    2908             :       { /* ell ramified in nf */
    2909             :         long eell, q;
    2910          21 :         GEN pell = getpell(nf, ell, &eell);
    2911          21 :         q = (ell - 1) / eell; if (vell % q) continue;
    2912          21 :         F = idealmul(nf, F, idealpows(nf, pell, vell / q));
    2913             :       }
    2914          35 :       G = mkvec2(galoisinit(nf, NULL), gen_2);
    2915          35 :       K = mybnrclassfield_X(Buchall(nf, nf_FORCE, DEFAULTPREC),
    2916             :                             F, ell, NULL, NULL, G);
    2917          35 :       l = lg(K);
    2918          63 :       for (k = ck = 1; k < l; k++)
    2919             :       {
    2920          28 :         GEN q = getpol(nf, gel(K, k));
    2921          56 :         if ((deg == 21 || okgal1(q, deg)) && /* automatic for M21;FIXME */
    2922          56 :             (q = ZX_red_disc(q, N))) gel(K, ck++) = q;
    2923             :       }
    2924          35 :       if (ck > 1) { setlg(K, ck); gel(R,c++) = K; }
    2925             :     }
    2926          56 :     setlg(R, c); gel(v, i) = myshallowconcat1(R);
    2927             :   }
    2928         126 :   return sturmseparate(gtoset_shallow(myshallowconcat1(v)), s, ell);
    2929             : }
    2930             : 
    2931             : /* (ell,a) = (5,4), (7,3) or (7,6) */
    2932             : static GEN
    2933          35 : makeMgenresolvent(long ell, long a, GEN pol, long flag)
    2934             : {
    2935          35 :   GEN Dpow = checkfield(pol, ell), G, R, DR, F2, nf, pell, F;
    2936             : 
    2937          35 :   G = galoissplittinginit(pol, utoipos(a*ell));
    2938          35 :   if (gal_get_order(G) != a * ell) pari_err_BUG("nfresolvent [Galois group]");
    2939          35 :   R = polredabs(galoisfixedfield(G, vecsplice(gal_get_gen(G), 2), 1, 0));
    2940          35 :   if (!flag) return R;
    2941          35 :   DR = nfdisc(R);
    2942          35 :   if (ell == 5 && a == 4)
    2943             :   {
    2944          14 :     F2 = sqrti(divii(Dpow, DR));
    2945          28 :     if (!Z_issquareall(F2, &F))
    2946             :     {
    2947             :       long e;
    2948          14 :       F2 = divis(F2, 5);
    2949          14 :       if (!Z_issquareall(F2, &F)) pari_err_BUG("nfresolvent [F5]");
    2950          14 :       nf = nfinit(R, DEFAULTPREC); pell = getpell(nf, 5, &e);
    2951          14 :       if (e == 4) pell = idealsqr(nf, pell);
    2952          14 :       F = idealmul(nf, F, pell);
    2953             :     }
    2954             :   }
    2955             :   else
    2956             :   { /* ell == 7 && (a == 3 || a == 6) */
    2957             :     long v;
    2958          21 :     if (a == 3) DR = sqri(DR);
    2959          21 :     if (!Z_issquareall(divii(Dpow, DR), &F2))
    2960           0 :       pari_err_BUG("nfresolvent [M21/M42]");
    2961             :     /* F2 = F^3 or 7F^3 or 7^2F^3 */
    2962          21 :     v = Z_lval(F2, 7) % 3;
    2963          21 :     if (v) F2 = divii(F2, powuu(7, v));
    2964          21 :     if (!Z_ispowerall(F2, 3, &F)) pari_err_BUG("nfresolvent [M21/M42]");
    2965          21 :     if (v)
    2966             :     {
    2967             :       long e;
    2968           7 :       nf = nfinit(R, DEFAULTPREC); pell = getpell(nf, 7, &e);
    2969           7 :       if (e == 6) v *= 2;
    2970           7 :       F = idealmul(nf, F, idealpows(nf, pell, v));
    2971             :     }
    2972             :   }
    2973          35 :   return mkvec2(R, F);
    2974             : }
    2975             : 
    2976             : GEN
    2977        2803 : nflist_Mgen_worker(GEN field, GEN X, GEN Xinf, GEN T)
    2978             : {
    2979        2803 :   pari_sp av = avma;
    2980        2803 :   GEN v, Fn, pell, lpow, bnf = bnfY(field), D = bnf_get_disc(bnf);
    2981        2807 :   GEN G = mkvec2(galoisinit(bnf, NULL), gen_2);
    2982        2807 :   long ell = T[1], drel = T[2], deg = T[3], c, e;
    2983        2807 :   long vd = Z_lval(D, ell), limf, f;
    2984             : 
    2985        2807 :   Fn = divii(X, drel == 1 ? absi_shallow(D) : sqri(D));
    2986        2807 :   limf = floorsqrtn(Fn, ell - 1);
    2987        2807 :   pell = getpell(bnf, ell, &e); /* e | a */
    2988        2807 :   lpow = powuu(ell, (ell - 1) / e);
    2989        2807 :   v = cgetg(limf + 1, t_VEC);
    2990        6902 :   for (f = c = 1; f <= limf; f++)
    2991             :   {
    2992        4095 :     GEN F = utoipos(f), K;
    2993             :     long k, ci, lK;
    2994             : 
    2995        4095 :     if (vd)
    2996             :     {
    2997        2135 :       GEN fn = powuu(f, ell - 1);
    2998        2135 :       long imax = minss(e - 1, logint(divii(Fn, fn), lpow));
    2999        2135 :       F = mkcol2(F, gmulgu(idealpows(bnf, pell, imax), f));
    3000             :     }
    3001        4095 :     K = mybnrclassfield_X(bnf, F, ell, NULL, NULL, G); lK = lg(K);
    3002        4326 :     for (k = ci = 1; k < lK; k++)
    3003             :     {
    3004         231 :       GEN q = getpol(bnf, gel(K, k));
    3005         462 :       if (degpol(q) == ell && (deg == 21 || okgal1(q, deg)) && /* FIXME */
    3006         462 :           (q = ZX_red_disc2(q, Xinf, X))) gel(K, ci++) = q;
    3007             :     }
    3008        4095 :     if (ci > 1) { setlg(K, ci); gel(v, c++) = K; }
    3009             :   }
    3010        2807 :   setlg(v, c); v = gtoset_shallow(myshallowconcat1(v));
    3011        2807 :   return gerepilecopy(av, v);
    3012             : }
    3013             : 
    3014             : /* (a,ell) = (3,7), (4,5) or (6,7) */
    3015             : static GEN
    3016         140 : makeMgenvec(long ell, long a, GEN X, GEN Xinf, GEN field, long s)
    3017             : {
    3018             :   GEN L, v, T;
    3019         140 :   long drel = (ell - 1) / a;
    3020             : 
    3021         140 :   if (field)
    3022             :   {
    3023          14 :     if (degpol(field) != a || !okgal2(field, a, a==3? 1: -1))
    3024           7 :       pari_err_TYPE("makeMgenvec [field]", field);
    3025           7 :     L = mkvec(field);
    3026             :   }
    3027         126 :   else L = nfmakevecnum(a, 1, drel == 1? X: sqrti(X), gen_1, NULL, maxss(s,-1));
    3028         133 :   if (!L) return NULL;
    3029          91 :   T = mkvecsmall3(ell, drel, ell * a);
    3030          91 :   v = gen_parapply(closure("_nflist_Mgen_worker", mkvec3(X, Xinf, T)), L);
    3031          91 :   return sturmseparate(myshallowconcat1(v), s, ell);
    3032             : }
    3033             : 
    3034             : /**********************************************************************/
    3035             : /*                        A5 by table lookup                          */
    3036             : /**********************************************************************/
    3037             : /* V a vector of [T, n] sorted wrt t_INT n. Return elts with Xinf <= n <= X.
    3038             :  * If flag = 0 return only the T's. */
    3039             : static GEN
    3040         273 : vecslicebyX(GEN V, GEN Xinf, GEN X, long flag)
    3041             : {
    3042         273 :   long l = lg(V), i = 1, c;
    3043             :   GEN W;
    3044             : 
    3045         273 :   if (l == 1) return NULL;
    3046         273 :   if (typ(gmael(V,1,1)) == t_POL)
    3047           0 :     pari_err(e_MISC,"Versions mismatch. Please update the nflistdata package");
    3048         273 :   if (!equali1(Xinf)) /* frequent special case */
    3049             :   {
    3050         182 :     i = gen_search(V, mkvec2(NULL,Xinf), NULL, &cmp2);
    3051         182 :     if (i > 0) /* found in list, rewind to first occurence */
    3052          35 :     { while (i > 1 && equalii(gmael(V, i-1, 2), Xinf)) i--; }
    3053             :     else /* not in list */
    3054         147 :     { i = -i; if (i >= lg(V)) return NULL; }
    3055             :   }
    3056         273 :   W = cgetg(l, t_VEC);
    3057         273 :   if (flag)
    3058         350 :     for (c = 1; i < l && cmpii(gmael(V, i, 2), X) <= 0; i++)
    3059             :     {
    3060         280 :       GEN x = gmael(V, i, 1);
    3061         280 :       gel(W, c++) = mkvec2(RgV_to_RgX(x,0), gmael(V, i, 2));
    3062             :     }
    3063             :   else
    3064        4683 :     for (c = 1; i < l && cmpii(gmael(V, i, 2), X) <= 0; i++)
    3065             :     {
    3066        4480 :       GEN x = gmael(V, i, 1);
    3067        4480 :       gel(W, c++) = RgV_to_RgX(x,0);
    3068             :     }
    3069         273 :   setlg(W, c); return W;
    3070             : }
    3071             : 
    3072             : /* assume 1 <= t < 1000, 1 <= 2s <= n < 100 */
    3073             : static GEN
    3074         266 : nflistfile(const char *suf, long n, long t, long s)
    3075             : {
    3076             :   pariFILE *F;
    3077             :   GEN z;
    3078         266 :   char *f = stack_sprintf("%s/nflistdata/%ld/%ld/%ld%s.gp", pari_datadir, n, t,s, suf?suf:"");
    3079         266 :   F = pari_fopengz(f);
    3080         266 :   if (!F) pari_err_FILE("nflistdata file",f);
    3081         266 :   z = gp_readvec_stream(F->file); pari_fclose(F); return z;
    3082             : }
    3083             : 
    3084             : static GEN
    3085         266 : A5file(const char *suf, long s) { return nflistfile(suf, 5, 4, s); }
    3086             : static GEN
    3087         154 : A5vec(GEN X, GEN Xinf, long s, long fl)
    3088             : {
    3089             :   GEN L1, L5;
    3090         154 :   const char *suf = fl? "cond": "";
    3091             : 
    3092         154 :   if (!fl)
    3093             :   {
    3094         112 :     GEN bnd = s==0 ? shifti(powuu(10,11),1): powuu(10,8);
    3095         112 :     if (cmpii(X, bnd) > 0) pari_err_DOMAIN("nflist(A5)", "N", ">", bnd, X);
    3096             :   }
    3097         154 :   L1 = L5 = NULL;
    3098         154 :   if (s <= 0) L5 = vecslicebyX(A5file(suf, 0), Xinf, X, fl);
    3099         154 :   if (s) L1 = vecslicebyX(A5file(suf, 2), Xinf, X, fl);
    3100         154 :   switch (s)
    3101             :   {
    3102          28 :     case 2: return L1;
    3103          21 :     case 0: return L5;
    3104          91 :     case -1:
    3105          91 :       if (!L1) return L5;
    3106          91 :       if (!L5) return L1;
    3107          91 :       return shallowconcat(L1, L5);
    3108          14 :     default:
    3109          14 :       if (!L1 && !L5) return NULL;
    3110          14 :       if (!L1) L1 = cgetg(1, t_VEC);
    3111          14 :       if (!L5) L5 = cgetg(1, t_VEC);
    3112          14 :       return mkvec3(L5, cgetg(1, t_VEC), L1);
    3113             :   }
    3114             : }
    3115             : static GEN
    3116          21 : makeA5_i(GEN N, long s, long fl)
    3117          21 : { return (s == 1 || (!fl && !Z_issquare(N)))? NULL: A5vec(N, N, s, fl); }
    3118             : static GEN
    3119          14 : makeA5(GEN N, long s) { return makeA5_i(N, s, 0); }
    3120             : static GEN
    3121           7 : makeA5cond(GEN N, long s) { return makeA5_i(N, s, 1); }
    3122             : 
    3123             : /* D a sorted t_VECSMALL of conductors; return all [T, d] with d = D[i]
    3124             :  * for some i and Gal(T) = A5 with s complex places */
    3125             : GEN
    3126           0 : veccond_to_A5(GEN D, long s)
    3127             : {
    3128           0 :   GEN W, V = A5file("cond", s);
    3129           0 :   long l = lg(V), i, j, lD = lg(D), c = 1;
    3130           0 :   W = cgetg(lD, t_VEC);
    3131           0 :   for (i = 1, j = 1; i < l; i++)
    3132             :   {
    3133           0 :     long e = itou(gmael(V,i,2));
    3134           0 :     if (e < D[j]) continue;
    3135           0 :     while (j < lD && e > D[j]) j++;
    3136           0 :     if (j==lD) break;
    3137           0 :     if (e == D[j])
    3138             :     {
    3139           0 :       GEN x = gmael(V, i, 1);
    3140           0 :       gel(W, c++) = mkvec2(RgV_to_RgX(x,0), gmael(V, i, 2));
    3141             :     }
    3142             :   }
    3143           0 :   setlg(W, c); return W;
    3144             : }
    3145             : 
    3146             : /* Sextic resolvent of A5 field */
    3147             : static GEN
    3148        4221 : makeA5resolvent(GEN pol, long flag)
    3149             : {
    3150        4221 :   GEN R = cgetg(9, t_POL), D = ZX_disc(pol), c, d, e, f, v;
    3151             :   GEN c2, d2, e2, c4, df;
    3152        4221 :   pol = RgX_translate(pol, gdivgs(gel(pol, 6), -5));
    3153        4221 :   c = gdivgu(gel(pol, 5), 10);
    3154        4221 :   d = gdivgu(gel(pol, 4), 10);
    3155        4221 :   e = gdivgu(gel(pol, 3), 5);
    3156        4221 :   f = gel(pol, 2);
    3157        4221 :   c2 = gsqr(c); c4 = gsqr(c2); d2 = gsqr(d); e2 = gsqr(e);
    3158        4221 :   df = gmul(d, f);
    3159        4221 :   R[1] = evalsigne(1)|evalvarn(0);
    3160        4221 :   gel(R, 8) = gen_1;
    3161        4221 :   gel(R, 7) = gen_0;
    3162        4221 :   gel(R, 6) = gmulsg(-25, gadd(e, gmulsg(3, c2)));
    3163        4221 :   gel(R, 5) = gen_0;
    3164             : 
    3165        4221 :   v = cgetg(6, t_VEC);
    3166        4221 :   gel(v, 1) = gmulsg(15, c4);
    3167        4221 :   gel(v, 2) = gmulsg(8, gmul(c, d2));
    3168        4221 :   gel(v, 3) = gmulsg(-2, gmul(c2, e));
    3169        4221 :   gel(v, 4) = gmulsg(3, e2);
    3170        4221 :   gel(v, 5) = gmulsg(-2, df);
    3171        4221 :   gel(R, 4) = gmulsg(125, vecsum(v));
    3172        4221 :   gel(R, 3) = sqrti(D);
    3173             : 
    3174        4221 :   v = cgetg(11, t_VEC);
    3175        4221 :   gel(v, 1) = gmulsg(-25, gmul(c2, c4));
    3176        4221 :   gel(v, 2) = gmulsg(-40, gmul(gmul(c, c2), d2));
    3177        4221 :   gel(v, 3) = gmulsg(-16, gsqr(d2));
    3178        4221 :   gel(v, 4) = gmulsg(35, gmul(c4, e));
    3179        4221 :   gel(v, 5) = gmulsg(28, gmul(c, gmul(d2, e)));
    3180        4221 :   gel(v, 6) = gmulsg(-11, gsqr(gmul(c, e)));
    3181        4221 :   gel(v, 7) = gmul(e, e2);
    3182        4221 :   gel(v, 8) = gmulsg(-2, gmul(c2, df));
    3183        4221 :   gel(v, 9) = gmulsg(-2, gmul(e, df));
    3184        4221 :   gel(v, 10) = gmul(c, gsqr(f));
    3185        4221 :   gel(R, 2) = gmulsg(625, vecsum(v));
    3186        4221 :   R = polredabs(R);
    3187        4221 :   return odd(flag)? mkvec2(R, gen_1): R;
    3188             : }
    3189             : 
    3190             : /* For now field ignored. */
    3191             : static GEN
    3192         133 : makeA5vec_i(GEN X, GEN Xinf, GEN field, long s, long fl)
    3193             : {
    3194         133 :   (void)field; if (s == 1) return NULL;
    3195         133 :   return A5vec(X, Xinf, s, fl);
    3196             : }
    3197             : 
    3198             : static GEN
    3199          98 : makeA5vec(GEN X, GEN Xinf, GEN field, long s)
    3200          98 : { return makeA5vec_i(X, Xinf, field, s, 0); }
    3201             : 
    3202             : static GEN
    3203          35 : makeA5condvec(GEN X, GEN Xinf, GEN field, long s)
    3204          35 : { return makeA5vec_i(X, Xinf, field, s, 1); }
    3205             : 
    3206             : static GEN
    3207          63 : makeA56vec_i(GEN V, GEN X, GEN Xinf)
    3208             : {
    3209          63 :   long l = lg(V), i, c;
    3210          63 :   GEN W = cgetg(l, t_VEC);
    3211        4263 :   for (i = c = 1; i < l; i++)
    3212             :   {
    3213        4200 :     GEN pol = makeA5resolvent(gel(V, i), 0), D = nfdisc(pol);
    3214        4200 :     if (cmpii(D, X) <= 0 && cmpii(D, Xinf) >= 0) gel(W, c++) = pol;
    3215             :   }
    3216          63 :   setlg(W, c); return W;
    3217             : }
    3218             : 
    3219             : static GEN
    3220          56 : makeA56vec(GEN X, GEN Xinf, long s)
    3221             : {
    3222             :   GEN v;
    3223          56 :   if (s == 1 || s == 3 || !(v = makeA5vec(X, Xinf, NULL, s))) return NULL;
    3224          56 :   if (s != -2) return makeA56vec_i(v, X, Xinf);
    3225           7 :   return mkvec3(makeA56vec_i(gel(v, 1), X, Xinf), cgetg(1, t_VEC),
    3226           7 :                 makeA56vec_i(gel(v, 3), X, Xinf));
    3227             : }
    3228             : static GEN
    3229           7 : makeA56(GEN N, long s) { return makeA56vec(N, N, s); }
    3230             : 
    3231             : /* Stupid for now */
    3232             : static GEN
    3233           7 : makeA56resolvent(GEN pol, long flag)
    3234             : {
    3235           7 :   GEN V, D6 = sqrti(nfdisc(pol)), LD = divisors(D6);
    3236             :   long i;
    3237           7 :   pol = polredabs(pol);
    3238           7 :   V = A5file("", pol2s(pol)? 2: 0);
    3239          56 :   for (i = 1; i < lg(LD); i++)
    3240             :   {
    3241          56 :     GEN D52 = sqri(gel(LD,i));
    3242          56 :     if (dvdii(D52, D6))
    3243             :     {
    3244          14 :       GEN L = vecslicebyX(V, D52, D52, 0);
    3245             :       long j;
    3246          21 :       for (j = 1; j < lg(L); j++)
    3247             :       {
    3248          14 :         GEN P = gel(L, j);
    3249          14 :         if (ZX_equal(makeA5resolvent(P, 0), pol))
    3250           7 :           return odd(flag)? mkvec2(P, gen_1): P;
    3251             :       }
    3252             :     }
    3253             :   }
    3254           0 :   pari_err_BUG("nfresolvent [A56 resolvent not found]");
    3255             :   return NULL; /* LCOV_EXCL_LINE */
    3256             : }
    3257             : 
    3258             : /**********************************************************************/
    3259             : /*                                 C6                                 */
    3260             : /**********************************************************************/
    3261             : 
    3262             : static GEN
    3263        8518 : makepol6(GEN P3, GEN P2) { return polcompositum0(P3, P2, 2); }
    3264             : static GEN
    3265          28 : makepol6abs(GEN P3, GEN P2) { return polredabs(makepol6(P3, P2)); }
    3266             : 
    3267             : static GEN
    3268          98 : makeC6(GEN N, GEN field, long s)
    3269             : {
    3270          98 :   GEN R, D, d3 = NULL;
    3271             :   long i, j, lD, s2, c;
    3272             : 
    3273          98 :   if (s == 1 || s == 2) return NULL;
    3274          70 :   if (!field) D = divisorsdisc(cored(N, 3), s);
    3275             :   else
    3276             :   {
    3277          14 :     if (degpol(field) == 2)
    3278             :     {
    3279           7 :       GEN D2 = nfdisc(field);
    3280           7 :       long si = signe(D2);
    3281           7 :       if ((s == 3 && si > 0) || (s == 0 && si < 0)
    3282           7 :           || !divissquare(N, powiu(D2,3))) return NULL;
    3283           7 :       D = mkvec(D2);
    3284             :     }
    3285             :     else
    3286             :     {
    3287           7 :       GEN q, D3 = checkfield(field, 3);
    3288           7 :       if (!Z_issquareall(D3, &d3)) pari_err_TYPE("makeC6 [field]", field);
    3289           7 :       if (!(q = divide(N, sqri(D3)))) return NULL;
    3290           7 :       D = divisorsdisc(cored(gcdii(N, powiu(q,3)), 3), s);
    3291             :     }
    3292             :   }
    3293          70 :   s2 = maxss(s, -1); if (s2 == 3) s2 = 1;
    3294          70 :   lD = lg(D); R = cgetg(lD, t_VEC);
    3295         154 :   for (i = c = 1; i < lD; i++)
    3296             :   {
    3297          84 :     GEN R0, D2 = gel(D, i), D2a = absi_shallow(D2);
    3298          84 :     GEN M = diviiexact(N, powiu(D2a, 3)), F, L, V2;
    3299             :     long l, l2;
    3300          84 :     if (!Z_issquareall(M, &F)) continue;
    3301          42 :     if (d3) { L = mkvec(mkvec(field)); l = 2; }
    3302             :     else
    3303             :     {
    3304             :       long k;
    3305          28 :       L = divisors(cored(mulii(F, D2a), 2)); l = lg(L);
    3306         126 :       for (j = k = 1; j < l; j ++)
    3307             :       {
    3308          98 :         GEN C = makeC3_f(gel(L, j));
    3309          98 :         if (lg(C) > 1) gel(L, k++) = C;
    3310             :       }
    3311          28 :       setlg(L, k); l = k; if (l == 1) continue;
    3312             :     }
    3313          42 :     V2 = makeC2(D2a, NULL, s2); l2 = lg(V2);
    3314          42 :     R0 = cgetg(l, t_VEC);
    3315          84 :     for (j = 1; j < l; j++)
    3316             :     {
    3317          42 :       GEN R3, C3 = gel(L, j);
    3318          42 :       long i2, c3, i3, l3 = lg(C3);
    3319             : 
    3320          42 :       R3 = cgetg(l2 * l3, t_VEC);
    3321          84 :       for (i3 = c3 = 1; i3 < l3; i3++)
    3322             :       {
    3323          42 :         GEN P3 = gel(C3, i3);
    3324         119 :         for (i2 = 1; i2 < l2; i2++)
    3325             :         {
    3326          77 :           GEN P6 = makepol6(P3, gel(V2, i2));
    3327          77 :           if (absequalii(nfdisc(P6), N)) gel(R3, c3++) = P6;
    3328             :         }
    3329             :       }
    3330          42 :       setlg(R3, c3); gel(R0, j) = R3;
    3331             :     }
    3332          42 :     gel(R, c++) = shallowconcat1(R0);
    3333             :   }
    3334          70 :   setlg(R,c); return sturmseparate(myshallowconcat1(R), s, 6);
    3335             : }
    3336             : 
    3337             : static GEN
    3338          28 : makeC6resolvent(GEN pol, long flag)
    3339             : {
    3340          28 :   GEN V, R3, R = mynfsubfield(pol, 2);
    3341          28 :   R3 = (flag >= 2)? mynfsubfield(pol, 3): NULL;
    3342          28 :   switch (flag)
    3343             :   {
    3344           7 :     case 0: V = R; break;
    3345           7 :     case 1: V = condrel_i(R, pol); break;
    3346           7 :     case 2: V = mkvec2(R, R3); break;
    3347           7 :     default:V = mkvec2(condrel_i(R, pol), condrel_i(R3, pol)); break;
    3348             :   }
    3349          28 :   return V;
    3350             : }
    3351             : 
    3352             : /* assume the odd part of M is squarefree, disc is OK */
    3353             : static void
    3354        8696 : C6fill(long M, GEN P3, long s, GEN vp,GEN vm)
    3355             : {
    3356             :   int p, m;
    3357        8696 :   uis_fundamental_pm_i(M, s, &p, &m, 1);
    3358        8696 :   if (p) vectrunc_append(vp, makepol6(P3, X2p(utoineg(M))));
    3359        8699 :   if (m) vectrunc_append(vm, makepol6(P3, X2p(utoipos(M))));
    3360        8699 : }
    3361             : 
    3362             : GEN
    3363         867 : nflist_C6_worker(GEN P3, GEN X, GEN Xinf, GEN M, GEN T)
    3364             : {
    3365         867 :   pari_sp av = avma;
    3366             :   GEN D3, f, D32, vp, vm, G, Ginf;
    3367         867 :   long i, limD2, l = lg(M), s = T[1];
    3368             : 
    3369         867 :   if (typ(P3)==t_VEC) { f = gel(P3,2); P3 = gel(P3,1);  } else f = C3pol_f(P3);
    3370         868 :   D3 = sqri(f); D32 = sqri(D3); G = divii(X, D32); Ginf = ceildiv(Xinf, D32);
    3371         868 :   limD2 = cmpiu(G, T[2]) < 0 ? itou(G) : T[2];
    3372             : 
    3373             :   /* D3 = f^2 is odd, gcd(M,D3) = gcd(M,f); disc = D3^2 / (D3,M)^2 * M^3 */
    3374         868 :   vp = vectrunc_init(limD2);
    3375         868 :   vm = vectrunc_init(limD2);
    3376      247954 :   for (i = 1; i < l; i++)
    3377             :   {
    3378      247756 :     long m = M[i];
    3379             :     GEN g;
    3380      247756 :     if (!odd(m)) continue;
    3381      165096 :     if (m > limD2) break;
    3382      164426 :     g = muliu(sqru(m / ugcdiu(f, m)), m);
    3383      164605 :     if (m != 1 && ok_int(g, G, Ginf)) C6fill(m, P3, s, vp, vm);
    3384      164510 :     if ((m << 2) <= limD2 && ok_int(shifti(g,6), G, Ginf))
    3385        1701 :       C6fill(m << 2, P3, s, vp, vm);
    3386      164523 :     if ((m << 3) <= limD2 && ok_int(shifti(g,9), G, Ginf))
    3387         742 :       C6fill(m << 3, P3, s, vp, vm);
    3388             :   }
    3389         868 :   return gerepilecopy(av, mkvec2(vp, vm));
    3390             : }
    3391             : 
    3392             : static GEN
    3393          91 : makeC6vec(GEN X, GEN Xinf, GEN field, long s)
    3394             : {
    3395             :   GEN T, v, M;
    3396             : 
    3397          91 :   if (s == 1 || s == 2) return NULL;
    3398          63 :   if (field)
    3399             :   {
    3400             :     GEN D, f;
    3401          21 :     if (degpol(field) == 2)
    3402             :     {
    3403             :       long si, m, i, c, l;
    3404             :       GEN F;
    3405          14 :       D = nfdisc(field); si = signe(D);
    3406          14 :       if (cmpii(powiu(D, 3), X) > 0 || (s == 3 && si > 0)
    3407          14 :           || (s == 0 && si < 0)) return NULL;
    3408          14 :       m = itou(D); v = C3vec_F(floorsqrtdiv(X,D), 1, &F); l = lg(v);
    3409       78358 :       for (i = c = 1; i < l; i++)
    3410             :       {
    3411       78344 :         long f = F[i]; /* conductor */
    3412       78344 :         GEN g = muliu(sqru(m / ugcd(f, m)), m);
    3413       78344 :         if (ok_int(mulii(powuu(f, 4), g), X, Xinf))
    3414         140 :           gel(v, c++) = makepol6(gtopoly(gel(v,i), 0), field);
    3415             :       }
    3416          14 :       setlg(v, c);
    3417          14 :       if (s == -2) v = si > 0? vecs14(v, cgetg(1,t_VEC)): vecs(4, v);
    3418          14 :       return v;
    3419             :     }
    3420           7 :     D = checkfield(field, 3);
    3421           7 :     if (!Z_issquareall(D, &f)) pari_err_TYPE("makeC6 [field]", field);
    3422           7 :     if (cmpii(sqri(D), X) > 0) return NULL;
    3423           7 :     v = mkvec(mkvec2(field, f));
    3424             :   }
    3425          42 :   else if (!(v = makeC3vec(sqrti(divis(X, 3)), gen_1, NULL, 0))) return NULL;
    3426          49 :   T = mkvecsmall2(s, floorsqrtn(X, 3));
    3427          49 :   M = vecsquarefreeu(1, T[2]);
    3428          49 :   v = gen_parapply(closure("_nflist_C6_worker", mkvec4(X, Xinf, M, T)), v);
    3429          49 :   switch (s)
    3430             :   {
    3431          14 :     case -1: return shallowconcat(Sextract(v,1), Sextract(v,2));
    3432           7 :     case -2: return vecs14(Sextract(v,1), Sextract(v,2)); /* -2 */
    3433          28 :     default: return Sextract(v, s? 2: 1);
    3434             :   }
    3435             : }
    3436             : 
    3437             : /**********************************************************************/
    3438             : /*                             S36 = D66                              */
    3439             : /**********************************************************************/
    3440             : static GEN
    3441          63 : makeS36(GEN N, GEN field, long s)
    3442             : {
    3443             :   GEN vD, P, vp, vm;
    3444             :   long i, l, cp, cm;
    3445          63 :   if (s == 1 || s == 2) return NULL;
    3446          49 :   if (s == 3) s = 1;
    3447          49 :   if (field)
    3448             :   {
    3449          21 :     long sf = s != -1? pol2s(field): 0/*dummy*/;
    3450          21 :     if (s >= 0 && s != sf) return NULL;
    3451          21 :     if (degpol(field) == 3)
    3452             :     {
    3453           7 :       GEN d, D = nfcoredisc(field, &d);
    3454           7 :       if (!absequalii(mulii(sqri(D), d), N)) return NULL;
    3455           7 :       P = mkvec(makepol6abs(field, X2m(d)));
    3456           7 :       if (s == -2) { P = vecs(4, P); if (sf) swap(gel(P,1), gel(P,4)); }
    3457           7 :       return P;
    3458             :     }
    3459             :     else
    3460             :     {
    3461          14 :       GEN D2 = checkfield(field, 2);
    3462          14 :       if (!divispowerall(N,  powiu(absi_shallow(D2),3), 4, NULL)) return NULL;
    3463          14 :       vD = mkvec(D2);
    3464             :     }
    3465             :   }
    3466          28 :   else vD = divisorsdisc(cored(N, 3), s);
    3467          42 :   l = lg(vD);
    3468          42 :   vp = cgetg(l, t_VEC);
    3469          42 :   vm = cgetg(l, t_VEC);
    3470          77 :   for (i = cp = cm = 1; i < l; i++)
    3471             :   {
    3472          35 :     GEN F, w, P2, D = gel(vD, i), Da = absi_shallow(D);
    3473          35 :     long lw, j, s2 = signe(D) > 0? 0: 1;
    3474          35 :     if (!Z_ispowerall(divii(N, powiu(Da, 3)), 4, &F)) continue;
    3475          21 :     P2 = X2m(D); if (!(w = makeDL(3, mulii(Da, sqri(F)), P2, s2))) continue;
    3476          21 :     lw = lg(w);
    3477          42 :     for (j = 1; j < lw; j++) gel(w, j) = makepol6abs(gel(w, j), P2);
    3478          21 :     if (signe(D) < 0) gel(vm, cm++) = w; else gel(vp, cp++) = w;
    3479             :   }
    3480          42 :   setlg(vp, cp); vp = myshallowconcat1(vp);
    3481          42 :   setlg(vm, cm); vm = myshallowconcat1(vm);
    3482          42 :   return s == -2? vecs14(vp, vm): shallowconcat(vp, vm);
    3483             : }
    3484             : 
    3485             : static GEN
    3486          21 : makeS36resolvent(GEN pol, long flag)
    3487             : {
    3488          21 :   GEN R2, V, S = mynfsubfields(pol, 3);
    3489          21 :   if (flag < 2) return condrel(gel(S,1), pol, flag);
    3490          14 :   R2 = mynfsubfield(pol, 2);
    3491          14 :   if (flag == 2)
    3492           7 :     V = vec_append(S, R2);
    3493             :   else
    3494          14 :     V = mkvec4(condrel_i(gel(S,1), pol), condrel_i(gel(S,2), pol),
    3495           7 :                condrel_i(gel(S,3), pol), condrel_i(R2, pol));
    3496          14 :   return V;
    3497             : }
    3498             : 
    3499             : GEN
    3500       14699 : nflist_S36_worker(GEN pol, GEN X, GEN Xinf)
    3501             : {
    3502       14699 :   GEN d, D = nfcoredisc(pol, &d);
    3503       14699 :   if (ok_int(mulii(sqri(D), d), X, Xinf)) return makepol6(pol, X2m(d));
    3504       13160 :   return gen_0;
    3505             : }
    3506             : 
    3507             : static GEN
    3508          35 : parselectS36(GEN v, GEN X, GEN Xinf)
    3509             : {
    3510          35 :   GEN w = gen_parapply(closure("_nflist_S36_worker", mkvec2(X, Xinf)), v);
    3511          35 :   long l = lg(w), i, c;
    3512             : 
    3513       14770 :   for (i = c = 1; i < l; i++)
    3514             :   {
    3515       14735 :     GEN t = gel(w, i);
    3516       14735 :     if (typ(t) == t_POL) gel(w, c++) = t;
    3517             :   }
    3518          35 :   setlg(w, c); return w;
    3519             : }
    3520             : 
    3521             : static GEN
    3522          49 : makeS36vec(GEN X, GEN Xinf, GEN field, long s)
    3523             : {
    3524             :   GEN v;
    3525             : 
    3526          49 :   if (s == 1 || s == 2) return NULL;
    3527          35 :   if (s == 3) s = 1;
    3528          35 :   if (field)
    3529             :   {
    3530          14 :     if (degpol(field) == 3)
    3531             :     {
    3532           7 :       GEN d, D = nfcoredisc(field,&d);
    3533           7 :       long ss = signe(D) < 0? 1: 0;
    3534           7 :       if (s >= 0 && s != ss) return NULL;
    3535           7 :       if (abscmpii(mulii(sqri(D), d), X) > 0) return NULL;
    3536           7 :       v = mkvec(field);
    3537             :     }
    3538             :     else
    3539             :     {
    3540           7 :       GEN D2a = absi_shallow(checkfield(field, 2)), D2a3 = powiu(D2a, 3), RES;
    3541             :       long Fsup, Finf, F, c;
    3542           7 :       if ((s >= 0 && s != pol2s(field)) || cmpii(D2a3, X) > 0) return NULL;
    3543           7 :       Fsup = floorsqrtndiv(X, D2a3, 4);
    3544           7 :       Finf = ceilsqrtndiv(Xinf, D2a3, 4);
    3545           7 :       RES = cgetg(Fsup + 1, t_VEC);
    3546          14 :       for (F = Finf, c = 1; F <= Fsup; F++)
    3547             :       {
    3548           7 :         pari_sp av = avma;
    3549           7 :         GEN w, N = mulii(powuu(F, 4), D2a3);
    3550           7 :         if (!(w = makeS36(N, field, s))) set_avma(av);
    3551           7 :         else gel(RES, c++) = gerepilecopy(av, w);
    3552             :       }
    3553           7 :       setlg(RES,c); return myshallowconcat1(RES);
    3554             :     }
    3555             :   }
    3556             :   else
    3557          21 :     if (!(v = makeS3vec(sqrti(divis(X, 3)), gen_1, NULL, s))) return NULL;
    3558          28 :   if (s != -2) return parselectS36(v, X, Xinf);
    3559           7 :   return mkvec4(parselectS36(gel(v,1), X, Xinf), cgetg(1, t_VEC),
    3560           7 :                 cgetg(1, t_VEC), parselectS36(gel(v,2), X, Xinf));
    3561             : }
    3562             : /**********************************************************************/
    3563             : /*                              D612                                  */
    3564             : /**********************************************************************/
    3565             : static void
    3566          91 : gets2s3(long s, long *s2, long *s3)
    3567             : {
    3568          91 :   switch (s)
    3569             :   {
    3570          14 :     case 0: *s2 = *s3 = 0; break;
    3571          14 :     case 2: *s2 = 0; *s3 = 1; break;
    3572           7 :     case 3: *s2 = 1; *s3 = -1; break;
    3573          56 :     default: *s2 = *s3 = -1; break;
    3574             :   }
    3575          91 : }
    3576             : 
    3577             : static GEN makeD612vec(GEN X, GEN Xinf, GEN field, long s);
    3578             : static GEN
    3579          56 : makeD612(GEN N, GEN field, long s)
    3580             : {
    3581             :   long i, j, l, c3, s2, s3;
    3582             :   GEN v;
    3583             : 
    3584          56 :   if (s == 1) return NULL;
    3585          49 :   gets2s3(s, &s2, &s3);
    3586          49 :   if (field)
    3587             :   {
    3588             :     GEN D2;
    3589             :     long si;
    3590           7 :     if (degpol(field) == 3) return makeD612vec(N,N,field,s);
    3591           7 :     D2 = checkfield(field, 2); si = signe(D2);
    3592           7 :     if ((si == 1 && s2 > 0) || (si == -1 && !s2)
    3593           7 :         || !divissquare(N, powiu(D2,3))) return NULL;
    3594           7 :     v = mkvec(D2);
    3595             :   }
    3596          42 :   else v = divisorsdisc(cored(N, 3), s2);
    3597          49 :   l = lg(v);
    3598          84 :   for (i = c3 = 1; i < l; i++)
    3599             :   {
    3600          35 :     GEN D2 = gel(v, i), D2a = absi_shallow(D2), M = divii(N, powiu(D2a, 3));
    3601          35 :     GEN P2, F = gel(core2(M), 2), L = divisors(mulii(F, D2a));
    3602          35 :     long c2, lL = lg(L);
    3603          35 :     if (lL == 1) continue;
    3604          35 :     P2 = quadpoly_i(D2);
    3605         343 :     for (j = c2 = 1; j < lL; j++)
    3606             :     {
    3607         308 :       GEN w, D3 = gel(L, j);
    3608             :       long k, c, lw;
    3609         308 :       if (Mod4(D3) == 2 || !dvdii(F, divii(D3, gcdii(D2a, D3)))
    3610         308 :           || !(w = makeDL(3, D3, NULL, s3))) continue;
    3611          21 :       lw = lg(w);
    3612          42 :       for (k = c = 1; k < lw; k++)
    3613             :       {
    3614          21 :         GEN P3 = gel(w, k), P6, d;
    3615          21 :         (void)nfcoredisc(P3, &d); if (equalii(d, D2)) continue;
    3616          21 :         if ((P6 = ZX_red_disc(makepol6(P3, P2), N))) gel(w, c++) = P6;
    3617             :       }
    3618          21 :       if (c > 1) { setlg(w, c); gel(L, c2++) = w; }
    3619             :     }
    3620          35 :     if (c2 > 1) { setlg(L, c2); gel(v, c3++) = shallowconcat1(L); }
    3621             :   }
    3622          49 :   setlg(v, c3); return sturmseparate(myshallowconcat1(v), s, 6);
    3623             : }
    3624             : 
    3625             : static GEN
    3626          14 : makeD612resolvent(GEN pol, long flag)
    3627             : {
    3628          14 :   GEN R3, R = mynfsubfield(pol, 2);
    3629          14 :   if (flag < 2) return condrel(R, pol, flag);
    3630           7 :   R3 = mynfsubfield(pol, 3);
    3631           7 :   if (flag == 3) { R = condrel_i(R, pol); R3 = condrel_i(R3, pol); }
    3632           7 :   return mkvec2(R, R3);
    3633             : }
    3634             : 
    3635             : GEN
    3636         783 : nflist_D612_worker(GEN P3, GEN X, GEN Xinf, GEN limd2s2)
    3637             : {
    3638         783 :   pari_sp av = avma;
    3639         783 :   GEN v, D2, D3 = nfcoredisc(P3, &D2), D32 = sqri(D3), Q = divii(X, D32);
    3640         784 :   long limD2 = limd2s2[1], s2 = limd2s2[2];
    3641         784 :   long c, M, limD = cmpis(Q, limD2) < 0 ? itos(Q) : limD2;
    3642         784 :   v = cgetg(2 * limD + 1, t_VEC);
    3643        6027 :   for (M = 3, c = 1; M <= limD; M++)
    3644             :   {
    3645        5243 :     GEN N, LD = cgetg(1, t_VEC);
    3646             :     long g, i;
    3647             :     int p, m;
    3648        5243 :     uis_fundamental_pm(M, s2, &p, &m);
    3649        5243 :     if (absequaliu(D2, M))
    3650          91 :     { if (signe(D2) > 0) p = 0; else m = 0; }
    3651        5243 :     if (!(LD = ufund_pm(M, p, m))) continue;
    3652        2394 :     g = ugcdiu(D3, M);
    3653        2394 :     N = mulii(D32, muliu(sqru(M/g), M));
    3654        2394 :     if (cmpii(N, X) <= 0 && cmpii(shifti(N, 2), Xinf) >= 0)
    3655             :     {
    3656         336 :       long l = lg(LD);
    3657         686 :       for (i = 1; i < l; i++)
    3658             :       {
    3659         350 :         GEN P = makepol6(P3, X2m(gel(LD,i)));
    3660         350 :         if (odd(g)) gel(v, c++) = polredabs(P);
    3661         182 :         else if ((P = ZX_red_disc2(P, Xinf, X))) gel(v, c++) = P;
    3662             :       }
    3663             :     }
    3664             :   }
    3665         784 :   setlg(v, c); return gerepilecopy(av, v);
    3666             : }
    3667             : 
    3668             : static GEN
    3669          49 : makeD612vec(GEN X, GEN Xinf, GEN field, long s)
    3670             : {
    3671             :   GEN v, T;
    3672             :   long s2, s3;
    3673             : 
    3674          49 :   if (s == 1) return NULL;
    3675          42 :   v = NULL; gets2s3(s, &s2, &s3);
    3676          42 :   if (field)
    3677             :   {
    3678          14 :     if (degpol(field) == 3)
    3679             :     {
    3680           7 :       GEN D3 = nfdisc(field);
    3681           7 :       long si = signe(D3);
    3682           7 :       if ((si > 0 && s2 > 0) || (si < 0 && !s2)
    3683           7 :           || cmpii(sqri(D3), X) > 0) return NULL;
    3684           7 :       v = mkvec(field);
    3685             :     }
    3686             :     else
    3687             :     {
    3688           7 :       GEN D2a = absi_shallow(checkfield(field, 2));
    3689             :       long l, j, c;
    3690           7 :       if (!(v = makeS3vec(sqrti(divii(X, D2a)), gen_1, NULL, s3))) return NULL;
    3691           7 :       l = lg(v);
    3692         105 :       for (j = c = 1; j < l; j++)
    3693             :       {
    3694          98 :         GEN P = makepol6(gel(v, j), field);
    3695          98 :         if ((P = ZX_red_disc2(P, Xinf, X))) gel(v, c++) = P;
    3696             :       }
    3697           7 :       setlg(v, c); return sturmseparate(v, s, 6);
    3698             :     }
    3699             :   }
    3700          28 :   else if (!(v = makeS3vec(sqrti(X), gen_1, NULL, s3))) return NULL;
    3701          35 :   T = mkvecsmall2(floorsqrtn(X, 3), s2);
    3702          35 :   v = gen_parapply(closure("_nflist_D612_worker", mkvec3(X, Xinf, T)), v);
    3703          35 :   return sturmseparate(myshallowconcat1(v), s, 6);
    3704             : }
    3705             : 
    3706             : /**********************************************************************/
    3707             : /*                          A46 and S46P                              */
    3708             : /**********************************************************************/
    3709             : 
    3710             : /* A46, S46P, in place */
    3711             : static GEN
    3712         343 : makeS46Ppols(long card, GEN v)
    3713             : {
    3714         343 :   long l = lg(v), i;
    3715         343 :   GEN d = utoipos(card);
    3716         686 :   for (i = 1; i < l; i++)
    3717             :   {
    3718         343 :     GEN G = galoissplittinginit(gel(v,i), d), g = gal_get_gen(G);
    3719         343 :     GEN p = (card == 12)? gel(g, 1): mkvec2(gel(g, 1), gel(g, 4));
    3720         343 :     gel(v,i) = polredabs(galoisfixedfield(G, p, 1, 0));
    3721             :   }
    3722         343 :   return v;
    3723             : }
    3724             : /* S46M, in place */
    3725             : static GEN
    3726         630 : makeS46Mpols(GEN v, GEN X, GEN Xinf)
    3727             : {
    3728         630 :   long l = lg(v), i, c;
    3729         630 :   GEN d = utoipos(24);
    3730         861 :   for (i = c = 1; i < l; i++)
    3731             :   {
    3732         231 :     GEN G = galoissplittinginit(gel(v,i), d), g = gal_get_gen(G);
    3733         231 :     GEN p = perm_mul(gel(g, 4), gel(g, 2));
    3734         231 :     p = galoisfixedfield(G, p, 1, 0);
    3735         231 :     p = Xinf? ZX_red_disc2(p, Xinf, X): ZX_red_disc(p, X);
    3736         231 :     if (p) gel(v, c++) = p;
    3737             :   }
    3738         630 :   setlg(v, c); return v;
    3739             : }
    3740             : 
    3741             : static GEN
    3742          49 : makeA46(GEN N, GEN field, long s)
    3743             : {
    3744             :   GEN n, v, D;
    3745             :   long i, l, c;
    3746             : 
    3747          49 :   if (s== 1 || s==3 || !Z_issquareall(N, &n)) return NULL;
    3748          42 :   if (field)
    3749             :   {
    3750           7 :     GEN t, q, D = checkfield(field, 3);
    3751           7 :     if (!Z_issquare(D)
    3752           7 :         || !(q = divide(n, D)) || !(t = makeA4S4(field, q, s))) return NULL;
    3753           7 :     return makeS46Ppols(12, t);
    3754             :   }
    3755          35 :   D = divisors(gel(core2(n), 2));
    3756          35 :   l = lg(D); v = cgetg(l, t_VEC);
    3757          56 :   for (i = 2, c = 1; i < l; i++)
    3758             :   {
    3759          21 :     GEN t, q, g3 = gel(D,i), C = makeC3_f(g3);
    3760          21 :     long j, l = lg(C);
    3761          21 :     if (l == 1) continue;
    3762           7 :     q = diviiexact(n, sqri(g3));
    3763          14 :     for (j = 1; j < l; j++)
    3764           7 :       if ((t = makeA4S4(gel(C,j), q, s))) gel(v, c++) = makeS46Ppols(12,t);
    3765             :   }
    3766          35 :   setlg(v,c); return sturmseparate(myshallowconcat1(v), s, 6);
    3767             : }
    3768             : 
    3769             : static GEN
    3770          49 : makeS46P(GEN N, GEN field, long s)
    3771             : {
    3772             :   GEN n, v, D;
    3773             :   long i, snew, l, c;
    3774             : 
    3775          49 :   if (s==1 || s==3 || !Z_issquareall(N, &n)) return NULL;
    3776             :   /* s = -2, -1, 0, 2 */
    3777          42 :   if (field)
    3778             :   {
    3779           7 :     GEN D3 = checkfield(field, 3), f, t;
    3780           7 :     if (Z_issquare(D3) || !dvdii(n, D3)) return NULL;
    3781           7 :     snew = s == 2 && signe(D3) < 0 ? 1 : s;
    3782           7 :     f = divii(n, absi_shallow(D3));
    3783           7 :     if (!(t = makeA4S4(field, f, snew))) return NULL;
    3784           7 :     return makeS46Ppols(24, t);
    3785             :   }
    3786          35 :   D = divisors(n); l = lg(D); v = cgetg(l, t_VEC);
    3787          42 :   for (i = 2, c = 1; i < l; i++)
    3788             :   {
    3789           7 :     GEN f, P, D3a = gel(D,i);
    3790             :     long c3, j, lv3;
    3791           7 :     if (!(P =  makeDL(3, D3a, NULL, s? -1: 0))) continue;
    3792           7 :     f = gel(D, l-i); lv3 = lg(P);
    3793          14 :     for (j = c3 = 1; j < lv3; j++)
    3794             :     {
    3795           7 :       GEN T, P3 = gel(P,j);
    3796           7 :       long snew = (s == 2 && signe(ZX_disc(P3)) == -1) ? 1 : s;
    3797           7 :       if ((T = makeA4S4(P3, f, snew))) gel(P,c3++) = T;
    3798             :     }
    3799           7 :     if (c3 == 1) continue;
    3800           7 :     setlg(P, c3); gel(v, c++) = makeS46Ppols(24, shallowconcat1(P));
    3801             :   }
    3802          35 :   setlg(v,c); return sturmseparate(myshallowconcat1(v), s, 6);
    3803             : }
    3804             : 
    3805             : GEN
    3806         881 : nflist_A46S46P_worker(GEN P3, GEN Xinf, GEN sqX, GEN cards)
    3807             : {
    3808         881 :   pari_sp av = avma;
    3809         881 :   long card = cards[1], s = cards[2];
    3810         881 :   GEN w, F, V, DATA = S4data(P3, s), D3 = S4_get_disc(DATA);
    3811         882 :   GEN D3a = absi_shallow(D3);
    3812         882 :   long limf = itos(divii(sqX, D3a)), linf = 1, snew, f, i, c;
    3813             : 
    3814         882 :   if (cmpii(Xinf, sqri(shifti(D3a, 2))) >= 0)
    3815          21 :     linf = ceilsqrtdiv(Xinf, sqri(D3));
    3816         882 :   snew = s == 2 && signe(D3) < 0 ? 1 : s;
    3817         882 :   V = cgetg(limf, t_VEC);
    3818         882 :   F = vecfactoru_i(linf, limf);
    3819        5614 :   for (f = linf, i = c = 1; f <= limf; f++, i++)
    3820        4732 :     if ((w = A4S4_fa(DATA, gel(F,i), f, snew)))
    3821         315 :       gel(V, c++) = makeS46Ppols(card, w);
    3822         882 :   setlg(V,c); V = myshallowconcat1(V);
    3823         882 :   return gerepilecopy(av, V);
    3824             : }
    3825             : 
    3826             : static GEN
    3827          91 : makeA46S46Pvec(long card, GEN X, GEN Xinf, GEN field, long s)
    3828             : {
    3829             :   GEN v, sqX, T;
    3830             : 
    3831          91 :   if (s == 1 || s == 3) return NULL;
    3832          63 :   sqX = sqrti(X);
    3833          63 :   if (field)
    3834             :   {
    3835          14 :     GEN D = checkfield(field, 3);
    3836          14 :     long fl = Z_issquare(D);
    3837          14 :     if ((card == 12 && !fl) || (card == 24 && fl)) return  NULL;
    3838          14 :     v = mkvec(field);
    3839             :   }
    3840             :   else
    3841          49 :     v = card == 12? makeC3vec(sqX, gen_1, NULL, 0)
    3842          49 :                   : makeS3vec(sqX, gen_1, NULL, s? -1: 0);
    3843          63 :   if (!v) return NULL;
    3844          63 :   T = mkvec3(Xinf, sqX, mkvecsmall2(card, s == -2? -1: s));
    3845          63 :   v = gen_parapply(closure("_nflist_A46S46P_worker", T), v);
    3846          63 :   return sturmseparate(myshallowconcat1(v), s, 6);
    3847             : }
    3848             : 
    3849             : /**********************************************************************/
    3850             : /*                              S46M                                  */
    3851             : /**********************************************************************/
    3852             : static GEN
    3853         630 : glco46M(GEN F, GEN D2a)
    3854             : {
    3855         630 :   GEN C, F0, D = divisors(D2a);
    3856         630 :   long k, i, c, l = lg(D), klim = vali(D2a)? minss(2, vali(F)): 0;
    3857             :   /* could restrict divisors to multiples of (D2,F)/2^klim */
    3858             : 
    3859         630 :   F0 = klim? shifti(F, -klim): F;
    3860         630 :   C = cgetg((klim+1) * (l-1) + 1, t_VEC);
    3861        2030 :   for (i = c = 1; i < l; i++)
    3862             :   {
    3863        1400 :     GEN g = gcdii(F, gel(D,l-i));
    3864        1400 :     long v = vali(g);
    3865        1400 :     if (v) g = shifti(g, -v);
    3866        1400 :     if (!is_pm1(g) || v > klim) continue;
    3867             :     /* (F,D[l-i]) = 2^v; if v <= k <= klim, add F*D[i]>>k */
    3868        1386 :     gel(C, c++) = g = mulii(F0, gel(D,i));
    3869        1386 :     for (k = v; k < klim; k++) gel(C, c++) = g = shifti(g, 1);
    3870             :   }
    3871         630 :   setlg(C, c); return C;
    3872             : }
    3873             : 
    3874             : static GEN
    3875         630 : doA4S4(GEN field, GEN C, long s)
    3876             : {
    3877         630 :   long l = lg(C), i, c;
    3878         630 :   GEN w, v = cgetg(l, t_VEC);
    3879        2016 :   for (i = c = 1; i < l; i++)
    3880        1386 :     if ((w = makeA4S4(field, gel(C,i), s))) gel(v, c++) = w;
    3881         630 :   setlg(v,c); return myshallowconcat1(v);
    3882             : }
    3883             : 
    3884             : static GEN
    3885          49 : makeS46M(GEN N, GEN field, long s)
    3886             : {
    3887             :   GEN v, D, LC, F;
    3888             :   long i, c, l, snew;
    3889             : 
    3890          49 :   if (s == 1) return NULL;
    3891          42 :   snew = s == 3 ? 1 : maxss(s, -1);
    3892          42 :   if (field)
    3893             :   {
    3894             :     GEN D3, D2, D2a, t, Dpow;
    3895           7 :     checkfield_i(field, 3); D3 = nfcoredisc(field, &D2); D2a = absi_shallow(D2);
    3896           7 :     Dpow = mulii(D2a, sqri(D3));
    3897           7 :     if ((signe(D3) < 0 && (s == 0 || s == 2))
    3898           7 :         || (signe(D3) > 0 && (s == 3 || Z_issquare(D3)))
    3899           7 :         || !divissquareall(N, Dpow, &F)) return NULL;
    3900           7 :     LC = glco46M(F, D2a);
    3901           7 :     t = doA4S4(field, LC, snew); return makeS46Mpols(t, N, NULL);
    3902             :   }
    3903          35 :   D = divisorsdisc(cored(N, 3), snew);
    3904          35 :   l = lg(D); v = cgetg(l*l, t_VEC);
    3905          42 :   for (i = c = 1; i < l; i++)
    3906             :   {
    3907           7 :     GEN D2 = gel(D, i), D2a = absi_shallow(D2);
    3908           7 :     GEN NSD2 = divii(N, powiu(D2a, 3)), NSD4, F;
    3909             :     long j;
    3910           7 :     if (!Z_issquareall(NSD2, &NSD4)) continue;
    3911           7 :     F = divisors(cored(NSD2, 4));
    3912          21 :     for (j = 1; j < lg(F); j++)
    3913             :     {
    3914          14 :       GEN f2 = sqri(gel(F, j)), P;
    3915             :       long k, lP;
    3916          14 :       if (!(P = makeDL(3, mulii(D2a, f2), NULL, minss(snew, 1)))) continue;
    3917           7 :       lP = lg(P); F = divii(NSD4, f2); LC = glco46M(F, D2a);
    3918          14 :       for (k = 1; k < lP; k++) gel(P,k) = doA4S4(gel(P,k), LC, snew);
    3919           7 :       gel(v, c++) = makeS46Mpols(shallowconcat1(P), N, NULL);
    3920             :     }
    3921             :   }
    3922          35 :   if (c == 1) return NULL;
    3923           7 :   setlg(v,c); return sturmseparate(gtoset_shallow(shallowconcat1(v)), s, 6);
    3924             : }
    3925             : 
    3926             : GEN
    3927         252 : nflist_S46M_worker(GEN P3, GEN X, GEN Xinf, GEN gs)
    3928             : {
    3929         252 :   pari_sp av = avma;
    3930         252 :   long s = gs[1], snew = s == 3 ? 1 : s;
    3931         252 :   GEN V, DATA = S4data(P3, s), D3 = S4_get_disc(DATA);
    3932         252 :   GEN D2a = absi_shallow(coredisc(D3));
    3933         252 :   long lim = floorsqrtdiv(X, mulii(sqri(D3), D2a)), f, c;
    3934             : 
    3935         252 :   V = cgetg(lim + 1, t_VEC);;
    3936         868 :   for (f = 1, c = 1; f <= lim; f++)
    3937             :   {
    3938         616 :     GEN C = glco46M(utoipos(f), D2a), t = doA4S4(DATA, C, snew);
    3939         616 :     gel(V, c++) = makeS46Mpols(t, X, Xinf);
    3940             :   }
    3941         252 :   setlg(V,c); V = myshallowconcat1(V);
    3942         252 :   return gerepileupto(av, gtoset(V));
    3943             : }
    3944             : 
    3945             : static GEN
    3946          42 : makeS46Mvec(GEN X, GEN Xinf, GEN field, long s)
    3947             : {
    3948             :   GEN v;
    3949             : 
    3950          42 :   if (s == 1) return NULL;
    3951          35 :   if (field)
    3952             :   {
    3953           7 :     GEN D = checkfield(field, 3);
    3954           7 :     if (Z_issquare(D)) return NULL;
    3955           7 :     v = mkvec(field);
    3956             :   }
    3957             :   else
    3958             :   {
    3959          28 :     long s3 = s == 3? 1: (s < 0? -1: 0), l2, i, c;
    3960          28 :     GEN v2 = makeC2vec(sqrtnint(X,3), gen_1, NULL, s3);
    3961          28 :     if (!v2) return NULL;
    3962          28 :     l2 = lg(v2); v = cgetg(l2, t_VEC);
    3963        1092 :     for (i = c = 1; i < l2; i++)
    3964             :     {
    3965        1064 :       GEN w, T = gel(v2, i), D2a = absi_shallow(nfdisc(T));
    3966        1064 :       if ((w = makeS3vec(sqrti(divii(X, D2a)), gen_1, T, s3))) gel(v, c++) = w;
    3967             :     }
    3968          28 :     setlg(v,c); v = myshallowconcat1(v);
    3969             :   }
    3970          35 :   v = gen_parapply(closure("_nflist_S46M_worker",
    3971             :                            mkvec3(X, Xinf, mkvecsmall(s == -2? -1: s))), v);
    3972          35 :   return sturmseparate(myshallowconcat1(v), s, 6);
    3973             : }
    3974             : 
    3975             : /************************************************************************/
    3976             : /*                                  A462                                */
    3977             : /************************************************************************/
    3978             : static GEN
    3979         126 : arch0() { return mkvec(mkvec3(gen_0, gen_0, gen_0)); }
    3980             : static GEN
    3981          63 : arch1g() { return mkvec(mkvec3(gen_1, gen_0, gen_0)); }
    3982             : static GEN
    3983          63 : arch1() { return mkvec3(mkvec3(gen_1, gen_0, gen_0),
    3984             :                         mkvec3(gen_0, gen_1, gen_0),
    3985             :                         mkvec3(gen_0, gen_0, gen_1)); }
    3986             : static GEN
    3987          63 : arch2g() { return mkvec(mkvec3(gen_0, gen_1, gen_1)); }
    3988             : static GEN
    3989          63 : arch2() { return mkvec3(mkvec3(gen_0, gen_1, gen_1),
    3990             :                         mkvec3(gen_1, gen_0, gen_1),
    3991             :                         mkvec3(gen_1, gen_1, gen_0)); }
    3992             : static GEN
    3993          56 : arch3() { return mkvec(mkvec3(gen_1, gen_1, gen_1)); }
    3994             : 
    3995             : static GEN
    3996          91 : archA462(long s)
    3997             : {
    3998          91 :   switch (s)
    3999             :   {
    4000          14 :     case 0: return arch0();
    4001          14 :     case 1: return arch1g();
    4002          14 :     case 2: return arch2g();
    4003          49 :     default: return shallowconcat1(mkvec3(arch0(),arch1g(),arch2g()));
    4004             :   }
    4005             : }
    4006             : 
    4007             : static int
    4008        4515 : stable_arch(GEN v)
    4009             : {
    4010        4515 :   long i, l = lg(v);
    4011        4515 :   GEN x = gel(v,1);
    4012        7525 :   for (i = 2; i < l; i++) if (!equalii(x, gel(v,i))) return 0;
    4013        1505 :   return 1;
    4014             : }
    4015             : /* nf cyclic of prime degree, return a generator of */
    4016             : static GEN
    4017        5894 : cycfindaut(GEN nf)
    4018             : {
    4019        5894 :   GEN A = galoisconj(nf, NULL);
    4020        5894 :   return nfgaloismatrix(nf, gel(A, gequalX(gel(A,1))? 2 : 1));
    4021             : }
    4022             : 
    4023             : static int
    4024        2653 : isprM(GEN x)
    4025        2653 : { return typ(x) == t_MAT && lg(x) == 3; }
    4026             : static GEN
    4027       20251 : doA462(GEN bnf, GEN L, GEN Arch, GEN aut, GEN G, GEN GAL)
    4028             : {
    4029       20251 :   pari_sp av = avma;
    4030       20251 :   long c, k, i, m, lA = lg(Arch), l = lg(L);
    4031             :   int stable0;
    4032             :   GEN v;
    4033       20251 :   if (l == 1) return NULL;
    4034        2653 :   v = cgetg((lA-1) * (l-1) + 1, t_VEC);
    4035        2653 :   stable0 = !isprM(gel(L,l-1)); /* not implemented for prM */
    4036        7210 :   for (i = c = 1; i < lA; i++)
    4037             :   {
    4038        4557 :     GEN arch = gel(Arch, i);
    4039        4557 :     int stable = stable0 && stable_arch(arch);
    4040       15939 :     for (k = 1; k < l; k++)
    4041             :     {
    4042       11382 :       GEN R, id = gel(L,k), F = mkvec2(id, arch);
    4043             :       long cR, lR;
    4044       11382 :       if (stable && ZM_equal(nfgaloismatrixapply(bnf, aut, id), id))
    4045         497 :         R = mybnrclassfield_X(bnf, F, 2, NULL, NULL, G);
    4046             :       else
    4047       10885 :         R = mybnrclassfield(bnf, F, 2);
    4048       11382 :       lR = lg(R);
    4049       12460 :       for (m = cR = 1; m < lR; m++)
    4050             :       {
    4051        1078 :         GEN P = rnfequation(bnf, gel(R, m));
    4052        1078 :         if (okgal(P, GAL)) gel(R, cR++) = polredabs(P);
    4053             :       }
    4054       11382 :       if (cR > 1) { setlg(R, cR); gel(v, c++) = R; }
    4055             :     }
    4056             :   }
    4057        2653 :   if (c == 1) { set_avma(av); return NULL; }
    4058         819 :   setlg(v, c); return gtoset_shallow(shallowconcat1(v));
    4059             : }
    4060             : static GEN
    4061          49 : makeA462(GEN N, GEN field, long s)
    4062             : {
    4063             :   GEN v, L, Arch, GAL;
    4064             :   long i, c, l;
    4065             : 
    4066          49 :   if (s == 3) return NULL;
    4067          49 :   Arch = archA462(s);
    4068          49 :   GAL = mkvecsmall3(24, -1, 2);
    4069          49 :   if (field)
    4070             :   {
    4071           7 :     GEN D3 = checkfield(field, 3);
    4072           7 :     if (!Z_issquare(D3) || !dvdii(N, sqri(D3))) return NULL;
    4073           7 :     L = mkvec(field);
    4074             :   }
    4075             :   else
    4076             :   {
    4077          42 :     GEN LD = divisors(cored(N, 4));
    4078          42 :     L = cgetg(1, t_VEC);
    4079          91 :     for (i = 1; i < lg(LD); i++)
    4080             :     {
    4081          49 :       GEN t = makeC3_f(gel(LD,i));
    4082          49 :       if (lg(t) > 1) L = shallowconcat(L, t);
    4083             :     }
    4084             :   }
    4085          49 :   l = lg(L); v = cgetg(l, t_VEC);
    4086          63 :   for (i = c = 1; i < l; i++)
    4087             :   {
    4088          14 :     GEN bnf = bnfY(gel(L,i)), nf = bnf_get_nf(bnf), aut = cycfindaut(bnf);
    4089          14 :     GEN T, I = ideals_by_norm(nf, divii(N, sqri(nf_get_disc(nf))));
    4090          14 :     GEN G = mkvec2(galoisinit(nf, NULL), gen_0);
    4091          14 :     if ((T = doA462(bnf, I, Arch, aut, G, GAL))) gel(v, c++) = T;
    4092             :   }
    4093          49 :   if (c == 1) return NULL;
    4094          14 :   setlg(v, c); return sturmseparate(shallowconcat1(v), s, 6);
    4095             : }
    4096             : 
    4097             : GEN
    4098         175 : nflist_A462_worker(GEN P3, GEN X, GEN Xinf, GEN Arch, GEN GAL)
    4099             : {
    4100         175 :   pari_sp av = avma;
    4101         175 :   GEN bnf = bnfY(P3), aut = cycfindaut(bnf), v, t;
    4102         175 :   GEN G = mkvec2(galoisinit(bnf, NULL), gen_0), D2 = sqri(bnf_get_disc(bnf));
    4103         175 :   long c, l, j, lim = itos(divii(X, D2)), liminf = itos(ceildiv(Xinf, D2));
    4104             : 
    4105         175 :   v = ideallist(bnf, lim); l = lg(v);
    4106       20412 :   for (c = 1, j = liminf; j < l; j++)
    4107       20237 :     if ((t = doA462(bnf, gel(v,j), Arch, aut, G, GAL))) gel(v,c++) = t;
    4108         175 :   setlg(v, c); return gerepilecopy(av, myshallowconcat1(v));
    4109             : }
    4110             : static GEN
    4111          49 : makeA462vec(GEN X, GEN Xinf, GEN field, long s)
    4112             : {
    4113             :   GEN v, GAL;
    4114             : 
    4115          49 :   if (s == 3) return NULL;
    4116          42 :   if (field)
    4117             :   {
    4118           7 :     GEN D3 = checkfield(field, 3);
    4119           7 :     if (!Z_issquare(D3) || cmpii(sqri(D3), X) > 0) return NULL;
    4120           7 :     v = mkvec(field);
    4121             :   }
    4122          35 :   else if (!(v = makeC3vec(sqrti(X), gen_1, NULL, 0))) return NULL;
    4123          42 :   GAL = mkvecsmall3(24, -1, 2);
    4124          42 :   v = gen_parapply(closure("_nflist_A462_worker", mkvec4(X, Xinf, archA462(s), GAL)), v);
    4125          42 :   return sturmseparate(myshallowconcat1(v), s, 6);
    4126             : }
    4127             : 
    4128             : /************************************************************************/
    4129             : /*                                  S3C3                                */
    4130             : /************************************************************************/
    4131             : 
    4132             : static int
    4133        3626 : isok3(ulong N)
    4134             : {
    4135             :   GEN fa, P, E;
    4136        3626 :   long v = u_lvalrem(N, 3, &N), i, l;
    4137        3626 :   if (v == 1 || v >= 4) return 0;
    4138        2828 :   fa = factoru(N); P = gel(fa, 1); E = gel(fa, 2); l = lg(P);
    4139        3633 :   for (i = 1; i < l; i++)
    4140        2415 :     if (P[i] % 3 == 1) { if (E[i] != 1) return 0; }
    4141        1974 :     else               { if (E[i] != 2) return 0; }
    4142        1218 :   return 1;
    4143             : }
    4144             : 
    4145             : static GEN
    4146          49 : makeS3C3(GEN N, GEN field, long s)
    4147             : {
    4148             :   GEN v, LD, cond;
    4149             :   long s2, i;
    4150             : 
    4151          49 :   if (s == 1 || s == 2) return NULL;
    4152          35 :   s2 = s == 3 ? 1 : s;
    4153          35 :   if (field)
    4154             :   {
    4155           7 :     GEN D = checkfield(field, 2);
    4156           7 :     if (!divissquareall(N, powiu(absi_shallow(D), 3), &cond)) return NULL;
    4157           7 :     LD = mkvec(D);
    4158             :   }
    4159          28 :   else LD = divisorsdisc(cored(N, 3), s2);
    4160          35 :   v = cgetg(1, t_VEC);
    4161          49 :   for (i = 1; i < lg(LD); i++)
    4162             :   {
    4163          14 :     GEN L, bnf, nf, D = gel(LD, i);
    4164             :     long j, k;
    4165          14 :     if (!divissquareall(N, powiu(absi_shallow(D), 3), &cond)) continue;
    4166          14 :     bnf = bnfY(Y2m(D)); nf = bnf_get_nf(bnf);
    4167          14 :     L = ideals_by_norm(nf, cond);
    4168          42 :     for (j = 1; j < lg(L); j++)
    4169             :     {
    4170          28 :       GEN R = mybnrclassfield_N(bnf, gel(L,j), N, 3);
    4171          56 :       for (k = 1; k < lg(R); k++)
    4172             :       {
    4173          28 :         GEN P = rnfequation(nf, gel(R, k));
    4174          28 :         if (okgal1(P, 18)) v = vec_append(v, polredabs(P));
    4175             :       }
    4176             :     }
    4177             :   }
    4178          35 :   return sturmseparate(gtoset_shallow(v), s, 6);
    4179             : }
    4180             : 
    4181             : GEN
    4182         413 : nflist_S3C3_worker(GEN D2, GEN X, GEN Xinf)
    4183             : {
    4184         413 :   pari_sp av = avma;
    4185         413 :   GEN bnf = bnfY(Y2m(D2)), nf = bnf_get_nf(bnf), aut = cycfindaut(nf);
    4186         413 :   GEN G = mkvec2(galoisinit(bnf, NULL), gen_0);
    4187         413 :   long f, c, limf = floorsqrtdiv(X, powuu(itou(D2), 3));
    4188         413 :   GEN v = ideallist0(nf, limf, 4 | 8);
    4189             : 
    4190        4039 :   for (f = c = 1; f <= limf; f++)
    4191             :   {
    4192             :     pari_sp av2;
    4193             :     long j, k, cL;
    4194             :     GEN L;
    4195             : 
    4196        3626 :     if (!isok3(f)) continue;
    4197        1218 :     av2 = avma; L = gel(v, f);
    4198        2548 :     for (j = cL = 1; j < lg(L); j++)
    4199             :     {
    4200        1330 :       pari_sp av3 = avma;
    4201        1330 :       long stable = gequal(gel(L,j), nfgaloismatrixapply(nf, aut, gel(L,j)));
    4202        1330 :       GEN R = mybnrclassfield_X(bnf, gel(L,j), 3, X, Xinf, stable? G: NULL);
    4203        1330 :       long lR = lg(R), cR;
    4204        1582 :       for (k = cR = 1; k < lR; k++)
    4205             :       {
    4206         252 :         GEN P = rnfequation(nf, gel(R, k));
    4207         252 :         if (okgal1(P, 18)) gel(R, cR++) = polredabs(P);
    4208             :       }
    4209        1330 :       if (cR == 1) { set_avma(av3); continue; }
    4210         252 :       setlg(R, cR); gel(L, cL++) = R;
    4211             :     }
    4212        1218 :     if (cL == 1) { set_avma(av2); continue; }
    4213         126 :     setlg(L, cL); gel(v, c++) = shallowconcat1(L);
    4214             :   }
    4215         413 :   setlg(v, c); return gerepilecopy(av, gtoset_shallow(myshallowconcat1(v)));
    4216             : }
    4217             : 
    4218             : static GEN
    4219          42 : makeS3C3vec(GEN X, GEN Xinf, GEN field, long s)
    4220             : {
    4221             :   GEN v;
    4222             : 
    4223          42 :   if (s == 1 || s == 2) return NULL;
    4224          28 :   if (field)
    4225             :   {
    4226           7 :     GEN D = checkfield(field, 2);
    4227           7 :     v = mkvec(D);
    4228             :   }
    4229             :   else
    4230             :   {
    4231          21 :     long lim = floorsqrtn(X, 3), Da, c;
    4232          21 :     v = cgetg(2 * lim + 1, t_VEC);
    4233         945 :     for (Da = 3, c = 1; Da <= lim; Da++)
    4234             :     {
    4235             :       int p, m;
    4236         924 :       uis_fundamental_pm(Da, s, &p, &m);
    4237         924 :       if (p) gel(v, c++) = utoipos(Da);
    4238         924 :       if (m) gel(v, c++) = utoineg(Da);
    4239             :     }
    4240          21 :     if (c == 1) return NULL;
    4241          21 :     setlg(v, c);
    4242             :   }
    4243          28 :   v = gen_parapply(closure("_nflist_S3C3_worker", mkvec2(X, Xinf)), v);
    4244          28 :   return sturmseparate(myshallowconcat1(v), s, 6);
    4245             : }
    4246             : 
    4247             : /************************************************************************/
    4248             : /*                               S462                                   */
    4249             : /************************************************************************/
    4250             : 
    4251             : static GEN
    4252          98 : archS4621(long s)
    4253             : {
    4254          98 :   switch(s)
    4255             :   {
    4256          28 :     case 0: case 1: return cgetg(1, t_VEC);
    4257          14 :     case 2: retmkvec(mkvec(gen_0));
    4258           7 :     case 3: retmkvec(mkvec(gen_1));
    4259          49 :     default:retmkvec2(mkvec(gen_0), mkvec(gen_1));
    4260             :   }
    4261             : }
    4262             : 
    4263             : static GEN
    4264          98 : archS4623(long s)
    4265             : {
    4266          98 :   switch (s)
    4267             :   {
    4268          14 :     case 0: return arch0();
    4269          14 :     case 1: return arch1();
    4270          14 :     case 2: return arch2();
    4271           7 :     case 3: return arch3();
    4272          49 :     default:return shallowconcat1(mkvec4(arch0(),arch1(),arch2(),arch3()));
    4273             :   }
    4274             : }
    4275             : 
    4276             : static GEN
    4277          49 : makeS462(GEN N, GEN field, long s)
    4278             : {
    4279          49 :   GEN RES = cgetg(1, t_VEC), L, listarch1, listarch3, GAL;
    4280             :   long i, j, l, m;
    4281          49 :   listarch1 = archS4621(s); listarch3 = archS4623(s);
    4282          49 :   GAL = mkvecsmall3(48, -1, 1);
    4283          49 :   if (field)
    4284             :   {
    4285           7 :     GEN d = checkfield(field, 3);
    4286           7 :     if (Z_issquare(d) || !dvdii(N, sqri(d))) return NULL;
    4287           7 :     L = mkvec(field);
    4288             :   }
    4289             :   else
    4290             :   {
    4291             :     GEN T;
    4292             :     long c;
    4293          42 :     L =  divisors(cored(N, 2));
    4294          91 :     for (i = c = 1; i < lg(L); i++)
    4295          49 :       if ((T = makeDL(3, gel(L,i), NULL, (s == 0 || s == 1) ? 0 : -1)))
    4296           7 :         gel(L, c++) = T;
    4297          42 :     if (c == 1) return NULL;
    4298           7 :     setlg(L, c); L = shallowconcat1(L);
    4299             :   }
    4300          28 :   for (i = 1; i < lg(L); i++)
    4301             :   {
    4302          14 :     GEN bnf = bnfY(gel(L,i)), nf = bnf_get_nf(bnf);
    4303          14 :     GEN I = ideals_by_norm(nf, divii(N, sqri(nf_get_disc(nf))));
    4304          14 :     GEN Arch = nf_get_r1(nf) == 1 ? listarch1 : listarch3;
    4305          28 :     for (j = 1; j < lg(I); j++)
    4306             :     {
    4307          14 :       GEN id = gel(I, j);
    4308          42 :       for (l = 1; l < lg(Arch); l++)
    4309             :       {
    4310          28 :         GEN R = mybnrclassfield(bnf, mkvec2(id, gel(Arch, l)), 2);
    4311          42 :         for (m = 1; m < lg(R); m++)
    4312             :         {
    4313          14 :           GEN P = rnfequation(bnf, gel(R, m));
    4314          14 :           if (okgal(P, GAL) && (P = ZX_red_disc(P, N))) RES = vec_append(RES, P);
    4315             :         }
    4316             :       }
    4317             :     }
    4318             :   }
    4319          14 :   return sturmseparate(gtoset_shallow(RES), s, 6);
    4320             : }
    4321             : 
    4322             : GEN
    4323         957 : nflist_S462_worker(GEN P3, GEN X, GEN Xinf, GEN vArch, GEN GAL)
    4324             : {
    4325         957 :   pari_sp av = avma;
    4326         957 :   GEN bnf = bnfY(P3), nf = bnf_get_nf(bnf), D2 = sqri(nf_get_disc(nf));
    4327         959 :   long limf = itos(divii(X, D2)), liminf = itos(ceildiv(Xinf, D2));
    4328         959 :   long r1 = nf_get_r1(nf), c, j, k, l, m;
    4329         959 :   GEN v, vI = ideallist(bnf, limf), Arch = gel(vArch, r1 == 1? 1 : 2);
    4330             : 
    4331         959 :   v = cgetg(limf + 1, t_VEC);
    4332       12677 :   for (c = 1, j = liminf; j <= limf; j++)
    4333             :   {
    4334       11718 :     GEN I = gel(vI, j), REU = cgetg(1, t_VEC);
    4335       18263 :     for (k = 1; k < lg(I); k++)
    4336             :     {
    4337        6545 :       GEN id = gel(I, k);
    4338       16079 :       for (l = 1; l < lg(Arch); l++)
    4339             :       {
    4340        9534 :         GEN R = mybnrclassfield(bnf, mkvec2(id, gel(Arch, l)), 2);
    4341       10836 :         for (m = 1; m < lg(R); m++)
    4342             :         {
    4343        1302 :           GEN P = rnfequation(bnf, gel(R, m));
    4344        1302 :           if (okgal(P, GAL)) REU = vec_append(REU, polredabs(P));
    4345             :         }
    4346             :       }
    4347             :     }
    4348       11718 :     if (lg(REU) > 1) gel(v, c++) = REU;
    4349             :   }
    4350         959 :   setlg(v,c); v = myshallowconcat1(v);
    4351         959 :   return gerepilecopy(av, gtoset_shallow(v));
    4352             : }
    4353             : static GEN
    4354          56 : makeS462vec(GEN X, GEN Xinf, GEN field, long s)
    4355             : {
    4356             :   GEN v, T, GAL;
    4357             : 
    4358          56 :   if (field)
    4359             :   {
    4360           7 :     GEN D3 = checkfield(field, 3);
    4361           7 :     long si = signe(D3);
    4362           7 :     if (Z_issquare(D3) || (si < 0 && (s == 0 || s == 1))) return NULL;
    4363           7 :     v = mkvec(field);
    4364             :   }
    4365          49 :   else if (!(v = makeS3vec(sqrti(X), gen_1, NULL, (s==0 || s==1)? 0: -1)))
    4366           7 :     return NULL;
    4367          49 :   GAL = mkvecsmall3(48, -1, 1);
    4368          49 :   T = mkvec4(X, Xinf, mkvec2(archS4621(s), archS4623(s)), GAL);
    4369          49 :   v = gen_parapply(closure("_nflist_S462_worker", T), v);
    4370          49 :   return sturmseparate(myshallowconcat1(v), s, 6);
    4371             : }
    4372             : /************************************************************************/
    4373             : /*                              C32C4                                   */
    4374             : /************************************************************************/
    4375             : static GEN
    4376        2933 : doC32C4_i(GEN bnf, GEN L, GEN GAL)
    4377             : {
    4378        2933 :   long i, l = lg(L);
    4379             :   GEN v;
    4380        2933 :   if (l == 1) return L;
    4381        1631 :   v = cgetg(l, t_VEC);
    4382        4389 :   for (i = 1; i < l; i++)
    4383             :   {
    4384        2758 :     GEN w = cgetg(1, t_VEC), R = mybnrclassfield(bnf, gel(L,i), 3);
    4385        2758 :     long j, lR = lg(R);
    4386        3150 :     for (j = 1; j < lR; j++)
    4387             :     {
    4388         392 :       GEN P12 = rnfequation(bnf, gel(R, j)), S = _nfsubfields(P12, 6);
    4389         392 :       long k, lS = lg(S);
    4390         868 :       for (k = 1; k < lS; k++)
    4391             :       {
    4392         476 :         GEN P = gel(S,k);
    4393         476 :         if (okgal(P, GAL)) w = vec_append(w, polredabs(P));
    4394             :       }
    4395             :     }
    4396        2758 :     gel(v,i) = gtoset_shallow(w);
    4397             :   }
    4398        1631 :   return myshallowconcat1(v);
    4399             : }
    4400             : static GEN
    4401          21 : doC32C4(GEN N, GEN P4, GEN GAL)
    4402             : {
    4403          21 :   GEN nf, bnf, F, F2, D4 = nfdisc(P4), D2 = nfdisc(_nfsubfields1(P4, 2));
    4404          21 :   if (!(F2 = divide(N, mulii(D2,D4))) || !Z_issquareall(F2, &F)) return NULL;
    4405          21 :   bnf = bnfY(P4); nf = bnf_get_nf(bnf);
    4406          21 :   return doC32C4_i(bnf, ideals_by_norm(nf, F2), GAL);
    4407             : }
    4408             : static GEN
    4409          49 : makeC32C4_i(GEN N, GEN field, long s)
    4410             : {
    4411          49 :   GEN GAL = mkvecsmall3(36, 1, 1), v, w, C;
    4412             :   long c, i, j, l;
    4413          49 :   if (!Z_issquare(N) || s == 1 || s == 3) return NULL;
    4414          42 :   if (field)
    4415             :   {
    4416           7 :     checkfield_i(field, 4);
    4417           7 :     return (okgal2(field,4,-1) && ok_s(field, s))? doC32C4(N, field, GAL): NULL;
    4418             :   }
    4419          35 :   v = divisors(N); l = lg(v);
    4420         168 :   for (i = c = 1; i < l; i++)
    4421             :   {
    4422             :     long cw, lC;
    4423         133 :     if (!(C = makeC4(gel(v, i), NULL, maxss(s, -1)))) continue;
    4424          14 :     lC = lg(C);
    4425          28 :     for (j = cw = 1; j < lC; j++)
    4426          14 :       if ((w = doC32C4(N, gel(C,j), GAL))) gel(C,cw++) = w;
    4427          14 :     if (cw > 1) { setlg(C, cw); gel(v, c++) = shallowconcat1(C); }
    4428             :   }
    4429          35 :   setlg(v, c); return myshallowconcat1(v);
    4430             : }
    4431             : static GEN
    4432          49 : makeC32C4(GEN N, GEN field, long s)
    4433             : {
    4434          49 :   GEN v = makeC32C4_i(N, field, s);
    4435          49 :   return v? sturmseparate(v, s, 6): NULL;
    4436             : }
    4437             : 
    4438             : static GEN
    4439          28 : makeC32C4resolvent(GEN pol, long flag)
    4440             : {
    4441          28 :   GEN P12 = polredabs(gel(compositum(pol, pol), 2));
    4442          28 :   return condrel(mynfsubfield(P12,4), P12, flag);
    4443             : }
    4444             : 
    4445             : /* ideals of square norm < lim^2 */
    4446             : static GEN
    4447        6426 : ideallistsquare(GEN bnf, long lim)
    4448             : {
    4449        6426 :   pari_sp av = avma;
    4450        6426 :   GEN nf = bnf_get_nf(bnf), V, Z, F;
    4451        6426 :   long d = nf_get_degree(nf), lim2 = lim * lim, p;
    4452             :   forprime_t T;
    4453             : 
    4454        6426 :   if (lim <= 0) return cgetg(1, t_VEC);
    4455        6181 :   V = const_vec(lim, cgetg(1, t_VEC)); gel(V, 1) = mkvec(trivial_fact());
    4456        6181 :   u_forprime_init(&T, 2, lim);
    4457        6181 :   F = cgetg(d+1, t_VECSMALL);
    4458        6181 :   Z = cgetg(d+1, t_VECSMALL);
    4459       14770 :   while ((p = u_forprime_next(&T)))
    4460             :   {
    4461        8589 :     long lv, i, llp = ulogint(lim2, p), tot, m;
    4462        8589 :     GEN P = idealprimedec_limit_f(nf, utoipos(p), llp);
    4463        8589 :     GEN W = shallowcopy(V);
    4464        8589 :     lv = lg(P);
    4465       19845 :     for (i = tot = 1; i < lv; i++)
    4466             :     {
    4467       11256 :       F[i] = pr_get_f(gel(P,i));
    4468       11256 :       Z[i] = llp / F[i] + 1; tot *= Z[i];
    4469             :     }
    4470       75348 :     for (m = 1; m < tot; m++)
    4471             :     {
    4472       66759 :       GEN v = cgetg(lv, t_VECSMALL);
    4473       66759 :       long n = m, S = 0;
    4474      258377 :       for (i = 1; i < lv; i++) { v[i] = n % Z[i]; n /= Z[i]; S += v[i] * F[i]; }
    4475       66759 :       if (!odd(S) && S <= llp)
    4476             :       {
    4477       18459 :         GEN id = famat_remove_trivial(mkvec2(P, zc_to_ZC(v)));
    4478       18459 :         long j, pS = upowuu(p, S >> 1);
    4479       54509 :         for (j = 1; j <= lim / pS; j++)
    4480             :         {
    4481       36050 :           GEN vs = shallowcopy(gel(V, j));
    4482       36050 :           long k, l = lg(vs);
    4483       58583 :           for (k = 1; k < l; k++) gel(vs, k) = famat_mul(gel(vs, k), id);
    4484       36050 :           gel(W, pS * j) = shallowconcat(gel(W, pS * j), vs);
    4485             :         }
    4486             :       }
    4487             :     }
    4488        8589 :     V = W;
    4489             :   }
    4490        6181 :   return gerepilecopy(av, V);
    4491             : }
    4492             : 
    4493             : GEN
    4494        1133 : nflist_C32C4_worker(GEN P4, GEN X, GEN Xinf, GEN GAL)
    4495             : {
    4496        1133 :   pari_sp av = avma;
    4497        1133 :   GEN bnf = bnfY(P4), D4 = bnf_get_disc(bnf), D2 = nfdisc(_nfsubfields1(P4, 2));
    4498        1134 :   GEN vI, v, w, D4D2 = mulii(D4, D2);
    4499        1134 :   long f, c, limf = floorsqrtdiv(X, D4D2), liminf = ceilsqrtdiv(Xinf, D4D2);
    4500             : 
    4501        1134 :   vI = ideallistsquare(bnf, limf); v = cgetg(limf + 1, t_VEC);
    4502        4046 :   for (c = 1, f = liminf; f <= limf; f++)
    4503        2912 :     if ((w = doC32C4_i(bnf,  gel(vI, f), GAL))) gel(v, c++) = w;
    4504        1134 :   setlg(v,c); return gerepilecopy(av, gtoset_shallow(myshallowconcat1(v)));
    4505             : }
    4506             : static GEN
    4507          49 : makeC32C4vec(GEN X, GEN Xinf, GEN field, long s)
    4508             : {
    4509             :   GEN v, L, GAL;
    4510             : 
    4511          49 :   if (s == 1 || s == 3) return NULL;
    4512          35 :   GAL = mkvecsmall3(36, 1, 1);
    4513          35 :   if (field)
    4514             :   {
    4515           7 :     checkfield_i(field, 4);
    4516           7 :     if (!okgal2(field, 4, -1) || !ok_s(field, s)) return NULL;
    4517           7 :     L = mkvec(field);
    4518             :   }
    4519          28 :   else L = makeC4vec(divis(X, 5), gen_1, NULL, s == -2? -1: s);
    4520          35 :   v = gen_parapply(closure("_nflist_C32C4_worker", mkvec3(X, Xinf, GAL)), L);
    4521          35 :   return sturmseparate(myshallowconcat1(v), s, 6);
    4522             : }
    4523             : /************************************************************************/
    4524             : /*                                 C9                                   */
    4525             : /************************************************************************/
    4526             : 
    4527             : static GEN
    4528         210 : bnrcfC9(GEN bnf, GEN P, GEN F)
    4529             : {
    4530         210 :   GEN v, cond = F, vec9 = mkvec(utoipos(9)), nf = bnf_get_nf(bnf);
    4531         210 :   long i, l, c, lP = lg(P);
    4532         420 :   for (i = 1; i < lP; i++)
    4533             :   {
    4534         210 :     GEN p = gel(P, i), pr = idealprimedec_galois(nf, p);
    4535         210 :     if (equaliu(p, 3)) pr = idealsqr(nf, pr);
    4536         210 :     cond = idealmul(nf, cond, pr);
    4537             :   }
    4538         210 :   v = mybnrclassfield(bnf, cond, 3);
    4539         210 :   l = lg(v); if (l == 1) return v;
    4540         112 :   for (i = c = 1; i < l; i++)
    4541             :   {
    4542          56 :     GEN P = rnfequation(nf, gel(v,i)), G = galoisinit(P, NULL);
    4543          56 :     if (typ(G) != t_INT && gequal(galoisisabelian(G, 2), vec9))
    4544          56 :       gel(v, c++) = polredabs(P);
    4545             :   }
    4546          56 :   setlg(v, c); return gtoset_shallow(v);
    4547             : }
    4548             : 
    4549             : static GEN
    4550          56 : makeC9(GEN N, GEN field, long s)
    4551             : {
    4552             :   GEN v, D, F;
    4553             :   long i, lD;
    4554             : 
    4555          56 :   if (s > 0) return NULL;
    4556          42 :   if (field)
    4557             :   {
    4558           7 :     GEN D = checkfield(field, 3), d, P;
    4559           7 :     if (!Z_issquareall(D, &d)
    4560           7 :         || !divispowerall(N, powiu(D,4), 6, &F)) return NULL;
    4561           7 :     P = gel(Z_factor(d), 1);
    4562           7 :     return bnrcfC9(bnfY(field), P, F);
    4563             :   }
    4564          35 :   v = cgetg(1, t_VEC);
    4565          35 :   D = divisors(cored(N, 8)); lD = lg(D);
    4566          63 :   for (i = 2; i < lD; i++)
    4567             :   {
    4568          28 :     GEN v3, P, d = gel(D,i);
    4569             :     long j, l3;
    4570          28 :     if (!Z_ispowerall(divii(N, powiu(d, 8)), 6, &F)
    4571          28 :         || !checkcondC3(d, &P)) continue;
    4572          14 :     v3 = makeC3_i(d, P); l3 = lg(v3);
    4573          28 :     for (j = 1; j < l3; j++)
    4574          14 :       v = shallowconcat(v, bnrcfC9(bnfY(gel(v3,j)), P, F));
    4575             :   }
    4576          35 :   return s == -2? vecs(5, v): v;
    4577             : }
    4578             : 
    4579             : GEN
    4580          77 : nflist_C9_worker(GEN T, GEN X, GEN Xinf)
    4581             : {
    4582          77 :   pari_sp av = avma;
    4583          77 :   GEN bnf = bnfY(T), D3 = bnf_get_disc(bnf), D34 = powiu(D3, 4);
    4584          77 :   GEN sqD = sqrti(D3), P = gel(Z_factor(sqD), 1), v;
    4585          77 :   long fl = umodiu(D3, 3) == 0;
    4586          77 :   long limf = floorsqrtndiv(X, D34, 6), f, c;
    4587          77 :   long limi = ceilsqrtndiv(Xinf, D34, 6);
    4588             : 
    4589          77 :   v = cgetg(limf + 1, t_VEC); c = 1;
    4590         350 :   for (f = limi; f <= limf; f++)
    4591             :   {
    4592             :     GEN t;
    4593         273 :     if (fl) { long r = f % 9; if (r != 3 && r != 6) continue; }
    4594         189 :     t = bnrcfC9(bnf, P, utoipos(f));
    4595         189 :     if (lg(t) > 1) gel(v, c++) = t;
    4596             :   }
    4597          77 :   if (c == 1) { set_avma(av); return cgetg(1, t_VEC); }
    4598          35 :   setlg(v,c); return gerepilecopy(av, myshallowconcat1(v));
    4599             : }
    4600             : 
    4601             : static GEN
    4602          49 : makeC9vec(GEN X, GEN Xinf, GEN field, long s)
    4603             : {
    4604             :   GEN v;
    4605          49 :   if (s > 0) return NULL;
    4606          21 :   if (field)
    4607             :   {
    4608           7 :     GEN D = checkfield(field, 3);
    4609           7 :     if (!Z_issquare(D) || cmpii(powiu(D,4), X) > 0) return NULL;
    4610           7 :     v = mkvec(field);
    4611             :   }
    4612          14 :   else if (!(v = makeC3vec(sqrtnint(X, 4), gen_1, NULL, 0))) return NULL;
    4613          21 :   v = gen_parapply(closure("_nflist_C9_worker", mkvec2(X, Xinf)), v);
    4614          21 :   v = myshallowconcat1(v);
    4615          21 :   return (s == -2)? vecs(5, v): v;
    4616             : }
    4617             : /************************************************************************/
    4618             : /*                                C3xC3                                 */
    4619             : /************************************************************************/
    4620             : 
    4621             : static GEN
    4622          49 : makeC3C3(GEN N, GEN field, long s)
    4623             : {
    4624             :   GEN D, v, f, L;
    4625             :   long i, j, l, c;
    4626             : 
    4627          49 :   if (s > 0 || !Z_ispowerall(N, 6, &f)) return NULL;
    4628          35 :   D = divisors(f); l = lg(D);
    4629          35 :   if (field)
    4630             :   {
    4631           7 :     GEN d = checkfield(field, 3), g;
    4632           7 :     if (!Z_issquareall(d, &g) || !dvdii(f, g)) return NULL;
    4633           7 :     v = cgetg(l, t_VEC);
    4634          42 :     for (i = 2, c = 1; i < l; i++)
    4635             :     {
    4636          35 :       GEN t, g3 = gel(D, i);
    4637             :       long lt;
    4638          35 :       if (equalii(g3, g) || !equalii(lcmii(g,g3), f)) continue;
    4639          21 :       t = makeC3_f(g3); lt = lg(t); if (lt == 1) continue;
    4640          35 :       for (j = 1; j < lt; j++)
    4641          21 :         gel(t,j) = polredabs(polcompositum0(field, gel(t,j), 2));
    4642          14 :       gel(v, c++) = t;
    4643             :     }
    4644           7 :     setlg(v, c); return gtoset_shallow(myshallowconcat1(v));
    4645             :   }
    4646          28 :   L = const_vec(l-1, NULL);
    4647          28 :   v = cgetg(l * (l-1) / 2 + 1, t_VEC);
    4648          91 :   for (i = c = 1; i < l; i++)
    4649             :   {
    4650          63 :     GEN g = gel(D,i);
    4651         231 :     for (j = i; j < l; j++)
    4652         168 :       if (equalii(lcmii(g, gel(D,j)), f))
    4653             :       {
    4654             :         GEN Li, Lj, w;
    4655             :         long li, lj, a, b, cw;
    4656          77 :         if (!gel(L,i)) gel(L,i) = makeC3_f(g);
    4657          77 :         if (!gel(L,j)) gel(L,j) = makeC3_f(gel(D,j));
    4658          77 :         Li = gel(L,i); li = lg(Li);
    4659          77 :         Lj = gel(L,j); lj = lg(Lj); w = cgetg(li * lj, t_VEC);
    4660         119 :         for (a = cw = 1; a < li; a++)
    4661          84 :           for (b = i == j? a+1: 1; b < lj; b++)
    4662          42 :             gel(w, cw++) = polredabs(polcompositum0(gel(Li,a), gel(Lj,b), 2));
    4663          77 :         setlg(w, cw); gel(v, c++) = w;
    4664             :       }
    4665             :   }
    4666          28 :   setlg(v, c); v = gtoset_shallow(myshallowconcat1(v));
    4667          28 :   return s == -2? vecs(5, v): v;
    4668             : }
    4669             : 
    4670             : static GEN
    4671          21 : makeC3C3resolvent(GEN pol, long flag)
    4672             : {
    4673          21 :   GEN V = mynfsubfields(pol, 3);
    4674          21 :   if (lg(V) != 5) pari_err_BUG("makeC3C3resolvent");
    4675          21 :   if (flag < 2) return condrel(gel(V,1), pol, flag);
    4676          14 :   if (flag == 2) return V;
    4677           7 :   return mkvec4(condrel_i(gel(V,1), pol),
    4678           7 :                 condrel_i(gel(V,2), pol),
    4679           7 :                 condrel_i(gel(V,3), pol),
    4680           7 :                 condrel_i(gel(V,4), pol));
    4681             : }
    4682             : 
    4683             : /* x, y > 0 */
    4684             : static GEN
    4685         112 : lcmiu(GEN x, ulong y) { return muliu(x, y / ugcd(umodiu(x,y), y)); }
    4686             : static GEN
    4687        1680 : lcmuu(ulong x, ulong y) { return muluu(x, y / ugcd(x, y)); }
    4688             : 
    4689             : GEN
    4690         224 : nflist_C3C3_worker(GEN gi, GEN w, GEN F, GEN X)
    4691             : {
    4692         224 :   pari_sp av = avma;
    4693         224 :   long c, j, i = itos(gi), l = lg(w), f = F[i], x = X[1], xinf = X[2];
    4694         224 :   GEN P3 = gel(w, i), v = cgetg(l, t_VEC);
    4695        1904 :   for (j = i + 1, c = 1; j < l; j++)
    4696        1680 :     if (ok_intu(lcmuu(f, F[j]), x, xinf))
    4697         168 :       gel(v, c++) = polredabs(polcompositum0(P3, gel(w, j), 2));
    4698         224 :   setlg(v, c); return gerepilecopy(av, v);
    4699             : }
    4700             : 
    4701             : static GEN
    4702          49 : makeC3C3vec(GEN X, GEN Xinf, GEN field, long s)
    4703             : {
    4704             :   GEN F, v, v3;
    4705             :   long j, l, x, xinf;
    4706             : 
    4707          49 :   if (s > 0) return NULL;
    4708          21 :   x = floorsqrtn(X, 6);
    4709          21 :   v3 = C3vec_F(x, 1, &F); if (!v3) return NULL;
    4710          21 :   v3 = zvV_to_ZXV(v3); l = lg(v3);
    4711          21 :   v = cgetg((l - 1) * l / 2 + 1, t_VEC);
    4712          21 :   xinf = ceilsqrtn(Xinf, 6);
    4713          21 :   if (field)
    4714             :   {
    4715           7 :     GEN F3, D3 = checkfield(field, 3);
    4716             :     long c;
    4717           7 :     if (!Z_issquareall(D3, &F3)) return NULL;
    4718         119 :     for (j = c = 1; j < l; j++)
    4719         112 :       if (ok_intu(lcmiu(F3, F[j]), x, xinf) && !ZX_equal(gel(v3,j), field))
    4720          28 :         gel(v, c++) = polredabs(polcompositum0(field, gel(v3,j), 2));
    4721           7 :     setlg(v, c);
    4722             :   }
    4723             :   else
    4724             :   {
    4725          14 :     GEN T = mkvec3(v3, F, mkvecsmall2(x,xinf));
    4726          14 :     v = gen_parapply(closure("_nflist_C3C3_worker", T), identity_ZV(l-1));
    4727          14 :     v = myshallowconcat1(v);
    4728             :   }
    4729          21 :   v = gtoset_shallow(v); return s == -2? vecs(5, v): v;
    4730             : }
    4731             : 
    4732             : /************************************************************************/
    4733             : /*                                S32                                   */
    4734             : /************************************************************************/
    4735             : 
    4736             : static GEN
    4737         560 : makepolS32(GEN P1, GEN P2)
    4738             : {
    4739         560 :   GEN G = galoissplittinginit(polcompositum0(P1, P2, 2), utoipos(36));
    4740         560 :   GEN vH = galoissubgroups(G), g = mkvec2(gal_get_gen(G), gal_get_orders(G));
    4741         560 :   long i, l = lg(vH);
    4742       21616 :   for (i = 1; i < l; i++)
    4743             :   {
    4744       21616 :     GEN H = gel(vH, i);
    4745       21616 :     if (group_order(H) == 6 && !group_isabelian(H) /*S3*/
    4746        4816 :         && group_subgroup_is_faithful(g, H))
    4747         560 :       return polredabs(galoisfixedfield(G, H, 1, 0));
    4748             :   }
    4749             :   return NULL; /*LCOV_EXCL_LINE*/
    4750             : }
    4751             : 
    4752             : static GEN
    4753          77 : extractS3cond(GEN V3, GEN sqX, GEN field, long s)
    4754             : {
    4755          77 :   GEN v, v2 = NULL;
    4756          77 :   long l = lg(V3), c, c2, i;
    4757             : 
    4758          77 :   v = cgetg(l, t_VEC);
    4759          77 :   if (s == 3) v2 = cgetg(l, t_VEC);
    4760      629251 :   for (i = c = c2 = 1; i < l; i++)
    4761             :   {
    4762      629174 :     GEN pol = gel(V3, i), D, F, DF;
    4763      629174 :     (void)nfcoredisc2(pol, &D, &F); DF = mulii(D, F);
    4764      629174 :     if (abscmpii(DF, sqX) <= 0)
    4765             :     {
    4766        9450 :       GEN ind = field || s == 3 ? gen_0 : utoipos(c);
    4767        9450 :       GEN V = mkvecn(5, pol, F, mulii(sqri(DF), D), D, ind);
    4768        9450 :       if (s != 3 || signe(D) > 0) gel(v, c++) = V; else gel(v2, c2++) = V;
    4769             :     }
    4770             :   }
    4771          77 :   setlg(v, c); if (s != 3) return v;
    4772           7 :   setlg(v2, c2); return mkvec2(v, v2);
    4773             : }
    4774             : 
    4775             : static GEN makeS32common(GEN V3, GEN X, GEN Xinf, GEN field, long s);
    4776             : static GEN
    4777          49 : makeS32(GEN N, GEN field, long s)
    4778             : {
    4779             :   long s3, i, c, l;
    4780             :   GEN v, t;
    4781             : 
    4782          49 :   if (s == 1) return NULL;
    4783          42 :   s3 = -1; if (s == 0) s3 = 0; if (s == 2) s3 = 1;
    4784          42 :   v = divisors(N); l = lg(v);
    4785         868 :   for (i = 2, c = 1; i < l; i++)
    4786         826 :     if ((t = makeDL(3, gel(v, i), NULL, s3))) gel(v,c++) = t;
    4787          42 :   setlg(v,c); return makeS32common(myshallowconcat1(v), N, N, field, s);
    4788             : }
    4789             : 
    4790             : static GEN
    4791          28 : group_add_elt(GEN H, GEN g, long r)
    4792          28 : { return mkvec2(vec_append(gel(H,1),g), vecsmall_append(gel(H,2), r)); }
    4793             : 
    4794             : static GEN
    4795          14 : makeS32resolvent(GEN pol, long flag)
    4796             : {
    4797          14 :   GEN w, g1, g2, H1, H2, G = galoissplittinginit(pol, utoipos(36));
    4798          14 :   GEN v = galoissubgroups(G), g = galois_group(G);
    4799          14 :   long i, c, l = lg(v);
    4800         854 :   for (i = c = 1; i < l; i++)
    4801             :   {
    4802         840 :     GEN H = gel(v,i);
    4803         840 :     if (group_order(H) == 6 && group_subgroup_isnormal(g,H)) gel(v, c++) = H;
    4804             :   }
    4805          14 :   H1 = gel(v,1); g1 = gel(H1,1);
    4806          14 :   H2 = gel(v,2); g2 = gel(H2,1); /* G = H1 x H2, Hi ~ S3 */
    4807          14 :   H1 = group_add_elt(H1, gel(g2,2), 2);
    4808          14 :   H2 = group_add_elt(H2, gel(g1,2), 2);
    4809          14 :   w = condrel_dummy(galoisfixedfield(G,H1,1,0), flag);
    4810          14 :   if (flag >= 2) w = mkvec2(w, condrel_dummy(galoisfixedfield(G,H2,1,0),flag));
    4811          14 :   return w;
    4812             : }
    4813             : 
    4814             : /* s = 0: real, real; s = 1 imp; s = 2: imag, imag; s = 3: real, imag. */
    4815             : GEN
    4816        7436 : nflist_S32_worker(GEN S1, GEN X, GEN Xinf, GEN w, GEN gs)
    4817             : {
    4818        7436 :   pari_sp av = avma;
    4819        7436 :   GEN pol1 = gel(S1, 1), F1 = gel(S1, 2), A1 = gel(S1, 3), D1 = gel(S1, 4), v;
    4820        7436 :   long c, j, l = lg(w), i = itos(gel(S1, 5)), s = gs[1];
    4821        7439 :   v = cgetg(l, t_VEC);
    4822      767237 :   for (j = s == 3 ? 1 : i + 1, c = 1; j < l; j++)
    4823             :   {
    4824      760341 :     GEN S2 = gel(w,j), F2 = gel(S2,2), A2 = gel(S2,3), D2 = gel(S2,4), Q,P;
    4825      760341 :     if (equalii(D2, D1)) continue;
    4826      694040 :     P = mulii(sqri(gcdii(D1,D2)), gcdii(F1,F2)); /* usually 1 */
    4827      676527 :     Q = diviiexact(mulii(A1, A2), sqri(P)); if (abscmpii(Q, X) > 0) continue;
    4828         560 :     P = makepolS32(pol1, gel(S2,1));
    4829         560 :     if (ok_int(nfdisc(P), X, Xinf)) gel(v, c++) = P;
    4830             :   }
    4831        6896 :   setlg(v, c); return gerepilecopy(av, v);
    4832             : }
    4833             : 
    4834             : static GEN
    4835          77 : makeS32common(GEN v, GEN X, GEN Xinf, GEN field, long s)
    4836             : {
    4837             :   GEN v1, v2;
    4838          77 :   v = extractS3cond(v, sqrti(X), field, s);
    4839          77 :   if (field)
    4840             :   {
    4841             :     GEN D, F;
    4842             :     long si;
    4843          14 :     checkfield_i(field, 3); nfcoredisc2(field, &D, &F); si = signe(D);
    4844          14 :     if ((si > 0 && s == 2) || (si < 0 && s == 0) || equali1(D)) return NULL;
    4845          14 :     v2 = mkvec(mkvecn(5, field, F, mulii(sqri(F), powiu(D, 3)), D, gen_0));
    4846          14 :     if (s != 3) v1 = v; else v1 = gel(v, si > 0 ? 2 : 1);
    4847             :   }
    4848             :   else
    4849          63 :     if (s != 3) v1 = v2 = v; else { v1 = gel(v, 1); v2 = gel(v, 2); }
    4850          77 :   v = parapply(closure("_nflist_S32_worker", mkvec4(X, Xinf, v2, mkvecsmall(s))), v1);
    4851          77 :   return sturmseparate(gtoset_shallow(myshallowconcat1(v)), s, 6);
    4852             : }
    4853             : 
    4854             : static GEN
    4855          42 : makeS32vec(GEN X, GEN Xinf, GEN field, long s)
    4856             : {
    4857          42 :   long s3 = -1;
    4858             :   GEN v;
    4859             : 
    4860          42 :   if (s == 1) return NULL;
    4861          35 :   if (s == 0) s3 = 0; else if (s == 2) s3 = 1;
    4862          35 :   if (!(v = makeS3vec(divis(X, s? 3: 5), gen_1, NULL, s3))) return NULL;
    4863          35 :   return makeS32common(v, X, Xinf, field, s);
    4864             : }
    4865             : 
    4866             : /************************************************************************/
    4867             : /*                            C32:D4                                    */
    4868             : /************************************************************************/
    4869             : 
    4870             : static GEN
    4871          14 : makeC32D4resolvent(GEN pol, long flag) { return makeC32C4resolvent(pol, flag); }
    4872             : static int
    4873       25249 : cyc_is_trivial(GEN c) { return lg(c) == 1 || equali1(gel(c,1)); }
    4874             : 
    4875             : static GEN
    4876       25249 : C32D4pol(GEN bnf, GEN id)
    4877             : {
    4878       25249 :   GEN v, g3 = utoipos(3), bnr = bnrinitmod(bnf, id, 0, g3);
    4879             :   long l, i, c;
    4880             : 
    4881       25249 :   if (cyc_is_trivial(bnr_get_cyc(bnr))) return NULL;
    4882        2436 :   v = bnrclassfield(bnr, g3, 0, DEFAULTPREC);
    4883        2436 :   if (typ(v) == t_POL) v = mkvec(v);
    4884        2436 :   l = lg(v);
    4885        5040 :   for (i = c = 1; i < l; i++)
    4886             :   {
    4887        2604 :     GEN Q = rnfequation0(bnf, gel(v, i), 0);
    4888        2604 :     Q = _nfsubfields(Q, 6);
    4889        2604 :     if (lg(Q) > 1)
    4890             :     {
    4891        1848 :       Q = polredabs(gel(Q, 1));
    4892        1848 :       if (okgal1(Q, 72)) gel(v, c++) = Q;
    4893             :     }
    4894             :   }
    4895        2436 :   if (c == 1) return NULL;
    4896         714 :   setlg(v, c); return v;
    4897             : }
    4898             : 
    4899             : static GEN
    4900       27284 : bigdisc(GEN P) { return mulii(nfdisc(P), nfdisc(_nfsubfields1(P, 2))); }
    4901             : 
    4902             : /* v,w = factorization matrices (for ideals of the same norm), do we have
    4903             :  * aut(v) = w ? */
    4904             : static int
    4905         504 : prMconj(GEN nf, GEN v, GEN w, GEN aut)
    4906             : {
    4907         504 :   GEN P = gel(v,1), E = gel(v,2), Q = gel(w,1), F = gel(w,2);
    4908         504 :   long i, j, l = lg(P);
    4909         504 :   if (lg(Q) != l) return 0;
    4910         189 :   if (!ZV_equal(ZV_sort(E), ZV_sort(F))) return 0;
    4911         168 :   Q = shallowcopy(Q);
    4912         504 :   for (i = 1; i < l; i++)
    4913             :   {
    4914         336 :     GEN pr = gel(P,i), p = pr_get_p(pr), e = gel(E,i), pi = pr_get_gen(pr);
    4915         336 :     long ep = pr_get_e(pr), fp = pr_get_f(pr);
    4916         336 :     pi = nfgaloismatrixapply(nf, aut, pi);
    4917         693 :     for (j = 1; j < l; j++)
    4918             :     {
    4919         588 :       GEN qr = gel(Q,j);
    4920         588 :       if (!qr) continue;
    4921         441 :       if (pr_get_f(qr) == fp && pr_get_e(qr) == ep
    4922         441 :           && equalii(gel(F,j), e) && equalii(pr_get_p(qr), p)
    4923         441 :           && nfval(nf, pi, qr)) { gel(Q,j) = NULL; break; }
    4924             :     }
    4925             :   }
    4926         168 :   return 1;
    4927             : }
    4928             : 
    4929             : GEN
    4930       27271 : nflist_C32D4_worker(GEN P, GEN X, GEN Xinf, GEN gs)
    4931             : {
    4932       27271 :   pari_sp av = avma;
    4933       27271 :   GEN bd = bigdisc(P), RES = cgetg(1, t_VEC), L, bnf, nf, aut;
    4934       27272 :   long s = itos(gs), lim, j;
    4935             : 
    4936       27272 :   if (absi_cmp(bd, X) > 0) { avma = av; return cgetg(1, t_VEC); }
    4937        5292 :   bnf = bnfY(P); nf = bnf_get_nf(bnf); aut = cycfindaut(nf);
    4938        5292 :   lim = itos(divii(X, absi_shallow(bd)));
    4939        5292 :   L = ideallistsquare(bnf, lim);
    4940       24423 :   for (j = 1; j <= lim; j++)
    4941             :   {
    4942       19131 :     GEN v = gel(L, j);
    4943       19131 :     long k, lv = lg(v);
    4944       44548 :     for (k = 1; k < lv; k++)
    4945             :     {
    4946       25417 :       GEN R, vk = gel(v, k);
    4947             :       long m, n, c, lR;
    4948       25417 :       if (!vk || !(R = C32D4pol(bnf, vk))) continue;
    4949         714 :       lR = lg(R);
    4950        1428 :       for (m = c = 1; m < lR; m++)
    4951             :       {
    4952         714 :         GEN Z = gel(R, m);
    4953         714 :         if (ok_s(Z, s) && ok_int(nfdisc(Z), X, Xinf)) gel(R, c++) = Z;
    4954             :       }
    4955         714 :       if (c > 1) { setlg(R, c); RES = shallowconcat(RES, R); }
    4956        1071 :       for (n = k + 1; n < lv; n++)
    4957         525 :         if (gel(v,n) && prMconj(nf, vk, gel(v,n), aut)) {gel(v,n)=NULL; break;}
    4958             :     }
    4959             :   }
    4960        5292 :   return gerepilecopy(av, RES);
    4961             : }
    4962             : 
    4963             : static GEN
    4964          42 : makeC32D4vec(GEN X, GEN Xinf, GEN field, long s)
    4965             : {
    4966             :   long s4;
    4967             :   GEN v;
    4968             : 
    4969          42 :   if (s == -2) s4 = -1; else if (s == 3) s4 = 2; else s4 = s;
    4970          42 :   if (field)
    4971             :   {
    4972           7 :     checkfield_i(field, 4);
    4973           7 :     if (!okgal1(field, 8) || !ok_s(field,s4)) return NULL;
    4974           7 :     v = mkvec(field);
    4975             :   }
    4976          35 :   else v = makeD4vec(X, gen_1, NULL, s4);
    4977          42 :   v = parapply(closure("_nflist_C32D4_worker", mkvec3(X, Xinf, stoi(s))), v);
    4978          42 :   return sturmseparate(gtoset_shallow(myshallowconcat1(v)), s, 6);
    4979             : }
    4980             : 
    4981             : static GEN
    4982          49 : makeC32D4(GEN N, GEN field, long s)
    4983             : {
    4984             :   long s4, i, lv;
    4985             :   GEN v;
    4986          49 :   if (s == -2) s4 = -1; else if (s == 3) s4 = 2; else s4 = s;
    4987          49 :   if (field)
    4988             :   {
    4989           7 :     GEN D = checkfield(field, 4);
    4990           7 :     if (!okgal1(field, 8) || !ok_s(field,s4) || !dvdii(N, D)) return NULL;
    4991           7 :     v = mkvec(field);
    4992             :   }
    4993             :   else
    4994             :   {
    4995             :     long c;
    4996             :     GEN C;
    4997          42 :     v = divisors(absi(N)); lv = lg(v);
    4998         133 :     for (i = c = 1; i < lv; i++)
    4999          91 :       if ((C = makeD4(gel(v, i), NULL, s4)))
    5000             :       {
    5001          91 :         long j, cC, lC = lg(C);
    5002         105 :         for (j = cC = 1; j < lC; j++)
    5003          14 :           if (dvdii(N, bigdisc(gel(C,j)))) gel(C, cC++) = gel(C,j);
    5004          91 :         if (cC > 1) { setlg(C, cC); gel(v, c++) = C; }
    5005             :       }
    5006          42 :     if (c == 1) return NULL;
    5007           7 :     setlg(v, c); v = shallowconcat1(v);
    5008             :   }
    5009          14 :   lv = lg(v);
    5010          28 :   for (i = 1; i < lv; i++)
    5011          14 :     gel(v,i) = nflist_C32D4_worker(gel(v,i), N, N, stoi(s));
    5012          14 :   return sturmseparate(gtoset_shallow(myshallowconcat1(v)), s, 6);
    5013             : }
    5014             : 
    5015             : /************************************************************************/
    5016             : /*                         Global Programs                              */
    5017             : /************************************************************************/
    5018             : static long
    5019        2310 : grouptranslate(const char *g, long *t, int QT)
    5020             : {
    5021             :   long ell;
    5022             :   char r;
    5023             : 
    5024        2310 :   if (QT)
    5025             :   {
    5026          63 :     r = *g; ell = itos( strtoi(g + 1) );
    5027          63 :     if (ell < 0) return 0;
    5028          63 :     if (r == 'A') { *t = -2; return ell; }
    5029          35 :     if (r == 'S') { *t = -1; return ell; }
    5030          28 :     if (!strcmp(g, "C3")) { *t = -2; return ell; }
    5031             :   }
    5032        2261 :   if (!strcmp(g, "C1")) { *t = 1; return 1; }
    5033        2177 :   if (!strcmp(g, "C2") || !strcmp(g, "D2")) { *t = 1; return 2; }
    5034        2030 :   if (!strcmp(g, "C3")) { *t = 1; return 3; }
    5035        1939 :   if (!strcmp(g, "S3") || !strcmp(g,"D3")) { *t = 2; return 3; }
    5036        1813 :   if (!strcmp(g, "C4")) { *t = 1; return 4; }
    5037        1673 :   if (!strcmp(g, "V4")) { *t = 2; return 4; }
    5038        1582 :   if (!strcmp(g, "D4")) { *t = 3; return 4; }
    5039        1470 :   if (!strcmp(g, "A4")) { *t = 4; return 4; }
    5040        1372 :   if (!strcmp(g, "S4")) { *t = 5; return 4; }
    5041        1253 :   if (!strcmp(g, "C5")) { *t = 1; return 5; }
    5042        1162 :   if (!strcmp(g, "D5"))  { *t = 2; return 5; }
    5043        1050 :   if (!strcmp(g, "F5") || !strcmp(g, "M20"))  { *t = 3; return 5; }
    5044         952 :   if (!strcmp(g, "A5")) { *t = 4; return 5; }
    5045         896 :   if (!strcmp(g, "A5cond")) { *t = 9; return 5; }
    5046         854 :   if (!strcmp(g, "C6")) { *t = 1; return 6; }
    5047         735 :   if (!strcmp(g, "D6")) { *t = 2; return 6; }
    5048         735 :   if (!strcmp(g, "C7")) { *t = 1; return 7; }
    5049         651 :   if (!strcmp(g, "D7")) { *t = 2; return 7; }
    5050         560 :   if (!strcmp(g, "M21")) { *t = 3; return 7; }
    5051         483 :   if (!strcmp(g, "M42")) { *t = 4; return 7; }
    5052         413 :   if (!strcmp(g, "C9")) { *t = 1; return 9; }
    5053         308 :   if (!strcmp(g, "D9")) { *t = 3; return 9; }
    5054         196 :   if (QT)
    5055             :   {
    5056           0 :     if (!strcmp(g, "C8")) { *t = 1; return 8; }
    5057           0 :     if (!strcmp(g, "D8")) { *t = 2; return 8; }
    5058           0 :     if (!strcmp(g, "C10")) { *t = 1; return 10; }
    5059           0 :     if (!strcmp(g, "D10")) { *t = 3; return 10; }
    5060           0 :     if (!strcmp(g, "C11")) { *t = 1; return 11; }
    5061           0 :     if (!strcmp(g, "D11")) { *t = 2; return 11; }
    5062             :   }
    5063         196 :   r = *g; ell = itos( strtoi(g + 1) );
    5064         196 :   if (ell >= 8 && uisprime(ell))
    5065             :   {
    5066         189 :     if (r == 'C') { *t = 1; return ell; }
    5067          84 :     if (r == 'D') { *t = 2; return ell; }
    5068             :   }
    5069           7 :   *t = 0; return 0;
    5070             : }
    5071             : static long
    5072        6090 : group_nTk(GEN g, long *t, int QT)
    5073             : {
    5074        6090 :   long L[] = { 0, /* https://oeis.org/A002106 */
    5075             :   1,1,2,5,5,16,7,50,34,45,8,301,9,63,104,1954,10,
    5076             :   983,8,1117,164,59,7,25000,211,96,2392,1854,8,5712,
    5077             :   12,2801324,162,115,407,121279,11,76,306,315842,10,
    5078             :   9491,10,2113,10923,56,6 };
    5079        6090 :   long N = numberof(L), n, k;
    5080             : 
    5081        6090 :   if (lg(g) != 3 || !RgV_is_ZV(g)) { *t = 0; return 0; }
    5082        6090 :   n = itos(gel(g,1)); if (n <= 0) return 0;
    5083        6090 :   if (n >= N) pari_err_IMPL(stack_sprintf("group nTk with n > %ld", N-1));
    5084        6090 :   *t = k = itos(gel(g,2));
    5085        6090 :   if (k <= 0 || k > L[n])
    5086             :   {
    5087             :     char *s;
    5088          14 :     s = stack_sprintf("incorrect group %ldTk with k = %ld not in [1,%ld]",
    5089             :                       n, k, L[n]);
    5090          14 :     pari_err(e_MISC, s);
    5091             :   }
    5092        6076 :   if (!QT)
    5093             :   {
    5094        1246 :     if (n <= 9)
    5095             :     {
    5096        1225 :       long v[] = { 0, 1, 1, 2, 5, 4, 13, 4, 0, 3 };
    5097        1225 :       return k <= v[n]? n: 0;
    5098             :     }
    5099          21 :     return (uisprime(n) && k <= 2)? n: 0;
    5100             :   }
    5101        4830 :   if (n <= 2) *t = -2; /* An */
    5102        4802 :   else if (k == L[n]) *t = -1; /* Sn */
    5103        4669 :   else if (k == L[n]-1) *t = -2; /* An */
    5104        4830 :   return n;
    5105             : }
    5106             : 
    5107             : static int
    5108        1036 : okfield(GEN F) { return typ(F) == t_POL && RgX_is_ZX(F) && ZX_is_irred(F); }
    5109             : static GEN
    5110        1974 : nfmakenum(long n, long t, GEN N, GEN field, long s)
    5111             : {
    5112        1974 :   GEN v = NULL;
    5113        1974 :   switch(100 * n + t)
    5114             :   {
    5115          35 :     case 101: return makeC1(N, field, s);
    5116          98 :     case 201: return makeC2(N, field, s);
    5117          77 :     case 301: return makeC3(N, field, s);
    5118          56 :     case 302: return makeDL(3, N, field, s);
    5119         196 :     case 401: return makeC4(N, field, s);
    5120          49 :     case 402: return makeV4(N, field, s);
    5121          63 :     case 403: return makeD4(N, field, s);
    5122          49 :     case 404: return makeA4(N, field, s);
    5123          77 :     case 405: return makeS4(N, field, s);
    5124          49 :     case 501: return makeC5(N, field, s);
    5125          63 :     case 502: return makeDL(5, N, field, s);
    5126          56 :     case 503: return makeMgen(5, 4, N, field, s); /*F5*/
    5127          14 :     case 504: return makeA5(N, s);
    5128           7 :     case 509: return makeA5cond(N, s);
    5129          98 :     case 601: return makeC6(N, field, s);
    5130          56 :     case 602: return makeS36(N, field, s);
    5131          56 :     case 603: return makeD612(N, field, s);
    5132          49 :     case 604: return makeA46(N, field, s);
    5133          49 :     case 605: return makeS3C3(N, field, s);
    5134          49 :     case 606: return makeA462(N, field, s);
    5135          49 :     case 607: return makeS46P(N, field, s);
    5136          49 :     case 608: return makeS46M(N, field, s);
    5137          49 :     case 609: return makeS32(N, field, s);
    5138          49 :     case 610: return makeC32C4(N, field, s);
    5139          49 :     case 611: return makeS462(N, field, s);
    5140           7 :     case 612: return makeA56(N, s);
    5141          49 :     case 613: return makeC32D4(N, field, s);
    5142          49 :     case 701: return makeCL(7, N, field, s);
    5143          49 :     case 702: return makeDL(7, N, field, s);
    5144          35 :     case 703: return makeMgen(7, 3, N, field, s); /*M21*/
    5145          35 :     case 704: return makeMgen(7, 6, N, field, s);
    5146          56 :     case 901: return makeC9(N, field, s);
    5147          49 :     case 902: return makeC3C3(N, field, s);
    5148          63 :     case 903: return makeD9(N, field, s);
    5149             :   }
    5150          91 :   if (!v && uisprime(n)) switch(t)
    5151             :   {
    5152          56 :     case 1: return makeCL(n, N, field, s);
    5153          35 :     case 2: return makeDL(n, N, field, s);
    5154             :   }
    5155             :   return NULL;/*LCOV_EXCL_LINE*/
    5156             : }
    5157             : /* deg(pol) < 8 */
    5158             : static GEN
    5159         441 : nfresolvent_small(GEN pol, long flag)
    5160             : {
    5161         441 :   long deg = degpol(pol), dP, s;
    5162             :   GEN G;
    5163         441 :   if (deg == 1) return makeC1resolvent(flag);
    5164         420 :   if (deg == 2) return makeC2resolvent(pol, flag);
    5165         406 :   G = polgalois(pol, DEFAULTPREC);
    5166         406 :   dP = itos(gel(G,1));
    5167         420 :   if (deg == 3) return dP == 3? makeC3resolvent(pol, flag)
    5168          42 :                               : makeS3resolvent(pol, flag);
    5169         378 :   s = itos(gel(G,2));
    5170         378 :   if (deg == 4)
    5171             :   {
    5172          91 :     if (dP == 4) return s == -1? makeC4resolvent(pol, flag)
    5173          49 :                                : makeV4resolvent(pol, flag);
    5174          42 :     if (dP == 8) return condrelresolvent(pol, 2, flag); /*D4*/
    5175          28 :     return makeA4S4resolvent(pol, flag);
    5176             :   }
    5177         301 :   if (deg == 5)
    5178             :   {
    5179          56 :     if (dP == 5)  return makeCLresolvent(5, pol, flag);
    5180          42 :     if (dP == 10) return makeDLresolvent(5, pol, flag);
    5181          28 :     if (dP == 20) return makeMgenresolvent(5, 4, pol, flag); /*F5*/
    5182          14 :     if (dP == 60) return makeA5resolvent(pol, flag);
    5183             :   }
    5184         252 :   if (deg == 6)
    5185             :   {
    5186         196 :     if (dP == 6 && s == -1)
    5187             :     { /* works both with new_galois_format set or unset */
    5188          49 :       long k = itos(gel(G,3));
    5189          28 :       return k == 1? makeC6resolvent(pol, flag)
    5190          77 :                    : makeS36resolvent(pol, flag);
    5191             :     }
    5192         161 :     if (dP == 12) return s == -1? makeD612resolvent(pol, flag)
    5193          42 :                                 : condrelresolvent(pol,3,flag); /*A46*/
    5194         119 :     if (dP == 18) return condrelresolvent(pol,2,flag); /*S3C3*/
    5195         105 :     if (dP == 24) return condrelresolvent(pol,3,flag); /*S46P,S46M,A462*/
    5196          77 :     if (dP == 36) return (s == 1)? makeC32C4resolvent(pol, flag)
    5197          42 :                                  : makeS32resolvent(pol, flag);
    5198          35 :     if (dP == 48) return condrelresolvent(pol,3,flag); /*S462*/
    5199          21 :     if (dP == 60) return makeA56resolvent(pol,flag);
    5200          14 :     if (dP == 72) return makeC32D4resolvent(pol, flag);
    5201             :   }
    5202          56 :   if (deg == 7)
    5203             :   {
    5204          49 :     if (dP == 7)  return makeCLresolvent(7, pol, flag);
    5205          35 :     if (dP == 14) return makeDLresolvent(7, pol, flag);
    5206          21 :     if (dP == 21) return makeMgenresolvent(7, 3, pol, flag); /*M21*/
    5207          14 :     if (dP == 42) return makeMgenresolvent(7, 6, pol, flag); /*M42*/
    5208             :   }
    5209           7 :   return gen_0;
    5210             : }
    5211             : 
    5212             : static GEN
    5213         525 : nfresolvent_i(GEN pol, long flag)
    5214             : {
    5215             :   long d;
    5216             :   GEN G;
    5217             : 
    5218         525 :   if (!okfield(pol)) pari_err_TYPE("nfresolvent", pol);
    5219         525 :   if (flag < 0 || flag > 3) pari_err_FLAG("nfresolvent");
    5220         525 :   d = degpol(pol);
    5221         525 :   if (d < 8) return nfresolvent_small(pol, flag);
    5222          84 :   if (d != 9 && !uisprime(d)) return gen_0;
    5223          84 :   G = galoisinit(pol, NULL);
    5224          84 :   if (typ(G) != t_INT)
    5225             :   {
    5226          56 :     if (d == 9)
    5227             :     {
    5228          35 :       long n = lg(gal_get_gen(G))-1;
    5229          14 :       return n == 1? condrelresolvent(pol,3,flag) /*C9*/
    5230          49 :                    : makeC3C3resolvent(pol, flag); /*C3xC3*/
    5231             :     }
    5232          21 :     return makeCLresolvent(d, pol, flag);
    5233             :   }
    5234          28 :   G = galoissplittinginit(pol, utoipos(2*d));
    5235          28 :   if (gal_get_order(G) != 2*d) return gen_0;
    5236          21 :   return d == 9? makeD9resolvent(G, flag): makeDLresolvent(d, pol, flag);
    5237             : }
    5238             : GEN
    5239         525 : nfresolvent(GEN pol, long flag)
    5240         525 : { pari_sp av = avma; return gerepilecopy(av, nfresolvent_i(pol, flag)); }
    5241             : 
    5242             : /* 1 <= Xinf <= X */
    5243             : static GEN
    5244        1904 : nfmakevecnum(long n, long t, GEN X, GEN Xinf, GEN field, long s)
    5245             : {
    5246        1904 :   switch(n * 100 + t)
    5247             :   {
    5248          28 :     case 101: return makeC1vec(Xinf, field, s);
    5249          35 :     case 201: return makeC2vec(X, Xinf, field, s);
    5250          70 :     case 301: return makeC3vec(X, Xinf, field, s);
    5251          49 :     case 302: return makeS3vec(X, Xinf, field, s);
    5252         105 :     case 401: return makeC4vec(X, Xinf, field, s);
    5253          42 :     case 402: return makeV4vec(X, Xinf, field, s);
    5254          49 :     case 403: return makeD4vec(X, Xinf, field, s);
    5255          49 :     case 404: return makeA4S4vec(1, X, Xinf, field, s);
    5256          42 :     case 405: return makeA4S4vec(0, X, Xinf, field, s);
    5257          42 :     case 501: return makeC5vec(X, Xinf, field, s);
    5258          49 :     case 502: return makeDLvec(5, X, Xinf, field, s);
    5259          63 :     case 503: return makeMgenvec(5, 4, X, Xinf, field, s); /*F5*/
    5260          42 :     case 504: return makeA5vec(X, Xinf, field, s);
    5261          35 :     case 509: return makeA5condvec(X, Xinf, field, s);
    5262          91 :     case 601: return makeC6vec(X, Xinf, field, s);
    5263          49 :     case 602: return makeS36vec(X, Xinf, field, s);
    5264          49 :     case 603: return makeD612vec(X, Xinf, field, s);
    5265          42 :     case 604: return makeA46S46Pvec(12, X, Xinf, field, s);/*A46S*/
    5266          42 :     case 605: return makeS3C3vec(X, Xinf, field, s);
    5267          49 :     case 606: return makeA462vec(X, Xinf, field, s);
    5268          49 :     case 607: return makeA46S46Pvec(24, X, Xinf, field, s); /*S46P*/
    5269          42 :     case 608: return makeS46Mvec(X, Xinf, field, s);
    5270          42 :     case 609: return makeS32vec(X, Xinf, field, s);
    5271          49 :     case 610: return makeC32C4vec(X, Xinf, field, s);
    5272          56 :     case 611: return makeS462vec(X, Xinf, field, s);
    5273          49 :     case 612: return makeA56vec(X, Xinf, s);
    5274          42 :     case 613: return makeC32D4vec(X, Xinf, field, s);
    5275          35 :     case 701: return makeCLvec(7, X, Xinf, field, s);
    5276          42 :     case 702: return makeDLvec(7, X, Xinf, field, s);
    5277          42 :     case 703: return makeMgenvec(7, 3, X, Xinf, field, s); /*M21*/
    5278          35 :     case 704: return makeMgenvec(7, 6, X, Xinf, field, s); /*M41*/
    5279          49 :     case 901: return makeC9vec(X, Xinf, field, s);
    5280          49 :     case 902: return makeC3C3vec(X, Xinf, field, s);
    5281          49 :     case 903: return makeD9vec(X, Xinf, field, s);
    5282             :   }
    5283         252 :   if (uisprime(n)) switch(t)
    5284             :   {
    5285         203 :     case 1: return makeCLvec(n, X, Xinf, field, s);
    5286          49 :     case 2: return makeDLvec(n, X, Xinf, field, s);
    5287             :   }
    5288             :   return NULL;/*LCOV_EXCL_LINE*/
    5289             : }
    5290             : 
    5291             : /* s > -2 */
    5292             : static GEN
    5293          14 : nfmakesomehard(long n, long t, long s)
    5294             : {
    5295          14 :   pari_sp av = avma;
    5296             :   long i;
    5297         168 :   for (i = 1;; i++, set_avma(av))
    5298         154 :   {
    5299         168 :     GEN v = nfmakevecnum(n, t, int2n(18 + 2*i), gen_1, NULL, s);
    5300         168 :     if (v && lg(v) > 2) return v;
    5301             :   }
    5302             : }
    5303             : static long
    5304         105 : minlim(GEN v)
    5305             : {
    5306         105 :   long i, m = LONG_MAX;
    5307         105 :   if (!v) return m;
    5308         392 :   for (i = lg(v)-1; i; i--) if (v[i] && m > v[i]) m = v[i];
    5309         105 :   return m;
    5310             : }
    5311             : static GEN
    5312         168 : nfmakesome(long n, long t, long s)
    5313             : {
    5314         168 :   GEN v = NULL;
    5315         168 :   long lim, flag = 0;
    5316         168 :   switch(n * 100 + t)
    5317             :   {
    5318           7 :     case 101: v = mkvecsmall(1); break;
    5319           7 :     case 201: v = mkvecsmall2(33, 24); break;
    5320           7 :     case 301: v = mkvecsmall2(3969, 0); break;
    5321          14 :     case 302: v = mkvecsmall2(568, 108); break;
    5322           7 :     case 401: v = mkvecsmall3(35152, 0, 44217); break;
    5323           7 :     case 402: v = mkvecsmall3(14400, 0, 1225); break;
    5324           7 :     case 403: v = mkvecsmall3(5125, 1375, 549); break;
    5325           7 :     case 404: v = mkvecsmall3(270400, 0, 29241); break;
    5326           7 :     case 405: v = mkvecsmall3(8468, 976, 1076); break;
    5327           7 :     case 501: v = mkvecsmall3(1073283121, 0, 0); break;
    5328           7 :     case 502: v = mkvecsmall3(4330561, 0, 51529); break;
    5329          14 :     case 503: v = mkvecsmall3(LONG_MAX, 0, 253125); break;
    5330          21 :     case 504: v = mkvecsmall3(11812969, 0, 149769); break;
    5331          21 :     case 509: v = mkvecsmall3(5105, 0, 992); break;
    5332           0 :     case 601: v = mkvecsmall4(4148928, 0, 0, 2250423); break;
    5333           0 :     case 602: v = mkvecsmall4(32166277, 0, 0, 273375); break;
    5334           0 :     case 603: v = mkvecsmall4(9045125, 0, 242000, 86528); break;
    5335           0 :     case 604: v = mkvecsmall4(125238481, 0, 4439449, 0); break;
    5336           0 :     case 605: v = mkvecsmall4(7442000, 0, 0, 143883); break;
    5337           0 :     case 606: v = mkvecsmall4(2115281, 419904, 373977, 0); break;
    5338           0 :     case 607: v = mkvecsmall4(12730624, 0, 118336, 0); break;
    5339           0 :     case 608: v = mkvecsmall4(183250432, 0, 440711081, 13144256); break;
    5340           0 :     case 609: v = mkvecsmall4(LONG_MAX, 0, 1382400, 1494108); break;
    5341           0 :     case 610: v = mkvecsmall4(765905625, 0, 4950625, 0); break;
    5342           0 :     case 611: v = mkvecsmall4(5695040, 941872, 57661, 37479); break;
    5343          21 :     case 612: v = mkvecsmall4(185313769, 0, 1907161, 0); break;
    5344           0 :     case 613: v = mkvecsmall4(LONG_MAX, 221875, 87625, 44496); break;
    5345           0 :     case 701: v = mkvecsmall4(LONG_MAX, 0, 0, 0); break;
    5346           0 :     case 702: v = mkvecsmall4(LONG_MAX, 0, 0, 80062991); break;
    5347           0 :     case 703: v = mkvecsmall4(LONG_MAX, 0, 0, 0); break;
    5348           0 :     case 704: v = mkvecsmall4(LONG_MAX, 0, 0, LONG_MAX); break;
    5349           0 :     case 901: v = mkvecsmall5(LONG_MAX, 0, 0, 0, 0); break;
    5350           0 :     case 902: v = mkvecsmall5(LONG_MAX, 0, 0, 0, 0); break;
    5351           0 :     case 903: v = mkvecsmall5(LONG_MAX, 0, 0, 0, LONG_MAX); break;
    5352             :   }
    5353         168 :   if (!v) flag = uisprime(n) && t <= 2? t: 0;
    5354         168 :   if (s == -2)
    5355             :   {
    5356          42 :     long i, l = (n >> 1) + 2;
    5357          42 :     GEN W = cgetg(l, t_VEC);
    5358         189 :     for (i = 1; i < l; i++)
    5359             :     {
    5360         147 :       GEN w = NULL;
    5361         147 :       if (!v)
    5362          42 :       { if (i == 1 || (i == l-1 && flag == 2)) w = nfmakesomehard(n, t, i-1); }
    5363         105 :       else if (v[i] == LONG_MAX)
    5364           7 :         w = nfmakesomehard(n, t, i-1);
    5365          98 :       else if (v[i])
    5366          63 :         w = nfmakevecnum(n, t, utoipos(v[i]), gen_1, NULL, i-1);
    5367         147 :       gel(W, i) = w? w: cgetg(1, t_VEC);
    5368             :     }
    5369          42 :     return W;
    5370             :   }
    5371         126 :   else if (s == -1)
    5372         105 :     lim = minlim(v);
    5373             :   else
    5374             :   {
    5375          21 :     lim = v[s + 1];
    5376          21 :     if (!lim) return cgetg(1, t_VEC);
    5377             :   }
    5378         112 :   if (lim == LONG_MAX) return nfmakesomehard(n, t, s);
    5379         112 :   return nfmakevecnum(n, t, utoipos(lim), gen_1, NULL, s);
    5380             : }
    5381             : 
    5382             : GEN
    5383        8400 : nflist(GEN GP, GEN N, long s, GEN field)
    5384             : {
    5385        8400 :   pari_sp av = avma;
    5386             :   GEN v, X, Xinf;
    5387        8400 :   long n = 0, t = 0, tp = typ(GP);
    5388        8400 :   long QT = N && typ(N) == t_POL;
    5389             : 
    5390        8400 :   if (s < -2) pari_err_DOMAIN("nflist", "s", "<", gen_m2, stoi(s));
    5391        8400 :   if (field && !okfield(field)) pari_err_TYPE("nflist", field);
    5392        8400 :   switch(tp)
    5393             :   {
    5394        2310 :     case t_STR: n = grouptranslate(GSTR(GP), &t, QT); break;
    5395        6090 :     case t_VEC: n = group_nTk(GP, &t, QT); break;
    5396             :   }
    5397        8386 :   if (!n)
    5398             :   {
    5399          28 :     const char *s =
    5400             :     "unsupported group (%Ps). Use one of\n\
    5401             :   \"C1\"=[1,1];\n\
    5402             :   \"C2\"=[2,1];\n\
    5403             :   \"C3\"=[3,1], \"S3\"=[3,2];\n\
    5404             :   \"C4\"=[4,1], \"V4\"=[4,2], \"D4\"=[4,3], \"A4\"=[4,4], \"S4\"=[4,5];\n\
    5405             :   \"C5\"=[5,1], \"D5\"=[5,2], \"F5\"=\"M20\"=[5,3], \"A5\"=[5,4];\n\
    5406             :   \"C6\"=[6,1], \"D6\"=[6,2], [6,3], [6,4],..., [6,13];\n\
    5407             :   \"C7\"=[7,1], \"D7\"=[7,2], \"M21\"=[7,3], \"M42\"=[7,4];\n\
    5408             :   \"C9\"=[9,1], [9,2], \"D9\"=[9,3].\"\n\
    5409             :   Also supported are \"Cp\"=[p,1] and \"Dp\"=[p,2] for any odd prime p";
    5410          28 :     pari_err(e_MISC, s, GP);
    5411             :   }
    5412        8358 :   if (QT) return gerepilecopy(av, nflistQT(n, t, varn(N)));
    5413        3465 :   if (s > (n >> 1)) return cgetg(1, t_VEC);
    5414        3430 :   if (!N) return gerepilecopy(av, nfmakesome(n, t, s));
    5415        3262 :   switch(typ(N))
    5416             :   {
    5417        1792 :     case t_INT: X = Xinf = N; break;
    5418        1470 :     case t_VEC: case t_COL:
    5419        1470 :       if (lg(N) == 3) { Xinf = gel(N,1); X = gel(N,2); break; }
    5420           7 :     default: pari_err_TYPE("nflist", N);
    5421             :       Xinf = X = NULL;/*LCOV_EXCL_LINE*/
    5422             :   }
    5423        3255 :   if (typ(X) != t_INT)
    5424             :   {
    5425         126 :     X = gfloor(X);
    5426         126 :     if (typ(X) != t_INT) pari_err_TYPE("nflist", N);
    5427             :   }
    5428        3255 :   if (typ(Xinf) != t_INT)
    5429             :   {
    5430           7 :     Xinf = gceil(Xinf);
    5431           7 :     if (typ(Xinf) != t_INT) pari_err_TYPE("nflist", N);
    5432             :   }
    5433        3255 :   if (signe(Xinf) <= 0)
    5434             :   {
    5435          28 :     if (signe(Xinf) < 0) pari_err_DOMAIN("nflist", "Xinf", "<=", gen_0, Xinf);
    5436          14 :     Xinf = gen_1;
    5437             :   }
    5438        3241 :   if (signe(X) < 0) pari_err_DOMAIN("nflist", "X", "<=", gen_0, X);
    5439        3234 :   switch(cmpii(Xinf, X))
    5440             :   {
    5441          14 :     case 1: v = NULL; break;
    5442        1785 :     case 0: v = nfmakenum(n, t, X, field, s); break;
    5443        1435 :     default: v = nfmakevecnum(n, t, X, Xinf, field, s);
    5444             :   }
    5445        3227 :   if (!v)
    5446             :   {
    5447        1050 :     set_avma(av); if (s != -2) return cgetg(1,t_VEC);
    5448         448 :     retconst_vec((n>>1) + 1, cgetg(1,t_VEC));
    5449             :   }
    5450        2177 :   return gerepilecopy(av, v);
    5451             : }
    5452             : 
    5453             : /*****************************************************************/
    5454             : /*                          Polsubcyclo                          */
    5455             : /*****************************************************************/
    5456             : /* auxiliary functions assume that trivial impossibilities for s or n
    5457             :  * are already handled in caller */
    5458             : static GEN
    5459           0 : polsubcycloC2(GEN n, long s)
    5460             : {
    5461           0 :   GEN V = divisorsdisc(n, s), W;
    5462           0 :   long l = lg(V), i;
    5463           0 :   W = cgetg(l, t_VEC);
    5464           0 :   for (i = 1; i < l; i++) gel(W, i) = quadpoly_i(gel(V, i));
    5465           0 :   return W;
    5466             : }
    5467             : static GEN
    5468           0 : polsubcycloC2_i(GEN n, long s)
    5469             : {
    5470             :   long l, i;
    5471             :   GEN V;
    5472             :   int p, m;
    5473           0 :   if (typ(n) == t_VEC)
    5474             :   {
    5475           0 :     fa_is_fundamental_pm(gel(n,1), gel(n,2), s, &p, &m);
    5476           0 :     n = gel(n,1);
    5477             :   }
    5478             :   else
    5479           0 :     is_fundamental_pm(n, s, &p, &m);
    5480           0 :   if (!(V = fund_pm(n, p, m))) return NULL;
    5481           0 :   l = lg(V);
    5482           0 :   for (i = 1; i < l; i++) gel(V, i) = quadpoly_i(gel(V, i));
    5483           0 :   return V;
    5484             : }
    5485             : 
    5486             : static GEN
    5487           7 : polsubcycloC3_i(GEN n)
    5488           7 : { GEN P; return checkcondC3(n, &P)? makeC3_i(typ(n) == t_VEC? gel(n,1): n, P)
    5489           7 :                                   : NULL; }
    5490             : /* Cyclic cubic subfields of Q(zeta_n). */
    5491             : static GEN
    5492           7 : polsubcycloC3(GEN n)
    5493             : {
    5494             :   long i, l, c;
    5495           7 :   GEN D = divisors_factored(n);
    5496           7 :   l = lg(D);
    5497          14 :   for (i = 2, c = 1; i < l; i++)
    5498             :   {
    5499           7 :     GEN v = polsubcycloC3_i(gel(D,i));
    5500           7 :     if (v) gel(D,c++) = v;
    5501             :   }
    5502           7 :   setlg(D, c); return myshallowconcat1(D);
    5503             : }
    5504             : 
    5505             : static GEN
    5506           7 : makeV4pairssimple(GEN D, GEN P, GEN f)
    5507             : {
    5508           7 :   long l = lg(D), n = l-1, i, j, c;
    5509           7 :   GEN R = cgetg((n-1) * n / 2 + 1, t_VEC);
    5510           7 :   for (i = c = 1; i < n; i++)
    5511             :   {
    5512           0 :     GEN Di = gel(D,i);
    5513           0 :     for (j = i + 1; j < l; j++)
    5514             :     {
    5515           0 :       if (f && !equalii(lcmii(Di, gel(D,j)), f)) continue;
    5516           0 :       gel(R, c++) = polcompositum0(gel(P,i), gel(P,j), 2);
    5517             :     }
    5518             :   }
    5519           7 :   setlg(R,c); return R;
    5520             : }
    5521             : static GEN
    5522          21 : makeV4pairs(GEN D, GEN P, GEN f)
    5523             : {
    5524          21 :   long l = lg(D), n = l-1, i, j, c;
    5525          21 :   GEN V = cgetg(l, t_VEC), R = cgetg((n-1) * n / 2 + 1, t_VEC);
    5526             : 
    5527         168 :   for (i = 1; i < l; i++) gel(V, i) = const_vecsmall(n, 1);
    5528         147 :   for (i = c = 1; i < n; i++)
    5529             :   {
    5530         126 :     GEN C = gel(V,i);
    5531         567 :     for (j = i + 1; j < l; j++)
    5532         441 :       if (C[j])
    5533             :       { /* Di, Dj fundamental discs */
    5534         189 :         GEN d, Di = gel(D,i), Dj = gel(D,j), g = gcdii(Di, Dj);
    5535             :         long k;
    5536         189 :         if (!is_pm1(g)) { Di = diviiexact(Di, g); Dj = diviiexact(Dj, g); }
    5537         189 :         d = mulii(Di, Dj); if (f && !equalii(f, mulii(d, g))) continue;
    5538         126 :         if (Mod4(d) > 1) d = shifti(d, 2);
    5539         126 :         k = vecsearch(D, d, NULL); /* d = coredisc(Di*Dj), j < k */
    5540         126 :         C[k] = gel(V, j)[k] = 0;
    5541         126 :         gel(R, c++) = polcompositum0(gel(P,i), gel(P,j), 2);
    5542             :       }
    5543             :   }
    5544          21 :   setlg(R, c); return R;
    5545             : }
    5546             : static GEN
    5547          28 : polsubcycloV4_i(GEN V, long s, GEN n)
    5548             : {
    5549          28 :   long i, l = lg(V);
    5550          28 :   GEN P = cgetg(l, t_VEC);
    5551          28 :   if (s <= 0) ZV_sort_inplace(V); /* for vecsearch */
    5552         175 :   for (i = 1; i < l; i++) gel(P,i) = quadpoly_i(gel(V,i));
    5553          28 :   return (s <= 0)? makeV4pairs(V, P, n): makeV4pairssimple(V, P, n);
    5554             : }
    5555             : 
    5556             : static GEN
    5557           7 : polsubcycloC5(GEN n)
    5558             : {
    5559           7 :   GEN v, D = divisors_factored(n), T = C5bnf();
    5560           7 :   long i, c, l = lg(D);
    5561          14 :   for (i = 2, c = 1; i < l; i++)
    5562           7 :     if ((v = polsubcycloC5_i(gel(D,i), T))) gel(D,c++) = v;
    5563           7 :   setlg(D, c); return myshallowconcat1(D);
    5564             : }
    5565             : 
    5566             : /* ell odd prime */
    5567             : static GEN
    5568           0 : makeCLall(long ell, GEN F)
    5569             : {
    5570           0 :   GEN D = divisors(F);
    5571           0 :   long i, l = lg(D);
    5572           0 :   for (i = 1; i < l; i++) gel(D,i) = makeCL_f(ell, gel(D,i));
    5573           0 :   return shallowconcat1(D);
    5574             : }
    5575             : 
    5576             : static GEN
    5577           0 : polsubcycloC6(GEN n, long s)
    5578             : {
    5579           0 :   GEN v3 = polsubcycloC3(n), v2, R;
    5580           0 :   long n3 = lg(v3) - 1, n2, i, j, c;
    5581           0 :   if (!n3) return v3;
    5582           0 :   v2 = polsubcycloC2(n, s); n2 = lg(v2) - 1;
    5583           0 :   if (!n2) return NULL;
    5584           0 :   R = cgetg(n2 * n3 + 1, t_VEC);
    5585           0 :   for (i = c = 1; i <= n3; i++)
    5586             :   {
    5587           0 :     GEN p3 = gel(v3, i);
    5588           0 :     for (j = 1; j <= n2; j++)
    5589           0 :       gel(R, c++) = polcompositum0(p3, gel(v2,j), 2);
    5590             :   }
    5591           0 :   return R;
    5592             : }
    5593             : 
    5594             : static GEN
    5595           0 : polsubcycloC6_i(GEN n, long s)
    5596             : {
    5597           0 :   GEN D = divisors_factored(n), R;
    5598           0 :   long l = lg(D), i, j, c, L = 2 * (l-1) * omega(n);
    5599             : 
    5600           0 :   if (typ(n) == t_VEC) n = gel(n,1);
    5601           0 :   R = cgetg(L + 1, t_VEC); c = 1;
    5602           0 :   for (i = 2; i < l; i++)
    5603             :   {
    5604           0 :     GEN d = gel(D, i), V2 = polsubcycloC2_i(d, s);
    5605             :     long l2;
    5606           0 :     if (!V2) continue;
    5607           0 :     l2 = lg(V2);
    5608           0 :     if (typ(d) == t_VEC) d = gel(d,1);
    5609           0 :     for (j = 1; j < l; j++)
    5610             :     {
    5611           0 :       GEN V3, e = gel(D, j);
    5612             :       long l3, i3;
    5613           0 :       if (!equalii(lcmii(d, typ(e) == t_VEC? gel(e,1): e), n)) continue;
    5614           0 :       V3 = polsubcycloC3_i(e); if (!V3) continue;
    5615           0 :       l3 = lg(V3);
    5616           0 :       for (i3 = 1; i3 < l3; i3++)
    5617             :       {
    5618           0 :         GEN p3 = gel(V3, i3);
    5619             :         long i2;
    5620           0 :         for (i2 = 1; i2 < l2; i2++)
    5621           0 :           gel(R, c++) = polcompositum0(p3, gel(V2,i2), 2);
    5622             :       }
    5623             :     }
    5624             :   }
    5625           0 :   setlg(R, c); return R;
    5626             : }
    5627             : 
    5628             : /* fli = 1 for conductor n, else all subfields of Q(zeta_n) */
    5629             : static GEN
    5630         154 : polsubcyclofast_i(GEN n, long ell, long s, long fli)
    5631             : {
    5632         154 :   GEN N, fa = check_arith_pos(n, "polsubcyclofast");
    5633             : 
    5634         154 :   if (fa && typ(n) != t_VEC) n = mkvec2(factorback(fa), fa);
    5635             :   /* n either t_INT or [N, factor(N)] */
    5636         154 :   if (ell <= 0 && ell != -4)
    5637           0 :     pari_err_DOMAIN("polsubcyclofast", "d", "<=", gen_0, stoi(ell));
    5638             :   /* translate wrt r2 for compatibility with nflist functions */
    5639         154 :   if (!s) s = odd(ell)? 0: -1;
    5640          70 :   else if (s == 1) s = 0;
    5641          35 :   else if (s ==-1)
    5642             :   {
    5643          35 :     if (odd(ell)) return NULL;
    5644          35 :     s = labs(ell) >> 1;
    5645             :   }
    5646           0 :   else pari_err_FLAG("polsubcyclo");
    5647         154 :   N = fa? gel(n, 1): n;
    5648         154 :   if (Mod4(N) == 2)
    5649             :   {
    5650           0 :     if (fli) return NULL;
    5651           0 :     N = shifti(N, -1);
    5652           0 :     if (fa)
    5653             :     { /* remove 2^1 */
    5654           0 :       GEN P = vecsplice(gel(fa,1), 1), E = vecsplice(gel(fa,2), 1);
    5655           0 :       n = mkvec2(N, mkmat2(P, E));
    5656             :     }
    5657             :   }
    5658         154 :   if (ell == 1)
    5659             :   {
    5660           0 :     if (fli && !equali1(N)) return NULL;
    5661           0 :     retmkvec(pol_x(0));
    5662             :   }
    5663         154 :   if (equali1(N)) return NULL;
    5664         154 :   if (ell == -4) return polsubcycloV4_i(divisorsdisc(n,s), s, fli? N: NULL);
    5665         126 :   if (ell >= 7) return fli? makeCLall(ell,n): makeCL_f(ell,n);
    5666         105 :   switch(ell)
    5667             :   {
    5668           0 :     case 2: return fli? polsubcycloC2_i(n, s): polsubcycloC2(n, s);
    5669           7 :     case 3: return fli? polsubcycloC3_i(n): polsubcycloC3(n);
    5670          84 :     case 4: return fli? polsubcycloC4_i(n, s, fli, NULL): polsubcycloC4(n, s);
    5671          14 :     case 5: return fli? polsubcycloC5_i(n, NULL): polsubcycloC5(n);
    5672           0 :     case 6: return fli? polsubcycloC6_i(n, s): polsubcycloC6(n, s);
    5673             :   }
    5674             :   return NULL; /* LCOV_EXCL_LINE */
    5675             : }
    5676             : GEN
    5677         154 : polsubcyclofast(GEN n, long ell, long s, long fli)
    5678             : {
    5679         154 :   pari_sp av = avma;
    5680         154 :   GEN v = polsubcyclofast_i(n, ell, s, fli);
    5681         154 :   if (!v) { set_avma(av); return cgetg(1, t_VEC); }
    5682         147 :   return gerepilecopy(av, v);
    5683             : }

Generated by: LCOV version 1.13