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