/* $Id: kummer.c,v 1.48 2002/09/07 01:28:54 karim 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 "parinf.h" extern GEN gmul_mati_smallvec(GEN x, GEN y); extern GEN check_and_build_cycgen(GEN bnf); extern GEN get_arch_real(GEN nf,GEN x,GEN *emb,long prec); extern GEN T2_from_embed_norm(GEN x, long r1); extern GEN vconcat(GEN A, GEN B); extern long int_elt_val(GEN nf, GEN x, GEN p, GEN b, GEN *newx); extern GEN famat_inv(GEN f); extern GEN famat_pow(GEN f, GEN n); extern GEN famat_mul(GEN f, GEN g); extern GEN famat_reduce(GEN fa); extern GEN famat_ideallog(GEN nf, GEN g, GEN e, GEN bid); extern GEN to_famat(GEN g, GEN e); 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; long prank(GEN cyc, long ell) { long i; for (i=1; i= ell); for (j = i+1; j < k; j++) y[j] = 0; return 1; } /* as above, y increasing (y[i] <= y[i+1]) */ static int increment_inc(GEN y, long k, long ell) { long i = k, j; do { if (--i == 0) return 0; y[i]++; } while (y[i] >= ell); for (j = i+1; j < k; j++) y[j] = y[i]; 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(greal((GEN)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 */ z[1] = (long)concatsp(c, vecinv(c)); for (k=2; k<=n; k++) z[k] = (long) vecmul((GEN)z[1], (GEN)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; c[besti] = laddis((GEN)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; if (typ(be) != t_COL) be = algtobasis(bnfz, be); be = primitive_part(be, &c); if (c) { fa = factor(c); fa[2] = (long)FpV_red((GEN)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. */ static 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 = (GEN)fa[1]; l = lg(Pr); Ex = (GEN)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(greal((GEN)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) err(warnprec,"reducebeta",prec); nf = nfnewprec(nf,prec); } z = concatsp(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 = (GEN)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 = (GEN)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; iinvexpoteta1) - 1; GEN y = gmul(T->invexpoteta1, pol_to_vec(lift(x), degKz)); return gmodulcp(gtopolyrev(y,varn(T->polnf)), T->polnf); } static GEN tracetoK(toK_s *T, GEN x) { GEN p1 = x; long i; for (i=1; i < T->m; i++) p1 = gadd(x, tauofelt(p1,T->tau)); return downtoK(T, p1); } static GEN normtoK(toK_s *T, GEN x) { GEN p1 = x; long i; for (i=1; i < T->m; i++) p1 = gmul(x, tauofelt(p1,T->tau)); return downtoK(T, p1); } static GEN no_sol(long all, int i) { if (!all) 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(gmael(bnr,5,2))); if (typ(gell) != t_INT) 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 = (GEN)fa[1]; listex = (GEN)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 basistoalg(bnfz, be); /* FIXME */ } static GEN get_Selmer(GEN bnf, GEN cycgen, long rc) { GEN fu = check_units(bnf,"rnfkummer"); GEN tu = gmael3(bnf,8,4,2); return concatsp(algtobasis(bnf,concatsp(fu,tu)), vecextract_i(cycgen,1,rc)); } /* if all!=0, give all equations of degree 'all'. Assume bnr modulus is the * conductor */ static GEN rnfkummersimple(GEN bnr, GEN subgroup, GEN gell, long all) { long ell, i, j, degK, dK; long lSml2, lSl2, lSp, rc, lW; long prec; GEN bnf,nf,bid,ideal,arch,cycgen; GEN clgp,cyc; GEN Sp,listprSp,matP; GEN res,u,M,K,y,vecMsup,vecW,vecWB,vecBp,msign; primlist L; bnf = (GEN)bnr[1]; nf = (GEN)bnf[7]; degK = degpol(nf[1]); bid = (GEN)bnr[2]; ideal= gmael(bid,1,1); arch = gmael(bid,1,2); /* this is the conductor */ ell = itos(gell); i = build_list_Hecke(&L, nf, (GEN)bid[3], ideal, gell, NULL); if (i) return no_sol(all,i); lSml2 = lg(L.Sml2)-1; Sp = concatsp(L.Sm, L.Sml1); lSp = lg(Sp)-1; listprSp = concatsp(L.Sml2, L.Sl); lSl2 = lg(listprSp)-1; cycgen = check_and_build_cycgen(bnf); clgp = gmael(bnf,8,1); cyc = (GEN)clgp[2]; rc = prank(cyc, ell); vecW = get_Selmer(bnf, cycgen, rc); u = get_u(cyc, rc, gell); vecBp = cgetg(lSp+1, t_VEC); matP = cgetg(lSp+1, t_MAT); for (j=1; j<=lSp; j++) { GEN e, a, L; L = isprincipalell(bnf,(GEN)Sp[j], cycgen,u,gell,rc); e = (GEN)L[1]; matP[j] = (long)e; a = (GEN)L[2]; vecBp[j] = (long)a; } vecWB = concatsp(vecW, vecBp); prec = DEFAULTPREC + ((gexpo(vecWB) + gexpo(gmael(nf,5,1))) >> TWOPOTBYTES_IN_LONG); if (nfgetprec(nf) < prec) nf = nfnewprec(nf, prec); msign = zsigns(nf, vecWB); vecMsup = cgetg(lSml2+1,t_VEC); M = NULL; for (i=1; i<=lSl2; i++) { GEN pr = (GEN)listprSp[i]; long e = itos((GEN)pr[3]), z = ell * (e / (ell-1)); if (i <= lSml2) { z += 1 - L.ESml2[i]; vecMsup[i] = (long)logall(nf, vecWB, 0,0, ell, pr,z+1); } M = vconcat(M, logall(nf, vecWB, 0,0, ell, pr,z)); } lW = lg(vecW); M = vconcat(M, concatsp(zeromat(rc,lW-1), matP)); K = FpM_ker(M, gell); dK = lg(K)-1; y = cgetg(dK+1,t_VECSMALL); res = cgetg(1,t_VEC); /* in case all = 1 */ while (dK) { for (i=1; 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,steinitzZk; GEN nf = checknf(bnr), nfz = checknf(bnrz), polz = (GEN)nfz[1]; polrel = polrelKzK(T, polx[varn(polz)]); steinitzZk = steinitzaux(nf, (GEN)nfz[7], polrel); rayclgpz = (GEN)bnrz[5]; raycycz = (GEN)rayclgpz[2]; l = lg(raycycz); raygenz = (GEN)rayclgpz[3]; P = cgetg(l,t_MAT); for (j=1; j 1) z = diviiexact(z, mpfact(m)); a = b[i]; m = 1; } } if (m > 1) z = diviiexact(z, mpfact(m)); return z; } /* r[b[1]] + ... + r[b[k-1]] + 1 = 0 mod ell ?*/ static int b_suitable(GEN b, GEN r, long k, long ell) { long i, s = 1; for (i = 1; i < k; i++) s += r[ 1 + b[i] ]; return (s % ell) == 0; } static GEN pol_from_Newton(GEN S) { long i, k, l = lg(S); GEN c = cgetg(l, t_VEC); c[1] = S[1]; for (k = 2; k < l; k++) { GEN s = (GEN)S[k]; for (i = 1; i < k; i++) s = gadd(s, gmul((GEN)S[i], (GEN)c[k-i])); c[k] = ldivgs(s, -k); } return gadd(gpowgs(polx[0], l-1), gtopoly(c, 0)); } /* 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; GEN r, powtaubet, S, X = polx[0], e = normtoK(T,be); switch (ell) { /* special-cased for efficiency */ GEN p1, u; case 2: err(bugparier,"rnfkummer (-1 not in nf?)"); break; case 3: u = tracetoK(T,be); p1 = gsub(gsqr(X), gmulsg(3,e)); return gsub(gmul(X,p1), gmul(e,u)); case 5: if (m == 2) { u = tracetoK(T, gpowgs(be,3)); p1 = gadd(gmulsg(5,gsqr(e)), gmul(gsqr(X), gsub(gsqr(X),gmulsg(5,e)))); return gsub(gmul(X,p1), gmul(e,u)); } else { /* m = 4 */ GEN be1, be2, u1, u2, u3; be1 = tauofelt(be, T->tau); be2 = tauofelt(be1,T->tau); u1 = tracetoK(T, gmul(be,be1)); u2 = tracetoK(T, gmul(gmul(be,be2),gsqr(be1))); u3 = tracetoK(T, gmul(gmul(gsqr(be),gpowgs(be1,3)),be2)); p1 = gsub(gsqr(X), gmulsg(10,e)); p1 = gsub(gmul(X,p1), gmulsg(5,gmul(e,u1))); p1 = gadd(gmul(X,p1), gmul(gmulsg(5,e),gsub(e,u2))); return gsub(gmul(X,p1), gmul(e,u3)); } } /* general case */ 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); S = cgetg(ell+1, t_VEC); /* Newton sums */ S[1] = zero; for (k = 2; k <= ell; k++) { GEN z, g = gzero, b = vecsmall_const(k-1, 0); do { if (! b_suitable(b, r, k, ell)) continue; z = factorbackelt(powtaubet, compute_t(b, r, m, ell), nfz); if (typ(z) == t_COL) z = basistoalg(nfz, z); g = gadd(g, gmul(get_multinomial(b), z)); } while (increment_inc(b, k, m)); S[k] = lmul(gmulsg(ell, e), tracetoK(T,g)); } 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 = gmul((GEN)nf[7], (GEN)I[2]); I[2] = (long)algtobasis(nfz, RX_RXQ_compo(x, C->p, C->R)); return prime_to_ideal(nfz,I); } static void compositum_red(compo_s *C, GEN P, GEN Q) { GEN a, z = (GEN)compositum2(P, Q)[1]; C->R = (GEN)z[1]; C->p = (GEN)z[2]; C->q = (GEN)z[3]; C->k = (GEN)z[4]; /* reduce R */ z = polredabs0(C->R, nf_ORIG|nf_PARTIALFACT); C->R = (GEN)z[1]; if (DEBUGLEVEL>1) fprintferr("polred(compositum) = %Z\n",C->R); a = (GEN)z[2]; C->p = poleval(lift_intern(C->p), a); C->q = poleval(lift_intern(C->q), a); C->rev = modreverse_i((GEN)a[2], (GEN)a[1]); } 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 l, 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; checkbnrgen(bnr); bnf = (GEN)bnr[1]; nf = (GEN)bnf[7]; polnf = (GEN)nf[1]; vnf = varn(polnf); if (!vnf) err(talker,"main variable in kummer must not be x"); wk = gmael3(bnf,8,4,1); /* step 7 */ if (all) subgroup = NULL; p1 = conductor(bnr, subgroup, 2); bnr = (GEN)p1[2]; subgroup = (GEN)p1[3]; gell = get_gell(bnr,subgroup,all); if (gcmp1(gell)) return polx[vnf]; if (!isprime(gell)) err(impl,"kummer for composite relative degree"); if (divise(wk,gell)) return rnfkummersimple(bnr, subgroup, gell, all); bid = (GEN)bnr[2]; ideal = gmael(bid,1,1); ell = itos(gell); /* 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"); degK = degpol(polnf); degKz = degpol(COMPO.R); m = degKz / degK; d = (ell-1) / m; g = powuumod(u_gener(ell), d, ell); if (powuumod(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); cycgen = check_and_build_cycgen(bnfz); nfz = (GEN)bnfz[7]; clgp = gmael(bnfz,8,1); cyc = (GEN)clgp[2]; rc = prank(cyc,ell); gen = (GEN)clgp[3]; l = lg(cyc); u = get_u(cyc, rc, gell); vselmer = get_Selmer(bnfz, cycgen, rc); 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, (GEN)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); for (j=1; j<=rc; j++) vecC[j] = lgetg(1, t_MAT); p1 = cgetg(m,t_VEC); p1[1] = (long)idmat(rc); for (j=2; j<=m-1; j++) p1[j] = lmul((GEN)p1[j-1],Tc); p2 = vecB; for (j=1; j<=m-1; j++) { GEN T = FpM_red(gmulsg((j*d)%ell,(GEN)p1[m-j]), gell); p2 = tauofvec(p2, tau); for (i=1; i<=rc; i++) vecC[i] = (long)famat_mul((GEN)vecC[i], famat_factorback(p2, (GEN)T[i])); } for (i=1; i<=rc; i++) vecC[i] = (long)famat_reduce((GEN)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((GEN)vselmer[j], tau); if (typ(p1) == t_MAT) /* famat */ p1 = factorbackelt((GEN)p1[1], FpV_red((GEN)p1[2],gell), nfz); Tv[j] = (long)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(gtrans(Tc), g), gell); /* step 8 */ if (DEBUGLEVEL>2) fprintferr("Step 8\n"); p1 = RXQ_powers(lift_intern(COMPO.p), COMPO.R, degK-1); p1 = vecpol_to_mat(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(idealnorm(nf,ideal), 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 = concatsp(L.Sm, L.Sml1); lSp = lg(Sp)-1; listprSp = concatsp(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, (GEN)Sp[j], cycgen,u,gell,rc); e = (GEN)p1[1]; matP[j] = (long)e; a = (GEN)p1[2]; p2 = famat_mul(famat_factorback(vecC, gneg(e)), a); vecBp[j] = (long)p2; ap = cgetg(1, t_MAT); for (i=0; i2) fprintferr("Step 13\n"); vecWA = concatsp(vecW, vecAp); vecWB = concatsp(vecW, vecBp); /* step 14, 15, and 17 */ if (DEBUGLEVEL>2) fprintferr("Step 14, 15 and 17\n"); mginv = (m * u_invmod(g,ell)) % ell; vecMsup = cgetg(lSml2+1,t_VEC); M = NULL; for (i=1; i<=lSl2; i++) { GEN pr = (GEN)listprSp[i]; long e = itos((GEN)pr[3]), z = ell * (e / (ell-1)); if (i <= lSml2) { z += 1 - L.ESml2[i]; vecMsup[i] = (long)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(gtrans_i(Q), matP); M = vconcat(M, concatsp(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 */ while (dK) { for (i=1; i1) fprintferr("polrel(beta) = %Z\n", P); if (!all && gegal(subgroup, rnfnormgroup(bnr, P))) return P; /* DONE */ res = concatsp(res, P); } } while (increment(y, dK, ell)); y[dK--] = 0; } if (all) return res; return gzero; /* FAIL */ } GEN rnfkummer(GEN bnr, GEN subgroup, long all, long prec) { gpmem_t av = avma; return gerepilecopy(av, _rnfkummer(bnr, subgroup, all, prec)); }