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