/* $Id: kummer.c,v 1.126.2.1 2006/09/26 19:36:04 kb Exp $ Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*******************************************************************/ /* */ /* KUMMER EXTENSIONS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" typedef struct { GEN x; /* tau ( Mod(x, nf.pol) ) */ GEN zk; /* action of tau on nf.zk (as t_MAT) */ } tau_s; typedef struct { GEN polnf, invexpoteta1; tau_s *tau; long m; } toK_s; static long prank(GEN cyc, long ell) { long i; for (i=1; i= d); for (j = i+1; j < k; j++) y[j] = 0; return 1; } static int ok_congruence(GEN X, GEN ell, long lW, GEN vecMsup) { long i, l; if (gcmp0(X)) return 0; l = lg(X); for (i=lW; i>1), 3); z = cgetg(n+1, t_VEC); c = gmul(real_i(gel(bnfz,3)), ell); c = logarch2arch(c, r1, prec); /* = embeddings of fu^ell */ c = gprec_w(gnorm(c), DEFAULTPREC); b = gprec_w(gnorm(b), DEFAULTPREC); /* need little precision */ gel(z,1) = shallowconcat(c, vecinv(c)); for (k=2; k<=n; k++) gel(z,k) = vecmul(gel(z,1), gel(z,k-1)); nmax = T2_from_embed_norm(b, r1); ru = lg(c)-1; c = zerovec(ru); for(;;) { GEN B = NULL; long besti = 0, bestk = 0; for (k=1; k<=n; k++) for (i=1; i<=ru; i++) { p1 = vecmul(b, gmael(z,k,i)); p2 = T2_from_embed_norm(p1,r1); if (gcmp(p2,nmax) < 0) { B=p1; nmax=p2; besti=i; bestk = k; continue; } p1 = vecmul(b, gmael(z,k,i+ru)); p2 = T2_from_embed_norm(p1,r1); if (gcmp(p2,nmax) < 0) { B=p1; nmax=p2; besti=i; bestk =-k; } } if (!B) break; b = B; gel(c,besti) = addis(gel(c,besti), bestk); } if (DEBUGLEVEL) fprintferr("naive reduction mod U^l: unit exp. = %Z\n",c); return fix_be(bnfz, be, gmul(ell,c)); } static GEN reduce_mod_Qell(GEN bnfz, GEN be, GEN gell) { GEN c, fa; be = algtobasis_i(bnfz, be); be = primitive_part(be, &c); if (c) { fa = factor(c); gel(fa,2) = FpC_red(gel(fa,2), gell); c = factorback(fa, NULL); be = gmul(be, c); } return be; } /* return q, q^n r = x, v_pr(r) < n for all pr. Insist q is a genuine n-th * root (i.e r = 1) if strict != 0. */ GEN idealsqrtn(GEN nf, GEN x, GEN gn, int strict) { long i, l, n = itos(gn); GEN fa, q, Ex, Pr; fa = idealfactor(nf, x); Pr = gel(fa,1); l = lg(Pr); Ex = gel(fa,2); q = NULL; for (i=1; i1) fprintferr("reducing beta = %Z\n",be); /* reduce mod Q^ell */ be = reduce_mod_Qell(nf, be, ell); /* reduce l-th root */ z = idealsqrtn(nf, be, ell, 0); if (typ(z) == t_MAT && !gcmp1(gcoeff(z,1,1))) { z = idealred_elt(nf, z); be = element_div(nf, be, element_pow(nf, z, ell)); /* make be integral */ be = reduce_mod_Qell(nf, be, ell); } if (DEBUGLEVEL>1) fprintferr("beta reduced via ell-th root = %Z\n",be); matunit = gmul(real_i(gel(bnfz,3)), ell); /* log. embeddings of fu^ell */ for (;;) { z = get_arch_real(nf, be, &emb, prec); if (z) break; prec = (prec-1)<<1; if (DEBUGLEVEL) pari_warn(warnprec,"reducebeta",prec); nf = nfnewprec(nf,prec); } z = shallowconcat(matunit, z); u = lllintern(z, 100, 1, prec); if (u) { ru = lg(u); for (j=1; j < ru; j++) if (gcmp1(gcoeff(u,ru-1,j))) break; if (j < ru) { u = gel(u,j); /* coords on (fu^ell, be) of a small generator */ ru--; setlg(u, ru); be = fix_be(bnfz, be, gmul(ell,u)); } } if (DEBUGLEVEL>1) fprintferr("beta LLL-reduced mod U^l = %Z\n",be); return reducebetanaive(bnfz, be, NULL, ell); } static GEN tauofalg(GEN x, GEN U) { return gsubst(lift(x), varn(U[1]), U); } static tau_s * get_tau(tau_s *tau, GEN nf, GEN U) { GEN bas = gel(nf,7), Uzk; long i, l = lg(bas); Uzk = cgetg(l, t_MAT); for (i=1; izk = Uzk; tau->x = U; return tau; } static GEN tauoffamat(GEN x, tau_s *tau); static GEN tauofelt(GEN x, tau_s *tau) { switch(typ(x)) { case t_COL: return gmul(tau->zk, x); case t_MAT: return tauoffamat(x, tau); default: return tauofalg(x, tau->x); } } static GEN tauofvec(GEN x, tau_s *tau) { long i, l = lg(x); GEN y = cgetg(l, typ(x)); for (i=1; izk, id), gcoeff(id, 1,1)); } static int isprimeidealconj(GEN nfz, GEN pr1, GEN pr2, tau_s *tau) { GEN p = gel(pr1,1); GEN x = gel(pr1,2); GEN b1= gel(pr1,5); GEN b2= gel(pr2,5); if (!equalii(p, gel(pr2,1)) || !equalii(gel(pr1,3), gel(pr2,3)) || !equalii(gel(pr1,4), gel(pr2,4))) return 0; if (gequal(x,gel(pr2,2))) return 1; for(;;) { if (int_elt_val(nfz,x,p,b2,NULL)) return 1; x = FpC_red(tauofelt(x, tau), p); if (int_elt_val(nfz,x,p,b1,NULL)) return 0; } } static int isconjinprimelist(GEN nfz, GEN S, GEN pr, tau_s *tau) { long i, l; if (!tau) return 0; l = lg(S); for (i=1; iinvexpoteta1) - 1; GEN y = gmul(T->invexpoteta1, RgX_to_RgV(lift_intern(x), degKz)); return gmodulo(gtopolyrev(y,varn(T->polnf)), T->polnf); } static GEN no_sol(long all, long i) { if (!all) pari_err(talker,"bug%d in kummer",i); return cgetg(1,t_VEC); } static GEN get_gell(GEN bnr, GEN subgp, long all) { GEN gell; if (all) gell = stoi(all); else if (subgp) gell = det(subgp); else gell = det(diagonal_i(gmael(bnr,5,2))); if (typ(gell) != t_INT) pari_err(arither1); return gell; } typedef struct { GEN Sm, Sml1, Sml2, Sl, ESml2; } primlist; static int build_list_Hecke(primlist *L, GEN nfz, GEN fa, GEN gothf, GEN gell, tau_s *tau) { GEN listpr, listex, pr, p, factell; long vd, vp, e, i, l, ell = itos(gell), degKz = degpol(nfz[1]); if (!fa) fa = idealfactor(nfz, gothf); listpr = gel(fa,1); listex = gel(fa,2); l = lg(listpr); L->Sm = cget1(l,t_VEC); L->Sml1= cget1(l,t_VEC); L->Sml2= cget1(l,t_VEC); L->Sl = cget1(l+degKz,t_VEC); L->ESml2=cget1(l,t_VECSMALL); for (i=1; iSm,pr,tau)) appendL(L->Sm,pr); } else { vd = (vp-1)*(ell-1)-ell*e; if (vd > 0) return 4; if (vd==0) { if (!isconjinprimelist(nfz, L->Sml1,pr,tau)) appendL(L->Sml1, pr); } else { if (vp==1) return 2; if (!isconjinprimelist(nfz, L->Sml2,pr,tau)) { appendL(L->Sml2, pr); appendL(L->ESml2,(GEN)vp); } } } } factell = primedec(nfz,gell); l = lg(factell); for (i=1; iSl,pr,tau)) appendL(L->Sl, pr); } return 0; /* OK */ } static GEN logall(GEN nf, GEN vec, long lW, long mginv, long ell, GEN pr, long ex) { GEN m, M, bid = zidealstarinitgen(nf, idealpows(nf, pr, ex)); long ellrank, i, l = lg(vec); ellrank = prank(gmael(bid,2,2), ell); M = cgetg(l,t_MAT); for (i=1; i1) fprintferr("beta reduced = %Z\n",be); return be; } static GEN get_Selmer(GEN bnf, GEN cycgen, long rc) { GEN fu = check_units(bnf,"rnfkummer"); GEN tu = gmael3(bnf,8,4,2); return shallowconcat(algtobasis(bnf,shallowconcat(fu,tu)), vecslice(cycgen,1,rc)); } GEN lift_if_rational(GEN x) { long lx, i; GEN y; switch(typ(x)) { default: break; case t_POLMOD: y = gel(x,2); if (typ(y) == t_POL) { long d = degpol(y); if (d > 0) return x; return (d < 0)? gen_0: gel(y,2); } return y; case t_POL: lx = lg(x); for (i=2; im, T->tau), 0); long i, l = lg(P); for (i=2; i Cl_m(K), lift subgroup from bnr to bnrz using Algo 4.1.11 */ static GEN invimsubgroup(GEN bnrz, GEN bnr, GEN subgroup, toK_s *T) { long l, j; GEN P,raycycz,rayclgpz,raygenz,U,polrel,StZk; GEN nf = checknf(bnr), nfz = checknf(bnrz), polz = gel(nfz,1); polrel = polrelKzK(T, pol_x[varn(polz)]); StZk = Stelt(nf, gel(nfz,7), polrel); rayclgpz = gel(bnrz,5); raycycz = gel(rayclgpz,2); l = lg(raycycz); raygenz = gel(rayclgpz,3); P = cgetg(l,t_MAT); for (j=1; j= varn(x) */ static GEN split_pol(GEN x, long v, long a, long b) { long i, l = degpol(x); GEN y = x + a, z; if (l < b) b = l; if (a > b || varn(x) != v) return zeropol(v); l = b-a + 3; z = cgetg(l, t_POL); z[1] = x[1]; for (i = 2; i < l; i++) z[i] = y[i]; return normalizepol_i(z, l); } /* return (den_a * z) mod (v^ell - num_a/den_a), assuming deg(z) < 2*ell * allow either num/den to be NULL (= 1) */ static GEN mod_Xell_a(GEN z, long v, long ell, GEN num_a, GEN den_a) { GEN z1 = split_pol(z, v, ell, degpol(z)); GEN z0 = split_pol(z, v, 0, ell-1); /* z = v^ell z1 + z0*/ if (den_a) z0 = gmul(den_a, z0); if (num_a) z1 = gmul(num_a, z1); return gadd(z0, z1); } static GEN to_alg(GEN nfz, GEN v) { GEN z; if (typ(v) != t_COL) return v; z = gmul(gel(nfz,7), v); if (typ(z) == t_POL) setvarn(z, MAXVARN); return z; } /* th. 5.3.5. and prop. 5.3.9. */ static GEN compute_polrel(GEN nfz, toK_s *T, GEN be, long g, long ell) { long i, k, m = T->m, vT = fetch_var(); GEN r, powtaubet, S, p1, root, num_t, den_t, nfzpol, powtau_prim_invbe; GEN prim_Rk, C_Rk, prim_root, C_root, prim_invbe, C_invbe; pari_timer ti; r = cgetg(m+1,t_VECSMALL); /* r[i+1] = g^i mod ell */ r[1] = 1; for (i=2; i<=m; i++) r[i] = (r[i-1] * g) % ell; powtaubet = powtau(be, m, T->tau); if (DEBUGLEVEL>1) { fprintferr("Computing Newton sums: "); TIMERstart(&ti); } prim_invbe = Q_primitive_part(element_inv(nfz, be), &C_invbe); powtau_prim_invbe = powtau(prim_invbe, m, T->tau); root = cgetg(ell + 2, t_POL); root[1] = evalsigne(1) | evalvarn(0); for (i = 0; i < ell; i++) gel(root,2+i) = gen_0; for (i = 0; i < m; i++) { /* compute (1/be) ^ (-mu) instead of be^mu [mu << 0]. * 1/be = C_invbe * prim_invbe */ GEN mmu = get_mmu(i, r, ell); /* p1 = prim_invbe ^ -mu */ p1 = to_alg(nfz, factorbackelt(powtau_prim_invbe, mmu, nfz)); if (C_invbe) p1 = gmul(p1, powgi(C_invbe, sum(mmu,1,m))); /* root += zeta_ell^{r_i} T^{r_i} be^mu_i */ gel(root, 2 + r[i+1]) = monomial(p1, r[i+1], vT); } /* Other roots are as above with z_ell --> z_ell^j. * Treat all contents (C_*) and principal parts (prim_*) separately */ prim_Rk = prim_root = Q_primitive_part(root, &C_root); C_Rk = C_root; /* Compute modulo X^ell - 1, T^ell - t, nfzpol(MAXVARN) */ p1 = to_alg(nfz, factorbackelt(powtaubet, get_reverse(r), nfz)); num_t = Q_remove_denom(p1, &den_t); nfzpol = shallowcopy(gel(nfz,1)); setvarn(nfzpol, MAXVARN); S = cgetg(ell+1, t_VEC); /* Newton sums */ gel(S,1) = gen_0; for (k = 2; k <= ell; k++) { /* compute the k-th Newton sum */ pari_sp av = avma; GEN z, D, Rk = gmul(prim_Rk, prim_root); C_Rk = mul_content(C_Rk, C_root); Rk = mod_Xell_a(Rk, 0, ell, NULL, NULL); /* mod X^ell - 1 */ for (i = 2; i < lg(Rk); i++) { z = mod_Xell_a(gel(Rk,i), vT, ell, num_t,den_t); /* mod T^ell - t */ gel(Rk,i) = RgXQX_red(z, nfzpol); /* mod nfz.pol */ } if (den_t) C_Rk = mul_content(C_Rk, ginv(den_t)); prim_Rk = Q_primitive_part(Rk, &D); C_Rk = mul_content(C_Rk, D); /* root^k = prim_Rk * C_Rk */ /* Newton sum is ell * constant coeff (in X), which has degree 0 in T */ z = polcoeff_i(prim_Rk, 0, 0); z = polcoeff_i(z , 0,vT); z = downtoK(T, gmulgs(z, ell)); if (C_Rk) z = gmul(z, C_Rk); gerepileall(av, C_Rk? 3: 2, &z, &prim_Rk, &C_Rk); if (DEBUGLEVEL>1) { fprintferr("%ld(%ld) ", k, TIMER(&ti)); flusherr(); } gel(S,k) = z; } if (DEBUGLEVEL>1) fprintferr("\n"); (void)delete_var(); return pol_from_Newton(S); } typedef struct { GEN R; /* compositum(P,Q) */ GEN p; /* Mod(p,R) root of P */ GEN q; /* Mod(q,R) root of Q */ GEN k; /* Q[X]/R generated by q + k p */ GEN rev; } compo_s; static GEN lifttoKz(GEN nfz, GEN nf, GEN id, compo_s *C) { GEN I = ideal_two_elt(nf,id); GEN x = coltoliftalg(nf, gel(I,2)); gel(I,2) = algtobasis(nfz, RgX_RgXQ_compo(x, C->p, C->R)); return prime_to_ideal(nfz,I); } static void compositum_red(compo_s *C, GEN P, GEN Q) { GEN p, q, a, z = (GEN)compositum2(P, Q)[1]; long v; a = gel(z,1); v = varn(a); p = lift_intern(gel(z,2)); q = lift_intern(gel(z,3)); C->k = gel(z,4); /* reduce R */ z = polredabs0(a, nf_ORIG|nf_PARTIALFACT); C->R = gel(z,1); a = gel(z,2); C->p = poleval(p, a); if (C->p == gen_0) C->p = mkpolmod(zeropol(v),gel(a,1)); C->q = poleval(q, a); C->rev = modreverse_i(gel(a,2), gel(a,1)); if (DEBUGLEVEL>1) fprintferr("polred(compositum) = %Z\n",C->R); } static GEN _rnfkummer(GEN bnr, GEN subgroup, long all, long prec) { long ell, i, j, m, d, dK, dc, rc, ru, rv, g, mginv, degK, degKz, vnf; long lSp, lSml2, lSl2, lW; GEN polnf,bnf,nf,bnfz,nfz,bid,ideal,cycgen,gell,p1,p2,wk,U,vselmer; GEN clgp,cyc,gen; GEN Q,idealz,gothf; GEN res,u,M,K,y,vecMsup,vecW,vecWA,vecWB,vecB,vecC,vecAp,vecBp; GEN matP,Sp,listprSp,Tc,Tv,P; primlist L; toK_s T; tau_s _tau, *tau; compo_s COMPO; pari_timer t; if (DEBUGLEVEL) TIMERstart(&t); checkbnrgen(bnr); bnf = gel(bnr,1); nf = gel(bnf,7); polnf = gel(nf,1); vnf = varn(polnf); if (!vnf) pari_err(talker,"main variable in kummer must not be x"); wk = gmael3(bnf,8,4,1); /* step 7 */ p1 = conductor(bnr, subgroup, 2); if (DEBUGLEVEL) msgTIMER(&t, "[rnfkummer] conductor"); bnr = gel(p1,2); subgroup = gel(p1,3); gell = get_gell(bnr,subgroup,all); ell = itos(gell); if (ell == 1) return pol_x[vnf]; if (!uisprime(ell)) pari_err(impl,"kummer for composite relative degree"); if (!umodiu(wk,ell)) return rnfkummersimple(bnr, subgroup, gell, all); bid = gel(bnr,2); ideal = gmael(bid,1,1); /* step 1 of alg 5.3.5. */ if (DEBUGLEVEL>2) fprintferr("Step 1\n"); compositum_red(&COMPO, polnf, cyclo(ell,vnf)); /* step 2 */ if (DEBUGLEVEL>2) fprintferr("Step 2\n"); if (DEBUGLEVEL) msgTIMER(&t, "[rnfkummer] compositum"); degK = degpol(polnf); degKz = degpol(COMPO.R); m = degKz / degK; d = (ell-1) / m; g = (long)Fl_pow(gener_Fl(ell), d, ell); if (Fl_pow((ulong)g, m, ell*ell) == 1) g += ell; /* ord(g) = m in all (Z/ell^k)^* */ /* step 3 */ if (DEBUGLEVEL>2) fprintferr("Step 3\n"); /* could factor disc(R) using th. 2.1.6. */ bnfz = bnfinit0(COMPO.R,1,NULL,prec); if (DEBUGLEVEL) msgTIMER(&t, "[rnfkummer] bnfinit(Kz)"); cycgen = check_and_build_cycgen(bnfz); nfz = gel(bnfz,7); clgp = gmael(bnfz,8,1); cyc = gel(clgp,2); rc = prank(cyc,ell); gen = gel(clgp,3); u = get_u(cyc, rc, gell); vselmer = get_Selmer(bnfz, cycgen, rc); if (DEBUGLEVEL) msgTIMER(&t, "[rnfkummer] Selmer group"); ru = (degKz>>1)-1; rv = rc+ru+1; /* compute action of tau */ U = gadd(gpowgs(COMPO.q, g), gmul(COMPO.k, COMPO.p)); U = poleval(COMPO.rev, U); tau = get_tau(&_tau, nfz, U); /* step 4 */ if (DEBUGLEVEL>2) fprintferr("Step 4\n"); vecB=cgetg(rc+1,t_VEC); Tc=cgetg(rc+1,t_MAT); for (j=1; j<=rc; j++) { p1 = tauofideal(nfz, gel(gen,j), tau); p1 = isprincipalell(bnfz, p1, cycgen,u,gell,rc); Tc[j] = p1[1]; vecB[j]= p1[2]; } vecC = cgetg(rc+1,t_VEC); if (rc) { for (j=1; j<=rc; j++) gel(vecC,j) = cgetg(1, t_MAT); p1 = cgetg(m,t_VEC); gel(p1,1) = matid(rc); for (j=2; j<=m-1; j++) gel(p1,j) = gmul(gel(p1,j-1),Tc); p2 = vecB; for (j=1; j<=m-1; j++) { GEN z = FpM_red(gmulsg((j*d)%ell,gel(p1,m-j)), gell); p2 = tauofvec(p2, tau); for (i=1; i<=rc; i++) gel(vecC,i) = famat_mul(gel(vecC,i), famat_factorback(p2,gel(z,i))); } for (i=1; i<=rc; i++) gel(vecC,i) = famat_reduce(gel(vecC,i)); } /* step 5 */ if (DEBUGLEVEL>2) fprintferr("Step 5\n"); Tv = cgetg(rv+1,t_MAT); for (j=1; j<=rv; j++) { p1 = tauofelt(gel(vselmer,j), tau); if (typ(p1) == t_MAT) /* famat */ p1 = factorbackelt(gel(p1,1), FpC_red(gel(p1,2),gell), nfz); gel(Tv,j) = isvirtualunit(bnfz, p1, cycgen,cyc,gell,rc); } P = FpM_ker(gsubgs(Tv, g), gell); lW = lg(P); vecW = cgetg(lW,t_VEC); for (j=1; j2) fprintferr("Step 6\n"); Q = FpM_ker(gsubgs(shallowtrans(Tc), g), gell); /* step 8 */ if (DEBUGLEVEL>2) fprintferr("Step 8\n"); p1 = RgX_powers(lift_intern(COMPO.p), COMPO.R, degK-1); p1 = RgXV_to_RgM(p1, degKz); T.invexpoteta1 = invmat(p1); /* left inverse */ T.polnf = polnf; T.tau = tau; T.m = m; idealz = lifttoKz(nfz, nf, ideal, &COMPO); if (smodis(gcoeff(ideal,1,1), ell)) gothf = idealz; else { /* ell | N(ideal) */ GEN bnrz = buchrayinitgen(bnfz, idealz); GEN subgroupz = invimsubgroup(bnrz, bnr, subgroup, &T); gothf = conductor(bnrz,subgroupz,0); } /* step 9, 10, 11 */ if (DEBUGLEVEL>2) fprintferr("Step 9, 10 and 11\n"); i = build_list_Hecke(&L, nfz, NULL, gothf, gell, tau); if (i) return no_sol(all,i); lSml2 = lg(L.Sml2)-1; Sp = shallowconcat(L.Sm, L.Sml1); lSp = lg(Sp)-1; listprSp = shallowconcat(L.Sml2, L.Sl); lSl2 = lg(listprSp)-1; /* step 12 */ if (DEBUGLEVEL>2) fprintferr("Step 12\n"); vecAp = cgetg(lSp+1, t_VEC); vecBp = cgetg(lSp+1, t_VEC); matP = cgetg(lSp+1, t_MAT); for (j=1; j<=lSp; j++) { GEN e, a, ap; p1 = isprincipalell(bnfz, gel(Sp,j), cycgen,u,gell,rc); e = gel(p1,1); gel(matP,j) = e; a = gel(p1,2); p2 = famat_mul(famat_factorback(vecC, gneg(e)), a); gel(vecBp,j) = p2; ap = cgetg(1, t_MAT); for (i=0; i2) fprintferr("Step 13\n"); vecWA = shallowconcat(vecW, vecAp); vecWB = shallowconcat(vecW, vecBp); /* step 14, 15, and 17 */ if (DEBUGLEVEL>2) fprintferr("Step 14, 15 and 17\n"); mginv = (m * Fl_inv(g,ell)) % ell; vecMsup = cgetg(lSml2+1,t_VEC); M = NULL; for (i=1; i<=lSl2; i++) { GEN pr = gel(listprSp,i); long e = itos(gel(pr,3)), z = ell * (e / (ell-1)); if (i <= lSml2) { z += 1 - L.ESml2[i]; gel(vecMsup,i) = logall(nfz, vecWA,lW,mginv,ell, pr,z+1); } M = vconcat(M, logall(nfz, vecWA,lW,mginv,ell, pr,z)); } dc = lg(Q)-1; if (dc) { GEN QtP = gmul(shallowtrans(Q), matP); M = vconcat(M, shallowconcat(zeromat(dc,lW-1), QtP)); } if (!M) M = zeromat(1, lSp + lW - 1); /* step 16 */ if (DEBUGLEVEL>2) fprintferr("Step 16\n"); K = FpM_ker(M, gell); /* step 18 & ff */ if (DEBUGLEVEL>2) fprintferr("Step 18\n"); dK = lg(K)-1; y = cgetg(dK+1,t_VECSMALL); res = cgetg(1, t_VEC); /* in case all = 1 */ if (DEBUGLEVEL) msgTIMER(&t, "[rnfkummer] candidate list"); while (dK) { for (i=1; i1) fprintferr("polrel(beta) = %Z\n", P); H = rnfnormgroup(bnr, P); if (!all) { if (gequal(subgroup, H)) return P; /* DONE */ } else { if (!gequal(subgroup,H) && conductor(bnr, H, -1) == gen_0) continue; } res = shallowconcat(res, P); } } while (increment(y, dK, ell)); y[dK--] = 0; } if (all) return res; return gen_0; /* FAIL */ } GEN rnfkummer(GEN bnr, GEN subgroup, long all, long prec) { pari_sp av = avma; return gerepilecopy(av, _rnfkummer(bnr, subgroup, all, prec)); }