1 /* $Id: kummer.c 10282 2008-06-09 11:15:00Z kb $
2
3 Copyright (C) 2000 The PARI group.
4
5 This file is part of the PARI/GP package.
6
7 PARI/GP is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation. It is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY WHATSOEVER.
11
12 Check the License for details. You should have received a copy of it, along
13 with the package; see the file 'COPYING'. If not, write to the Free Software
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
15
16 /*******************************************************************/
17 /* */
18 /* KUMMER EXTENSIONS */
19 /* */
20 /*******************************************************************/
21 #include "pari.h"
22 #include "paripriv.h"
23
24 typedef struct {
25 GEN x; /* tau ( Mod(x, nf.pol) ) */
26 GEN zk; /* action of tau on nf.zk (as t_MAT) */
27 } tau_s;
28
29 typedef struct {
30 GEN polnf, invexpoteta1;
31 tau_s *tau;
32 long m;
33 } toK_s;
34
35 static long
prank(GEN cyc,long ell)36 prank(GEN cyc, long ell)
37 {
38 long i;
39 for (i=1; i<lg(cyc); i++)
40 if (smodis(gel(cyc,i),ell)) break;
41 return i-1;
42 }
43
44 /* increment y, which runs through [0,d-1]^(k-1). Return 0 when done. */
45 static int
increment(GEN y,long k,long d)46 increment(GEN y, long k, long d)
47 {
48 long i = k, j;
49 do
50 {
51 if (--i == 0) return 0;
52 y[i]++;
53 } while (y[i] >= d);
54 for (j = i+1; j < k; j++) y[j] = 0;
55 return 1;
56 }
57
58 static int
ok_congruence(GEN X,GEN ell,long lW,GEN vecMsup)59 ok_congruence(GEN X, GEN ell, long lW, GEN vecMsup)
60 {
61 long i, l;
62 if (gcmp0(X)) return 0;
63 l = lg(X);
64 for (i=lW; i<l; i++)
65 if (gcmp0(gel(X,i))) return 0;
66 l = lg(vecMsup);
67 for (i=1; i<l; i++)
68 if (gcmp0(FpM_FpC_mul(gel(vecMsup,i),X, ell))) return 0;
69 return 1;
70 }
71
72 static int
ok_sign(GEN X,GEN msign,GEN arch)73 ok_sign(GEN X, GEN msign, GEN arch)
74 {
75 GEN p1 = F2V_red_ip( gmul(msign, X) );
76 settyp(p1,t_VEC); return gequal(p1, arch);
77 }
78
79 /* REDUCTION MOD ell-TH POWERS */
80
81 static GEN
fix_be(GEN bnfz,GEN be,GEN u)82 fix_be(GEN bnfz, GEN be, GEN u)
83 {
84 GEN nf = checknf(bnfz), fu = gmael(bnfz,8,5);
85 return element_mul(nf, be, factorbackelt(fu, u, nf));
86 }
87
88 static GEN
logarch2arch(GEN x,long r1,long prec)89 logarch2arch(GEN x, long r1, long prec)
90 {
91 long i, lx = lg(x), tx = typ(x);
92 GEN y = cgetg(lx, tx);
93
94 if (tx == t_MAT)
95 {
96 for (i=1; i<lx; i++) gel(y,i) = logarch2arch(gel(x,i), r1, prec);
97 return y;
98 }
99 for (i=1; i<=r1;i++) gel(y,i) = gexp(gel(x,i),prec);
100 for ( ; i<lx; i++) gel(y,i) = gexp(gmul2n(gel(x,i),-1),prec);
101 return y;
102 }
103
104 /* multiply be by ell-th powers of units as to find small L2-norm for new be */
105 static GEN
reducebetanaive(GEN bnfz,GEN be,GEN b,GEN ell)106 reducebetanaive(GEN bnfz, GEN be, GEN b, GEN ell)
107 {
108 long i,k,n,ru,r1, prec = nfgetprec(bnfz);
109 GEN z,p1,p2,nmax,c, nf = checknf(bnfz);
110
111 r1 = nf_get_r1(nf);
112 if (!b)
113 {
114 be = algtobasis_i(nf, be);
115 b = gmul(gmael(nf,5,1), be);
116 }
117 n = max((itos(ell)>>1), 3);
118 z = cgetg(n+1, t_VEC);
119 c = gmul(real_i(gel(bnfz,3)), ell);
120 c = logarch2arch(c, r1, prec); /* = embeddings of fu^ell */
121 c = gprec_w(gnorm(c), DEFAULTPREC);
122 b = gprec_w(gnorm(b), DEFAULTPREC); /* need little precision */
123 gel(z,1) = shallowconcat(c, vecinv(c));
124 for (k=2; k<=n; k++) gel(z,k) = vecmul(gel(z,1), gel(z,k-1));
125 nmax = T2_from_embed_norm(b, r1);
126 ru = lg(c)-1; c = zerovec(ru);
127 for(;;)
128 {
129 GEN B = NULL;
130 long besti = 0, bestk = 0;
131 for (k=1; k<=n; k++)
132 for (i=1; i<=ru; i++)
133 {
134 p1 = vecmul(b, gmael(z,k,i)); p2 = T2_from_embed_norm(p1,r1);
135 if (gcmp(p2,nmax) < 0) { B=p1; nmax=p2; besti=i; bestk = k; continue; }
136 p1 = vecmul(b, gmael(z,k,i+ru)); p2 = T2_from_embed_norm(p1,r1);
137 if (gcmp(p2,nmax) < 0) { B=p1; nmax=p2; besti=i; bestk =-k; }
138 }
139 if (!B) break;
140 b = B; gel(c,besti) = addis(gel(c,besti), bestk);
141 }
142 if (DEBUGLEVEL) fprintferr("naive reduction mod U^l: unit exp. = %Z\n",c);
143 return fix_be(bnfz, be, gmul(ell,c));
144 }
145
146 static GEN
reduce_mod_Qell(GEN bnfz,GEN be,GEN gell)147 reduce_mod_Qell(GEN bnfz, GEN be, GEN gell)
148 {
149 GEN c, fa;
150 be = algtobasis_i(bnfz, be);
151 be = primitive_part(be, &c);
152 if (c)
153 {
154 fa = factor(c);
155 gel(fa,2) = FpC_red(gel(fa,2), gell);
156 c = factorback(fa, NULL);
157 be = gmul(be, c);
158 }
159 return be;
160 }
161
162 /* return q, q^n r = x, v_pr(r) < n for all pr. Insist q is a genuine n-th
163 * root (i.e r = 1) if strict != 0. */
164 GEN
idealsqrtn(GEN nf,GEN x,GEN gn,int strict)165 idealsqrtn(GEN nf, GEN x, GEN gn, int strict)
166 {
167 long i, l, n = itos(gn);
168 GEN fa, q, Ex, Pr;
169
170 fa = idealfactor(nf, x);
171 Pr = gel(fa,1); l = lg(Pr);
172 Ex = gel(fa,2); q = NULL;
173 for (i=1; i<l; i++)
174 {
175 long ex = itos(gel(Ex,i));
176 GEN e = stoi(ex / n);
177 if (strict && ex % n) pari_err(talker,"not an n-th power in idealsqrtn");
178 if (q) q = idealmulpowprime(nf, q, gel(Pr,i), e);
179 else q = idealpow(nf, gel(Pr,i), e);
180 }
181 return q? q: gen_1;
182 }
183
184 static GEN
reducebeta(GEN bnfz,GEN be,GEN ell)185 reducebeta(GEN bnfz, GEN be, GEN ell)
186 {
187 long j,ru, prec = nfgetprec(bnfz);
188 GEN emb,z,u,matunit, nf = checknf(bnfz);
189
190 if (DEBUGLEVEL>1) fprintferr("reducing beta = %Z\n",be);
191 /* reduce mod Q^ell */
192 be = reduce_mod_Qell(nf, be, ell);
193 /* reduce l-th root */
194 z = idealsqrtn(nf, be, ell, 0);
195 if (typ(z) == t_MAT && !gcmp1(gcoeff(z,1,1)))
196 {
197 z = idealred_elt(nf, z);
198 be = element_div(nf, be, element_pow(nf, z, ell));
199 /* make be integral */
200 be = reduce_mod_Qell(nf, be, ell);
201 }
202 if (DEBUGLEVEL>1) fprintferr("beta reduced via ell-th root = %Z\n",be);
203
204 matunit = gmul(real_i(gel(bnfz,3)), ell); /* log. embeddings of fu^ell */
205 for (;;)
206 {
207 z = get_arch_real(nf, be, &emb, prec);
208 if (z) break;
209 prec = (prec-1)<<1;
210 if (DEBUGLEVEL) pari_warn(warnprec,"reducebeta",prec);
211 nf = nfnewprec(nf,prec);
212 }
213 z = shallowconcat(matunit, z);
214 u = lllintern(z, 100, 1, prec);
215 if (u)
216 {
217 ru = lg(u);
218 for (j=1; j < ru; j++)
219 if (gcmp1(gcoeff(u,ru-1,j))) break;
220 if (j < ru)
221 {
222 u = gel(u,j); /* coords on (fu^ell, be) of a small generator */
223 ru--; setlg(u, ru);
224 be = fix_be(bnfz, be, gmul(ell,u));
225 }
226 }
227 if (DEBUGLEVEL>1) fprintferr("beta LLL-reduced mod U^l = %Z\n",be);
228 return reducebetanaive(bnfz, be, NULL, ell);
229 }
230
231 static GEN
tauofalg(GEN x,GEN U)232 tauofalg(GEN x, GEN U) {
233 return gsubst(lift(x), varn(U[1]), U);
234 }
235
236 static tau_s *
get_tau(tau_s * tau,GEN nf,GEN U)237 get_tau(tau_s *tau, GEN nf, GEN U)
238 {
239 GEN bas = gel(nf,7), Uzk;
240 long i, l = lg(bas);
241 Uzk = cgetg(l, t_MAT);
242 for (i=1; i<l; i++)
243 gel(Uzk,i) = algtobasis(nf, tauofalg(gel(bas,i), U));
244 tau->zk = Uzk;
245 tau->x = U; return tau;
246 }
247
248 static GEN tauoffamat(GEN x, tau_s *tau);
249
250 static GEN
tauofelt(GEN x,tau_s * tau)251 tauofelt(GEN x, tau_s *tau)
252 {
253 switch(typ(x))
254 {
255 case t_COL: return gmul(tau->zk, x);
256 case t_MAT: return tauoffamat(x, tau);
257 default: return tauofalg(x, tau->x);
258 }
259 }
260 static GEN
tauofvec(GEN x,tau_s * tau)261 tauofvec(GEN x, tau_s *tau)
262 {
263 long i, l = lg(x);
264 GEN y = cgetg(l, typ(x));
265
266 for (i=1; i<l; i++) gel(y,i) = tauofelt(gel(x,i), tau);
267 return y;
268 }
269 /* [x, tau(x), ..., tau^m(x)] */
270 static GEN
powtau(GEN x,long m,tau_s * tau)271 powtau(GEN x, long m, tau_s *tau)
272 {
273 GEN y = cgetg(m+1, t_VEC);
274 long i;
275 gel(y,1) = x;
276 for (i=2; i<=m; i++) gel(y,i) = tauofelt(gel(y,i-1), tau);
277 return y;
278 }
279
280 static GEN
tauoffamat(GEN x,tau_s * tau)281 tauoffamat(GEN x, tau_s *tau)
282 {
283 return mkmat2(tauofvec(gel(x,1), tau), gel(x,2));
284 }
285
286 static GEN
tauofideal(GEN nfz,GEN id,tau_s * tau)287 tauofideal(GEN nfz, GEN id, tau_s *tau)
288 {
289 return hnfmodid(gmul(tau->zk, id), gcoeff(id, 1,1));
290 }
291
292 static int
isprimeidealconj(GEN nfz,GEN pr1,GEN pr2,tau_s * tau)293 isprimeidealconj(GEN nfz, GEN pr1, GEN pr2, tau_s *tau)
294 {
295 GEN p = gel(pr1,1);
296 GEN x = gel(pr1,2);
297 GEN b1= gel(pr1,5);
298 GEN b2= gel(pr2,5);
299 if (!equalii(p, gel(pr2,1))
300 || !equalii(gel(pr1,3), gel(pr2,3))
301 || !equalii(gel(pr1,4), gel(pr2,4))) return 0;
302 if (gequal(x,gel(pr2,2))) return 1;
303 for(;;)
304 {
305 if (int_elt_val(nfz,x,p,b2,NULL)) return 1;
306 x = FpC_red(tauofelt(x, tau), p);
307 if (int_elt_val(nfz,x,p,b1,NULL)) return 0;
308 }
309 }
310
311 static int
isconjinprimelist(GEN nfz,GEN S,GEN pr,tau_s * tau)312 isconjinprimelist(GEN nfz, GEN S, GEN pr, tau_s *tau)
313 {
314 long i, l;
315
316 if (!tau) return 0;
317 l = lg(S);
318 for (i=1; i<l; i++)
319 if (isprimeidealconj(nfz, gel(S,i),pr,tau)) return 1;
320 return 0;
321 }
322
323 /* assume x in basistoalg form */
324 static GEN
downtoK(toK_s * T,GEN x)325 downtoK(toK_s *T, GEN x)
326 {
327 long degKz = lg(T->invexpoteta1) - 1;
328 GEN y = gmul(T->invexpoteta1, RgX_to_RgV(lift_intern(x), degKz));
329 return gmodulo(gtopolyrev(y,varn(T->polnf)), T->polnf);
330 }
331
332 static GEN
no_sol(long all,long i)333 no_sol(long all, long i)
334 {
335 if (!all) pari_err(talker,"bug%d in kummer",i);
336 return cgetg(1,t_VEC);
337 }
338
339 static GEN
get_gell(GEN bnr,GEN subgp,long all)340 get_gell(GEN bnr, GEN subgp, long all)
341 {
342 GEN gell;
343 if (all) gell = stoi(all);
344 else if (subgp) gell = det(subgp);
345 else gell = det(diagonal_i(gmael(bnr,5,2)));
346 if (typ(gell) != t_INT) pari_err(arither1);
347 return gell;
348 }
349
350 typedef struct {
351 GEN Sm, Sml1, Sml2, Sl, ESml2;
352 } primlist;
353
354 static int
build_list_Hecke(primlist * L,GEN nfz,GEN fa,GEN gothf,GEN gell,tau_s * tau)355 build_list_Hecke(primlist *L, GEN nfz, GEN fa, GEN gothf, GEN gell, tau_s *tau)
356 {
357 GEN listpr, listex, pr, p, factell;
358 long vd, vp, e, i, l, ell = itos(gell), degKz = degpol(nfz[1]);
359
360 if (!fa) fa = idealfactor(nfz, gothf);
361 listpr = gel(fa,1);
362 listex = gel(fa,2); l = lg(listpr);
363 L->Sm = cget1(l,t_VEC);
364 L->Sml1= cget1(l,t_VEC);
365 L->Sml2= cget1(l,t_VEC);
366 L->Sl = cget1(l+degKz,t_VEC);
367 L->ESml2=cget1(l,t_VECSMALL);
368 for (i=1; i<l; i++)
369 {
370 pr = gel(listpr,i); p = gel(pr,1); e = itos(gel(pr,3));
371 vp = itos(gel(listex,i));
372 if (!equalii(p,gell))
373 {
374 if (vp != 1) return 1;
375 if (!isconjinprimelist(nfz, L->Sm,pr,tau)) appendL(L->Sm,pr);
376 }
377 else
378 {
379 vd = (vp-1)*(ell-1)-ell*e;
380 if (vd > 0) return 4;
381 if (vd==0)
382 {
383 if (!isconjinprimelist(nfz, L->Sml1,pr,tau)) appendL(L->Sml1, pr);
384 }
385 else
386 {
387 if (vp==1) return 2;
388 if (!isconjinprimelist(nfz, L->Sml2,pr,tau))
389 {
390 appendL(L->Sml2, pr);
391 appendL(L->ESml2,(GEN)vp);
392 }
393 }
394 }
395 }
396 factell = primedec(nfz,gell); l = lg(factell);
397 for (i=1; i<l; i++)
398 {
399 pr = gel(factell,i);
400 if (!idealval(nfz,gothf,pr))
401 if (!isconjinprimelist(nfz, L->Sl,pr,tau)) appendL(L->Sl, pr);
402 }
403 return 0; /* OK */
404 }
405
406 static GEN
logall(GEN nf,GEN vec,long lW,long mginv,long ell,GEN pr,long ex)407 logall(GEN nf, GEN vec, long lW, long mginv, long ell, GEN pr, long ex)
408 {
409 GEN m, M, bid = zidealstarinitgen(nf, idealpows(nf, pr, ex));
410 long ellrank, i, l = lg(vec);
411
412 ellrank = prank(gmael(bid,2,2), ell);
413 M = cgetg(l,t_MAT);
414 for (i=1; i<l; i++)
415 {
416 m = zideallog(nf, gel(vec,i), bid);
417 setlg(m, ellrank+1);
418 if (i < lW) m = gmulsg(mginv, m);
419 gel(M,i) = m;
420 }
421 return M;
422 }
423
424 /* compute the u_j (see remark 5.2.15.) */
425 static GEN
get_u(GEN cyc,long rc,GEN gell)426 get_u(GEN cyc, long rc, GEN gell)
427 {
428 long i, l = lg(cyc);
429 GEN u = cgetg(l,t_VEC);
430 for (i=1; i<=rc; i++) gel(u,i) = gen_0;
431 for ( ; i< l; i++) gel(u,i) = Fp_inv(gel(cyc,i), gell);
432 return u;
433 }
434
435 /* alg. 5.2.15. with remark */
436 static GEN
isprincipalell(GEN bnfz,GEN id,GEN cycgen,GEN u,GEN gell,long rc)437 isprincipalell(GEN bnfz, GEN id, GEN cycgen, GEN u, GEN gell, long rc)
438 {
439 long i, l = lg(cycgen);
440 GEN logdisc, b, y = quick_isprincipalgen(bnfz, id);
441
442 logdisc = FpC_red(gel(y,1), gell);
443 b = gel(y,2);
444 for (i=rc+1; i<l; i++)
445 {
446 GEN e = modii(mulii(gel(logdisc,i),gel(u,i)), gell);
447 if (signe(e)) b = famat_mul(b, famat_pow(gel(cycgen,i), e));
448 }
449 setlg(logdisc,rc+1); return mkvec2(logdisc, b);
450 }
451
452 static GEN
famat_factorback(GEN v,GEN e)453 famat_factorback(GEN v, GEN e)
454 {
455 long i, l = lg(e);
456 GEN V = cgetg(1, t_MAT);
457 for (i=1; i<l; i++)
458 if (signe(e[i])) V = famat_mul(V, famat_pow(gel(v,i), gel(e,i)));
459 return V;
460 }
461
462 static GEN
compute_beta(GEN X,GEN vecWB,GEN ell,GEN bnfz)463 compute_beta(GEN X, GEN vecWB, GEN ell, GEN bnfz)
464 {
465 GEN BE, be;
466 BE = famat_reduce(famat_factorback(vecWB, X));
467 gel(BE,2) = centermod(gel(BE,2), ell);
468 be = factorbackelt(BE, bnfz, NULL);
469 be = reducebeta(bnfz, be, ell);
470 if (DEBUGLEVEL>1) fprintferr("beta reduced = %Z\n",be);
471 return be;
472 }
473
474 static GEN
get_Selmer(GEN bnf,GEN cycgen,long rc)475 get_Selmer(GEN bnf, GEN cycgen, long rc)
476 {
477 GEN fu = check_units(bnf,"rnfkummer");
478 GEN tu = gmael3(bnf,8,4,2);
479 return shallowconcat(algtobasis(bnf,shallowconcat(fu,tu)), vecslice(cycgen,1,rc));
480 }
481
482
483 GEN
lift_if_rational(GEN x)484 lift_if_rational(GEN x)
485 {
486 long lx, i;
487 GEN y;
488
489 switch(typ(x))
490 {
491 default: break;
492
493 case t_POLMOD:
494 y = gel(x,2);
495 if (typ(y) == t_POL)
496 {
497 long d = degpol(y);
498 if (d > 0) return x;
499 return (d < 0)? gen_0: gel(y,2);
500 }
501 return y;
502
503 case t_POL: lx = lg(x);
504 for (i=2; i<lx; i++) gel(x,i) = lift_if_rational(gel(x,i));
505 break;
506 case t_VEC: case t_COL: case t_MAT: lx = lg(x);
507 for (i=1; i<lx; i++) gel(x,i) = lift_if_rational(gel(x,i));
508 }
509 return x;
510 }
511
512
513 /* if all!=0, give all equations of degree 'all'. Assume bnr modulus is the
514 * conductor */
515 static GEN
rnfkummersimple(GEN bnr,GEN subgroup,GEN gell,long all)516 rnfkummersimple(GEN bnr, GEN subgroup, GEN gell, long all)
517 {
518 long ell, i, j, degK, dK;
519 long lSml2, lSl2, lSp, rc, lW;
520 long prec;
521
522 GEN bnf,nf,bid,ideal,arch,cycgen;
523 GEN clgp,cyc;
524 GEN Sp,listprSp,matP;
525 GEN res,u,M,K,y,vecMsup,vecW,vecWB,vecBp,msign;
526 primlist L;
527
528 bnf = gel(bnr,1);
529 nf = gel(bnf,7);
530 degK = degpol(nf[1]);
531
532 bid = gel(bnr,2);
533 ideal= gmael(bid,1,1);
534 arch = gmael(bid,1,2); /* this is the conductor */
535 ell = itos(gell);
536 i = build_list_Hecke(&L, nf, gel(bid,3), ideal, gell, NULL);
537 if (i) return no_sol(all,i);
538
539 lSml2 = lg(L.Sml2)-1;
540 Sp = shallowconcat(L.Sm, L.Sml1); lSp = lg(Sp)-1;
541 listprSp = shallowconcat(L.Sml2, L.Sl); lSl2 = lg(listprSp)-1;
542
543 cycgen = check_and_build_cycgen(bnf);
544 clgp = gmael(bnf,8,1);
545 cyc = gel(clgp,2); rc = prank(cyc, ell);
546
547 vecW = get_Selmer(bnf, cycgen, rc);
548 u = get_u(cyc, rc, gell);
549
550 vecBp = cgetg(lSp+1, t_VEC);
551 matP = cgetg(lSp+1, t_MAT);
552 for (j=1; j<=lSp; j++)
553 {
554 GEN e, a, L;
555 L = isprincipalell(bnf,gel(Sp,j), cycgen,u,gell,rc);
556 e = gel(L,1); gel(matP,j) = e;
557 a = gel(L,2); gel(vecBp,j) = a;
558 }
559 vecWB = shallowconcat(vecW, vecBp);
560
561 prec = DEFAULTPREC +
562 nbits2nlong(((degK-1) * (gexpo(vecWB) + gexpo(gmael(nf,5,1)))));
563 if (nfgetprec(nf) < prec) nf = nfnewprec(nf, prec);
564 msign = zsigns(nf, vecWB);
565
566 vecMsup = cgetg(lSml2+1,t_VEC);
567 M = NULL;
568 for (i=1; i<=lSl2; i++)
569 {
570 GEN pr = gel(listprSp,i);
571 long e = itos(gel(pr,3)), z = ell * (e / (ell-1));
572
573 if (i <= lSml2)
574 {
575 z += 1 - L.ESml2[i];
576 gel(vecMsup,i) = logall(nf, vecWB, 0,0, ell, pr,z+1);
577 }
578 M = vconcat(M, logall(nf, vecWB, 0,0, ell, pr,z));
579 }
580 lW = lg(vecW);
581 M = vconcat(M, shallowconcat(zeromat(rc,lW-1), matP));
582
583 K = FpM_ker(M, gell);
584 dK = lg(K)-1;
585 y = cgetg(dK+1,t_VECSMALL);
586 res = cgetg(1,t_VEC); /* in case all = 1 */
587 while (dK)
588 {
589 for (i=1; i<dK; i++) y[i] = 0;
590 y[i] = 1; /* y = [0,...,0,1,0,...,0], 1 at dK'th position */
591 do
592 {
593 pari_sp av = avma;
594 GEN be, P, X = FpC_red(ZM_zc_mul(K, y), gell);
595 if (ok_congruence(X, gell, lW, vecMsup) && ok_sign(X, msign, arch))
596 {/* be satisfies all congruences, x^ell - be is irreducible, signature
597 * and relative discriminant are correct */
598 be = compute_beta(X, vecWB, gell, bnf);
599 be = lift_if_rational(coltoalg(nf, be));
600 P = gsub(monomial(gen_1, ell, 0), be);
601 if (all) res = shallowconcat(res, gerepileupto(av, P));
602 else
603 {
604 if (gequal(rnfnormgroup(bnr,P),subgroup)) return P; /*DONE*/
605 avma = av;
606 }
607 }
608 else avma = av;
609 } while (increment(y, dK, ell));
610 y[dK--] = 0;
611 }
612 if (all) return res;
613 return gen_0;
614 }
615
616 /* alg. 5.3.11 (return only discrete log mod ell) */
617 static GEN
isvirtualunit(GEN bnf,GEN v,GEN cycgen,GEN cyc,GEN gell,long rc)618 isvirtualunit(GEN bnf, GEN v, GEN cycgen, GEN cyc, GEN gell, long rc)
619 {
620 GEN L, b, eps, y, q, nf = checknf(bnf);
621 long i, l = lg(cycgen);
622
623 L = quick_isprincipalgen(bnf, idealsqrtn(nf, v, gell, 1));
624 q = gel(L,1);
625 if (gcmp0(q)) { eps = v; y = q; }
626 else
627 {
628 b = gel(L,2);
629 y = cgetg(l,t_COL);
630 for (i=1; i<l; i++)
631 gel(y,i) = diviiexact(mulii(gell,gel(q,i)), gel(cyc,i));
632 eps = famat_mul(famat_factorback(cycgen, y), famat_pow(b, gell));
633 eps = famat_mul(famat_inv(eps), v);
634 }
635 setlg(y, rc+1);
636 b = isunit(bnf,eps);
637 if (lg(b) == 1) pari_err(bugparier,"isvirtualunit");
638 return shallowconcat(lift_intern(b), y);
639 }
640
641 /* J a vector of elements in nfz = relative extension of nf by polrel,
642 * return the Steinitz element associated to the module generated by J */
643 static GEN
Stelt(GEN nf,GEN J,GEN polrel)644 Stelt(GEN nf, GEN J, GEN polrel)
645 {
646 long i, l = lg(J);
647 GEN x, A, I, id = matid(degpol(nf[1]));
648
649 A = cgetg(l, t_VEC);
650 I = cgetg(l, t_VEC);
651 for (i = 1; i < l; i++)
652 {
653 GEN v = gel(J,i);
654 gel(A,i) = (typ(v) != t_POL)? v: RgX_rem(v, polrel);
655 gel(I,i) = id;
656 }
657 x = cgetg(3,t_VEC);
658 gel(x,1) = RgXV_to_RgM(A, degpol(polrel));
659 gel(x,2) = I;
660 return prodid(nf, (GEN)nfhermite(nf,x)[2]);
661 }
662
663 static GEN
polrelKzK(toK_s * T,GEN x)664 polrelKzK(toK_s *T, GEN x)
665 {
666 GEN P = roots_to_pol(powtau(x, T->m, T->tau), 0);
667 long i, l = lg(P);
668 for (i=2; i<l; i++) gel(P,i) = downtoK(T, gel(P,i));
669 return P;
670 }
671
672 /* N: Cl_m(Kz) --> Cl_m(K), lift subgroup from bnr to bnrz using Algo 4.1.11 */
673 static GEN
invimsubgroup(GEN bnrz,GEN bnr,GEN subgroup,toK_s * T)674 invimsubgroup(GEN bnrz, GEN bnr, GEN subgroup, toK_s *T)
675 {
676 long l, j;
677 GEN P,raycycz,rayclgpz,raygenz,U,polrel,StZk;
678 GEN nf = checknf(bnr), nfz = checknf(bnrz), polz = gel(nfz,1);
679
680 polrel = polrelKzK(T, pol_x[varn(polz)]);
681 StZk = Stelt(nf, gel(nfz,7), polrel);
682 rayclgpz = gel(bnrz,5);
683 raycycz = gel(rayclgpz,2); l = lg(raycycz);
684 raygenz = gel(rayclgpz,3);
685 P = cgetg(l,t_MAT);
686 for (j=1; j<l; j++)
687 {
688 GEN g, id = idealhermite(nfz, gel(raygenz,j));
689 g = Stelt(nf, gmul(gel(nfz,7), id), polrel);
690 g = idealdiv(nf, g, StZk); /* N_{Kz/K}(gen[j]) */
691 gel(P,j) = isprincipalray(bnr, g);
692 }
693 (void)hnfall_i(shallowconcat(P, subgroup), &U, 1);
694 setlg(U, l); for (j=1; j<l; j++) setlg(U[j], l);
695 return hnfmodid(shallowconcat(U, diagonal_i(raycycz)), gel(raycycz,1));
696 }
697
698 static GEN
pol_from_Newton(GEN S)699 pol_from_Newton(GEN S)
700 {
701 long i, k, l = lg(S);
702 GEN C = cgetg(l+1, t_VEC), c = C + 1;
703 gel(c,0) = gen_1;
704 c[1] = S[1];
705 for (k = 2; k < l; k++)
706 {
707 GEN s = gel(S,k);
708 for (i = 1; i < k; i++) s = gadd(s, gmul(gel(S,i), gel(c,k-i)));
709 gel(c,k) = gdivgs(s, -k);
710 }
711 return gtopoly(C, 0);
712 }
713
714 /* - mu_b = sum_{0 <= i < m} floor(r_b r_{d-1-i} / ell) tau^i */
715 static GEN
get_mmu(long b,GEN r,long ell)716 get_mmu(long b, GEN r, long ell)
717 {
718 long i, m = lg(r)-1;
719 GEN M = cgetg(m+1, t_VEC);
720 for (i = 0; i < m; i++) gel(M,i+1) = stoi((r[b + 1] * r[m - i]) / ell);
721 return M;
722 }
723 /* theta^ell = be ^ ( sum tau^a r_{d-1-a} ) */
724 static GEN
get_reverse(GEN r)725 get_reverse(GEN r)
726 {
727 long i, m = lg(r)-1;
728 GEN M = cgetg(m+1, t_VEC);
729 for (i = 0; i < m; i++) gel(M,i+1) = stoi(r[m - i]);
730 return M;
731 }
732
733 /* coeffs(x, a..b) in variable v >= varn(x) */
734 static GEN
split_pol(GEN x,long v,long a,long b)735 split_pol(GEN x, long v, long a, long b)
736 {
737 long i, l = degpol(x);
738 GEN y = x + a, z;
739
740 if (l < b) b = l;
741 if (a > b || varn(x) != v) return zeropol(v);
742 l = b-a + 3;
743 z = cgetg(l, t_POL); z[1] = x[1];
744 for (i = 2; i < l; i++) z[i] = y[i];
745 return normalizepol_i(z, l);
746 }
747
748 /* return (den_a * z) mod (v^ell - num_a/den_a), assuming deg(z) < 2*ell
749 * allow either num/den to be NULL (= 1) */
750 static GEN
mod_Xell_a(GEN z,long v,long ell,GEN num_a,GEN den_a)751 mod_Xell_a(GEN z, long v, long ell, GEN num_a, GEN den_a)
752 {
753 GEN z1 = split_pol(z, v, ell, degpol(z));
754 GEN z0 = split_pol(z, v, 0, ell-1); /* z = v^ell z1 + z0*/
755 if (den_a) z0 = gmul(den_a, z0);
756 if (num_a) z1 = gmul(num_a, z1);
757 return gadd(z0, z1);
758 }
759 static GEN
to_alg(GEN nfz,GEN v)760 to_alg(GEN nfz, GEN v)
761 {
762 GEN z;
763 if (typ(v) != t_COL) return v;
764 z = gmul(gel(nfz,7), v);
765 if (typ(z) == t_POL) setvarn(z, MAXVARN);
766 return z;
767 }
768
769 /* th. 5.3.5. and prop. 5.3.9. */
770 static GEN
compute_polrel(GEN nfz,toK_s * T,GEN be,long g,long ell)771 compute_polrel(GEN nfz, toK_s *T, GEN be, long g, long ell)
772 {
773 long i, k, m = T->m, vT = fetch_var();
774 GEN r, powtaubet, S, p1, root, num_t, den_t, nfzpol, powtau_prim_invbe;
775 GEN prim_Rk, C_Rk, prim_root, C_root, prim_invbe, C_invbe;
776 pari_timer ti;
777
778 r = cgetg(m+1,t_VECSMALL); /* r[i+1] = g^i mod ell */
779 r[1] = 1;
780 for (i=2; i<=m; i++) r[i] = (r[i-1] * g) % ell;
781 powtaubet = powtau(be, m, T->tau);
782 if (DEBUGLEVEL>1) { fprintferr("Computing Newton sums: "); TIMERstart(&ti); }
783 prim_invbe = Q_primitive_part(element_inv(nfz, be), &C_invbe);
784 powtau_prim_invbe = powtau(prim_invbe, m, T->tau);
785
786 root = cgetg(ell + 2, t_POL);
787 root[1] = evalsigne(1) | evalvarn(0);
788 for (i = 0; i < ell; i++) gel(root,2+i) = gen_0;
789 for (i = 0; i < m; i++)
790 { /* compute (1/be) ^ (-mu) instead of be^mu [mu << 0].
791 * 1/be = C_invbe * prim_invbe */
792 GEN mmu = get_mmu(i, r, ell);
793 /* p1 = prim_invbe ^ -mu */
794 p1 = to_alg(nfz, factorbackelt(powtau_prim_invbe, mmu, nfz));
795 if (C_invbe) p1 = gmul(p1, powgi(C_invbe, sum(mmu,1,m)));
796 /* root += zeta_ell^{r_i} T^{r_i} be^mu_i */
797 gel(root, 2 + r[i+1]) = monomial(p1, r[i+1], vT);
798 }
799 /* Other roots are as above with z_ell --> z_ell^j.
800 * Treat all contents (C_*) and principal parts (prim_*) separately */
801 prim_Rk = prim_root = Q_primitive_part(root, &C_root);
802 C_Rk = C_root;
803
804 /* Compute modulo X^ell - 1, T^ell - t, nfzpol(MAXVARN) */
805 p1 = to_alg(nfz, factorbackelt(powtaubet, get_reverse(r), nfz));
806 num_t = Q_remove_denom(p1, &den_t);
807
808 nfzpol = shallowcopy(gel(nfz,1));
809 setvarn(nfzpol, MAXVARN);
810 S = cgetg(ell+1, t_VEC); /* Newton sums */
811 gel(S,1) = gen_0;
812 for (k = 2; k <= ell; k++)
813 { /* compute the k-th Newton sum */
814 pari_sp av = avma;
815 GEN z, D, Rk = gmul(prim_Rk, prim_root);
816 C_Rk = mul_content(C_Rk, C_root);
817 Rk = mod_Xell_a(Rk, 0, ell, NULL, NULL); /* mod X^ell - 1 */
818 for (i = 2; i < lg(Rk); i++)
819 {
820 z = mod_Xell_a(gel(Rk,i), vT, ell, num_t,den_t); /* mod T^ell - t */
821 gel(Rk,i) = RgXQX_red(z, nfzpol); /* mod nfz.pol */
822 }
823 if (den_t) C_Rk = mul_content(C_Rk, ginv(den_t));
824 prim_Rk = Q_primitive_part(Rk, &D);
825 C_Rk = mul_content(C_Rk, D); /* root^k = prim_Rk * C_Rk */
826
827 /* Newton sum is ell * constant coeff (in X), which has degree 0 in T */
828 z = polcoeff_i(prim_Rk, 0, 0);
829 z = polcoeff_i(z , 0,vT);
830 z = downtoK(T, gmulgs(z, ell));
831 if (C_Rk) z = gmul(z, C_Rk);
832 gerepileall(av, C_Rk? 3: 2, &z, &prim_Rk, &C_Rk);
833 if (DEBUGLEVEL>1) { fprintferr("%ld(%ld) ", k, TIMER(&ti)); flusherr(); }
834 gel(S,k) = z;
835 }
836 if (DEBUGLEVEL>1) fprintferr("\n");
837 (void)delete_var(); return pol_from_Newton(S);
838 }
839
840 typedef struct {
841 GEN R; /* compositum(P,Q) */
842 GEN p; /* Mod(p,R) root of P */
843 GEN q; /* Mod(q,R) root of Q */
844 GEN k; /* Q[X]/R generated by q + k p */
845 GEN rev;
846 } compo_s;
847
848 static GEN
lifttoKz(GEN nfz,GEN nf,GEN id,compo_s * C)849 lifttoKz(GEN nfz, GEN nf, GEN id, compo_s *C)
850 {
851 GEN I = ideal_two_elt(nf,id);
852 GEN x = coltoliftalg(nf, gel(I,2));
853 gel(I,2) = algtobasis(nfz, RgX_RgXQ_compo(x, C->p, C->R));
854 return prime_to_ideal(nfz,I);
855 }
856
857 static void
compositum_red(compo_s * C,GEN P,GEN Q)858 compositum_red(compo_s *C, GEN P, GEN Q)
859 {
860 GEN p, q, a, z = (GEN)compositum2(P, Q)[1];
861 long v;
862 a = gel(z,1); v = varn(a);
863 p = lift_intern(gel(z,2));
864 q = lift_intern(gel(z,3));
865 C->k = gel(z,4);
866 /* reduce R */
867 z = polredabs0(a, nf_ORIG|nf_PARTIALFACT);
868 C->R = gel(z,1);
869 a = gel(z,2);
870 C->p = poleval(p, a);
871 if (C->p == gen_0) C->p = mkpolmod(zeropol(v),gel(a,1));
872 C->q = poleval(q, a);
873 C->rev = modreverse_i(gel(a,2), gel(a,1));
874 if (DEBUGLEVEL>1) fprintferr("polred(compositum) = %Z\n",C->R);
875 }
876
877 static GEN
_rnfkummer(GEN bnr,GEN subgroup,long all,long prec)878 _rnfkummer(GEN bnr, GEN subgroup, long all, long prec)
879 {
880 long ell, i, j, m, d, dK, dc, rc, ru, rv, g, mginv, degK, degKz, vnf;
881 long lSp, lSml2, lSl2, lW;
882 GEN polnf,bnf,nf,bnfz,nfz,bid,ideal,cycgen,gell,p1,p2,wk,U,vselmer;
883 GEN clgp,cyc,gen;
884 GEN Q,idealz,gothf;
885 GEN res,u,M,K,y,vecMsup,vecW,vecWA,vecWB,vecB,vecC,vecAp,vecBp;
886 GEN matP,Sp,listprSp,Tc,Tv,P;
887 primlist L;
888 toK_s T;
889 tau_s _tau, *tau;
890 compo_s COMPO;
891 pari_timer t;
892
893 if (DEBUGLEVEL) TIMERstart(&t);
894 checkbnrgen(bnr);
895 bnf = gel(bnr,1);
896 nf = gel(bnf,7);
897 polnf = gel(nf,1); vnf = varn(polnf);
898 if (!vnf) pari_err(talker,"main variable in kummer must not be x");
899 wk = gmael3(bnf,8,4,1);
900 /* step 7 */
901 p1 = conductor(bnr, subgroup, 2);
902 if (DEBUGLEVEL) msgTIMER(&t, "[rnfkummer] conductor");
903 bnr = gel(p1,2);
904 subgroup = gel(p1,3);
905 gell = get_gell(bnr,subgroup,all);
906 ell = itos(gell);
907 if (ell == 1) return pol_x[vnf];
908 if (!uisprime(ell)) pari_err(impl,"kummer for composite relative degree");
909 if (!umodiu(wk,ell)) return rnfkummersimple(bnr, subgroup, gell, all);
910
911 bid = gel(bnr,2);
912 ideal = gmael(bid,1,1);
913 /* step 1 of alg 5.3.5. */
914 if (DEBUGLEVEL>2) fprintferr("Step 1\n");
915 compositum_red(&COMPO, polnf, cyclo(ell,vnf));
916 /* step 2 */
917 if (DEBUGLEVEL>2) fprintferr("Step 2\n");
918 if (DEBUGLEVEL) msgTIMER(&t, "[rnfkummer] compositum");
919 degK = degpol(polnf);
920 degKz = degpol(COMPO.R);
921 m = degKz / degK;
922 d = (ell-1) / m;
923 g = (long)Fl_pow(gener_Fl(ell), d, ell);
924 if (Fl_pow((ulong)g, m, ell*ell) == 1) g += ell;
925 /* ord(g) = m in all (Z/ell^k)^* */
926 /* step 3 */
927 if (DEBUGLEVEL>2) fprintferr("Step 3\n");
928 /* could factor disc(R) using th. 2.1.6. */
929 bnfz = bnfinit0(COMPO.R,1,NULL,prec);
930 if (DEBUGLEVEL) msgTIMER(&t, "[rnfkummer] bnfinit(Kz)");
931 cycgen = check_and_build_cycgen(bnfz);
932 nfz = gel(bnfz,7);
933 clgp = gmael(bnfz,8,1);
934 cyc = gel(clgp,2); rc = prank(cyc,ell);
935 gen = gel(clgp,3);
936 u = get_u(cyc, rc, gell);
937
938 vselmer = get_Selmer(bnfz, cycgen, rc);
939 if (DEBUGLEVEL) msgTIMER(&t, "[rnfkummer] Selmer group");
940 ru = (degKz>>1)-1;
941 rv = rc+ru+1;
942
943 /* compute action of tau */
944 U = gadd(gpowgs(COMPO.q, g), gmul(COMPO.k, COMPO.p));
945 U = poleval(COMPO.rev, U);
946 tau = get_tau(&_tau, nfz, U);
947
948 /* step 4 */
949 if (DEBUGLEVEL>2) fprintferr("Step 4\n");
950 vecB=cgetg(rc+1,t_VEC);
951 Tc=cgetg(rc+1,t_MAT);
952 for (j=1; j<=rc; j++)
953 {
954 p1 = tauofideal(nfz, gel(gen,j), tau);
955 p1 = isprincipalell(bnfz, p1, cycgen,u,gell,rc);
956 Tc[j] = p1[1];
957 vecB[j]= p1[2];
958 }
959
960 vecC = cgetg(rc+1,t_VEC);
961 if (rc)
962 {
963 for (j=1; j<=rc; j++) gel(vecC,j) = cgetg(1, t_MAT);
964 p1 = cgetg(m,t_VEC);
965 gel(p1,1) = matid(rc);
966 for (j=2; j<=m-1; j++) gel(p1,j) = gmul(gel(p1,j-1),Tc);
967 p2 = vecB;
968 for (j=1; j<=m-1; j++)
969 {
970 GEN z = FpM_red(gmulsg((j*d)%ell,gel(p1,m-j)), gell);
971 p2 = tauofvec(p2, tau);
972 for (i=1; i<=rc; i++)
973 gel(vecC,i) = famat_mul(gel(vecC,i), famat_factorback(p2,gel(z,i)));
974 }
975 for (i=1; i<=rc; i++) gel(vecC,i) = famat_reduce(gel(vecC,i));
976 }
977 /* step 5 */
978 if (DEBUGLEVEL>2) fprintferr("Step 5\n");
979 Tv = cgetg(rv+1,t_MAT);
980 for (j=1; j<=rv; j++)
981 {
982 p1 = tauofelt(gel(vselmer,j), tau);
983 if (typ(p1) == t_MAT) /* famat */
984 p1 = factorbackelt(gel(p1,1), FpC_red(gel(p1,2),gell), nfz);
985 gel(Tv,j) = isvirtualunit(bnfz, p1, cycgen,cyc,gell,rc);
986 }
987 P = FpM_ker(gsubgs(Tv, g), gell);
988 lW = lg(P); vecW = cgetg(lW,t_VEC);
989 for (j=1; j<lW; j++) gel(vecW,j) = famat_factorback(vselmer, gel(P,j));
990 /* step 6 */
991 if (DEBUGLEVEL>2) fprintferr("Step 6\n");
992 Q = FpM_ker(gsubgs(shallowtrans(Tc), g), gell);
993 /* step 8 */
994 if (DEBUGLEVEL>2) fprintferr("Step 8\n");
995 p1 = RgX_powers(lift_intern(COMPO.p), COMPO.R, degK-1);
996 p1 = RgXV_to_RgM(p1, degKz);
997 T.invexpoteta1 = invmat(p1); /* left inverse */
998 T.polnf = polnf;
999 T.tau = tau;
1000 T.m = m;
1001
1002 idealz = lifttoKz(nfz, nf, ideal, &COMPO);
1003 if (smodis(gcoeff(ideal,1,1), ell)) gothf = idealz;
1004 else
1005 { /* ell | N(ideal) */
1006 GEN bnrz = buchrayinitgen(bnfz, idealz);
1007 GEN subgroupz = invimsubgroup(bnrz, bnr, subgroup, &T);
1008 gothf = conductor(bnrz,subgroupz,0);
1009 }
1010 /* step 9, 10, 11 */
1011 if (DEBUGLEVEL>2) fprintferr("Step 9, 10 and 11\n");
1012 i = build_list_Hecke(&L, nfz, NULL, gothf, gell, tau);
1013 if (i) return no_sol(all,i);
1014
1015 lSml2 = lg(L.Sml2)-1;
1016 Sp = shallowconcat(L.Sm, L.Sml1); lSp = lg(Sp)-1;
1017 listprSp = shallowconcat(L.Sml2, L.Sl); lSl2 = lg(listprSp)-1;
1018
1019 /* step 12 */
1020 if (DEBUGLEVEL>2) fprintferr("Step 12\n");
1021 vecAp = cgetg(lSp+1, t_VEC);
1022 vecBp = cgetg(lSp+1, t_VEC);
1023 matP = cgetg(lSp+1, t_MAT);
1024 for (j=1; j<=lSp; j++)
1025 {
1026 GEN e, a, ap;
1027 p1 = isprincipalell(bnfz, gel(Sp,j), cycgen,u,gell,rc);
1028 e = gel(p1,1); gel(matP,j) = e;
1029 a = gel(p1,2);
1030 p2 = famat_mul(famat_factorback(vecC, gneg(e)), a);
1031 gel(vecBp,j) = p2;
1032 ap = cgetg(1, t_MAT);
1033 for (i=0; i<m; i++)
1034 {
1035 ap = famat_mul(ap, famat_pow(p2, utoi(Fl_pow(g,m-1-i,ell))));
1036 if (i < m-1) p2 = tauofelt(p2, tau);
1037 }
1038 gel(vecAp,j) = ap;
1039 }
1040 /* step 13 */
1041 if (DEBUGLEVEL>2) fprintferr("Step 13\n");
1042 vecWA = shallowconcat(vecW, vecAp);
1043 vecWB = shallowconcat(vecW, vecBp);
1044
1045 /* step 14, 15, and 17 */
1046 if (DEBUGLEVEL>2) fprintferr("Step 14, 15 and 17\n");
1047 mginv = (m * Fl_inv(g,ell)) % ell;
1048 vecMsup = cgetg(lSml2+1,t_VEC);
1049 M = NULL;
1050 for (i=1; i<=lSl2; i++)
1051 {
1052 GEN pr = gel(listprSp,i);
1053 long e = itos(gel(pr,3)), z = ell * (e / (ell-1));
1054
1055 if (i <= lSml2)
1056 {
1057 z += 1 - L.ESml2[i];
1058 gel(vecMsup,i) = logall(nfz, vecWA,lW,mginv,ell, pr,z+1);
1059 }
1060 M = vconcat(M, logall(nfz, vecWA,lW,mginv,ell, pr,z));
1061 }
1062 dc = lg(Q)-1;
1063 if (dc)
1064 {
1065 GEN QtP = gmul(shallowtrans(Q), matP);
1066 M = vconcat(M, shallowconcat(zeromat(dc,lW-1), QtP));
1067 }
1068 if (!M) M = zeromat(1, lSp + lW - 1);
1069 /* step 16 */
1070 if (DEBUGLEVEL>2) fprintferr("Step 16\n");
1071 K = FpM_ker(M, gell);
1072 /* step 18 & ff */
1073 if (DEBUGLEVEL>2) fprintferr("Step 18\n");
1074 dK = lg(K)-1;
1075 y = cgetg(dK+1,t_VECSMALL);
1076 res = cgetg(1, t_VEC); /* in case all = 1 */
1077 if (DEBUGLEVEL) msgTIMER(&t, "[rnfkummer] candidate list");
1078 while (dK)
1079 {
1080 for (i=1; i<dK; i++) y[i] = 0;
1081 y[i] = 1; /* y = [0,...,0,1,0,...,0], 1 at dK'th position */
1082 do
1083 { /* cf. algo 5.3.18 */
1084 GEN H, be, P, X = FpC_red(ZM_zc_mul(K, y), gell);
1085 if (ok_congruence(X, gell, lW, vecMsup))
1086 {
1087 be = compute_beta(X, vecWB, gell, bnfz);
1088 P = compute_polrel(nfz, &T, be, g, ell);
1089 P = lift_if_rational(P);
1090 if (DEBUGLEVEL>1) fprintferr("polrel(beta) = %Z\n", P);
1091 if (!all) {
1092 H = rnfnormgroup(bnr, P);
1093 if (gequal(subgroup, H)) return P; /* DONE */
1094 } else {
1095 GEN P0 = lift(P);
1096 GEN g = nfgcd(P0, derivpol(P0), polnf, gel(nf,4));
1097 if (degpol(g)) continue;
1098 H = rnfnormgroup(bnr, P);
1099 if (!gequal(subgroup,H) && conductor(bnr, H, -1) == gen_0) continue;
1100 }
1101 res = shallowconcat(res, P);
1102 }
1103 } while (increment(y, dK, ell));
1104 y[dK--] = 0;
1105 }
1106 if (all) return res;
1107 return gen_0; /* FAIL */
1108 }
1109
1110 GEN
rnfkummer(GEN bnr,GEN subgroup,long all,long prec)1111 rnfkummer(GEN bnr, GEN subgroup, long all, long prec)
1112 {
1113 pari_sp av = avma;
1114 return gerepilecopy(av, _rnfkummer(bnr, subgroup, all, prec));
1115 }
1116