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