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

Generated by: LCOV version 2.0-1