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

Generated by: LCOV version 1.14