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