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