=================================================================== RCS file: /home/cvs/OpenXM_contrib/pari-2.2/src/modules/Attic/kummer.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- OpenXM_contrib/pari-2.2/src/modules/Attic/kummer.c 2001/10/02 11:17:11 1.1 +++ OpenXM_contrib/pari-2.2/src/modules/Attic/kummer.c 2002/09/11 07:27:05 1.2 @@ -1,4 +1,4 @@ -/* $Id: kummer.c,v 1.1 2001/10/02 11:17:11 noro Exp $ +/* $Id: kummer.c,v 1.2 2002/09/11 07:27:05 noro Exp $ Copyright (C) 2000 The PARI group. @@ -19,1212 +19,1067 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, /* */ /*******************************************************************/ #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 vecmul(GEN x, GEN y); -extern GEN vecinv(GEN x); extern GEN T2_from_embed_norm(GEN x, long r1); -extern GEN pol_to_vec(GEN x, long N); -extern GEN famat_to_nf(GEN nf, GEN f); +extern GEN vconcat(GEN A, GEN B); +extern long int_elt_val(GEN nf, GEN x, GEN p, GEN b, GEN *newx); -static long rc,ell,degK,degKz,m,d,vnf,dv; -static GEN matexpoteta1,nf,raycyc,polnf; -static GEN bnfz,nfz,U,uu,gell,cyc,gencyc,vecalpha,R,g; -static GEN listmod,listprSp,listbid,listunif,listellrank; -static GEN listbidsup,listellranksup,vecw; +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); -/* row vector B x matrix T : c_j=prod_i (b_i^T_ij) */ -static GEN -groupproduct(GEN B, GEN T) -{ - long lB,lT,i,j; - GEN c,p1; +typedef struct { + GEN x; /* tau ( Mod(x, nf.pol) ) */ + GEN zk; /* action of tau on nf.zk (as t_MAT) */ +} tau_s; - lB=lg(B)-1; - lT=lg(T)-1; - c=cgetg(lT+1,t_VEC); - for (j=1; j<=lT; j++) - { - p1=gun; - for (i=1; i<=lB; i++) p1=gmul(p1,gpui((GEN)B[i],gcoeff(T,i,j),0)); - c[j]=(long)p1; - } - return c; -} +typedef struct { + GEN polnf, invexpoteta1; + tau_s *tau; + long m; +} toK_s; -static GEN -grouppows(GEN B, long ex) +long +prank(GEN cyc, long ell) { - long lB = lg(B),j; - GEN c; - - c = cgetg(lB,t_VEC); - for (j=1; j= ell); + for (j = i+1; j < k; j++) y[j] = 0; + return 1; } -static GEN -get_listx(GEN arch,GEN msign,GEN munit,GEN vecmunit2,long ell,long lSp,long nbvunit) +/* as above, y increasing (y[i] <= y[i+1]) */ +static int +increment_inc(GEN y, long k, long ell) { - GEN kermat,p2,X,y, listx = cgetg(1,t_VEC); - long i,j,cmpt,lker; - - kermat = FpM_ker(munit,gell); lker=lg(kermat)-1; - if (!lker) return listx; - y = cgetg(lker,t_VECSMALL); - for (i=1; i= ell); - } + 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 GEN -reducealpha(GEN nf,GEN x,GEN gell) -/* etant donne un nombre algebrique x du corps nf -- non necessairement - entier -- calcule un entier algebrique de la forme x*g^gell */ +static int +ok_congruence(GEN X, GEN ell, long lW, GEN vecMsup) { - long tx=typ(x),i; - GEN den,fa,fac,ep,p1,y; - - nf = checknf(nf); - if (tx==t_POL || tx==t_POLMOD) y = algtobasis(nf,x); - else { y = x; x = basistoalg(nf,y); } - den = denom(y); - if (gcmp1(den)) return x; - fa = decomp(den); fac = (GEN)fa[1];ep = (GEN)fa[2]; - p1 = gun; - for (i=1; 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(;;) { - long k; - p3 = basistoalg(nf,idealcoprime(nf,(GEN)genK[i],p1)); - p2 = basistoalg(nf, famat_to_nf(nf, (GEN)cycgen[i])); - k = itos(mpinvmod((GEN)cyclicK[i], gell)); - p2 = gpowgs(p2,k); - listgamma0[i]= (long)p2; - listgamma[i] = lmul(p2, gpowgs(p3, k * itos((GEN)cyclicK[i]) - 1)); - } - fa = (GEN)bid[3]; - prm = (GEN)fa[1]; - expom = (GEN)fa[2]; l = lg(prm); - Sm = cgetg(l,t_VEC); setlg(Sm,1); - Sml1= cgetg(l,t_VEC); setlg(Sml1,1); - Sml2= cgetg(l,t_VEC); setlg(Sml2,1); - Sl = cgetg(l+degnf,t_VEC); setlg(Sl,1); - ESml2=cgetg(l,t_VECSMALL); setlg(ESml2,1); - for (i=1; i 0) return no_sol(all,4); - if (vd==0) - _append(Sml1, pr); - else + GEN B = NULL; + long besti = 0, bestk = 0; + for (k=1; k<=n; k++) + for (i=1; i<=ru; i++) { - if (vp==1) return no_sol(all,2); - _append(Sml2, pr); - _append(ESml2,(GEN)vp); + 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); } - factell = primedec(nf,gell); l = lg(factell); - 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))) { - pr = (GEN)Sl[i]; e = itos((GEN)pr[3]); - id = idealmul(nf, id, idealpows(nf,pr,(ell*e)/(ell-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); } - vsml2=cgetg(lSml2+1,t_VEC); - for (i=1; i<=lSml2; i++) + 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 (;;) { - pr = (GEN)Sml2[i]; e = itos((GEN)pr[3]); - p1=idealpows(nf,pr, (e*ell)/(ell-1) + 1 - ESml2[i]); - id = idealmul(nf,id,p1); - p2 = idealmul(nf,p1,pr); - p3 = zidealstarinitgen(nf,p2); - vsml2[i] = (long)p3; - cycpro = gmael(p3,2,2); l = lg(cycpro)-1; - if (! gdivise((GEN)cycpro[l],gell)) err(talker,"bug5 in kummer"); + 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); } - bid = zidealstarinitgen(nf,id); - lastbid = ellrank(gmael(bid,2,2), ell); - nbcol=nbvunit+lSp; nblig=lastbid+rc; - munit=cgetg(nbcol+1,t_MAT); vecmunit2=cgetg(lSml2+1,t_VEC); - msign=cgetg(nbcol+1,t_MAT); - for (k=1; k<=lSml2; k++) vecmunit2[k]=lgetg(nbcol+1,t_MAT); - archartif=cgetg(r1+1,t_VEC); for (j=1; j<=r1; j++) archartif[j]=un; - for (j=1; j<=nbvunit; j++) + z = concatsp(matunit, z); + u = lllintern(z, 100, 1, prec); + if (u) { - p1 = zideallog(nf,(GEN)vunit[j],bid); - p2 = cgetg(nblig+1,t_COL); munit[j]=(long)p2; - for (i=1; i<=lastbid; i++) p2[i]=p1[i]; - for ( ; i<=nblig; i++) p2[i]=zero; - for (k=1; k<=lSml2; k++) - mael(vecmunit2,k,j) = (long)zideallog(nf,(GEN)vunit[j],(GEN)vsml2[k]); - msign[j] = (long)zsigne(nf,(GEN)vunit[j],archartif); + 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)); + } } - for (j=1; j<=lSp; j++) - { - p1 = zideallog(nf,(GEN)vecbeta[j],bid); - p2 = cgetg(nblig+1,t_COL); munit[j+nbvunit]=(long)p2; - for (i=1; i<=lastbid; i++) p2[i]=p1[i]; - for ( ; i<=nblig; i++) p2[i]=coeff(matexpo,i-lastbid,j); - for (k=1; k<=lSml2; k++) - mael(vecmunit2,k,j+nbvunit) = (long)zideallog(nf,(GEN)vecbeta[j],(GEN)vsml2[k]); - msign[j+nbvunit] = (long)zsigne(nf,(GEN)vecbeta[j],archartif); - } - listx = get_listx(arch,msign,munit,vecmunit2,ell,lSp,nbvunit); - llistx= lg(listx); - listal= cgetg(llistx,t_VEC); - listg = concatsp(listg, concatsp(vecalpha0,vecbeta0)); - l = lg(listg); - for (i=1; i1) fprintferr("beta LLL-reduced mod U^l = %Z\n",be); + return reducebetanaive(bnfz, be, NULL, ell); } static GEN -tauofideal(GEN id) -{ - long j; - GEN p1,p2; - - p1=gsubst(gmul((GEN)nfz[7],id),vnf,U); - p2=cgetg(lg(p1),t_MAT); - for (j=1; jzk = Uzk; + tau->x = U; return tau; } -static long -isprimeidealconj(GEN pr1, GEN pr2) -{ - GEN pr=pr1; +static GEN tauoffamat(GEN x, tau_s *tau); - do +static GEN +tauofelt(GEN x, tau_s *tau) +{ + switch(typ(x)) { - if (gegal(pr,pr2)) return 1; - pr = tauofprimeideal(pr); + case t_COL: return gmul(tau->zk, x); + case t_MAT: return tauoffamat(x, tau); + default: return tauofalg(x, tau->x); } - while (!gegal(pr,pr1)); - return 0; } +static GEN +tauofvec(GEN x, tau_s *tau) +{ + long i, l = lg(x); + GEN y = cgetg(l, typ(x)); -static long -isconjinprimelist(GEN listpr, GEN pr2) + 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(GEN x) +tracetoK(toK_s *T, GEN x) { + GEN p1 = x; long i; - GEN p1,p2; - - p1=x; p2=x; - for (i=1; i<=m-1; i++) - { - p1=gsubst(lift(p1),vnf,U); - p2=gadd(p2,p1); - } - return downtoK(p2); + for (i=1; i < T->m; i++) p1 = gadd(x, tauofelt(p1,T->tau)); + return downtoK(T, p1); } static GEN -normtoK(GEN x) +normtoK(toK_s *T, GEN x) { + GEN p1 = x; long i; - GEN p1,p2; - - p1=x; p2=x; - for (i=1; i<=m-1; i++) - { - p1=gsubst(lift(p1),vnf,U); - p2=gmul(p2,p1); - } - return downtoK(p2); + for (i=1; i < T->m; i++) p1 = gmul(x, tauofelt(p1,T->tau)); + return downtoK(T, p1); } static GEN -computepolrel(void) +no_sol(long all, int i) { - long i,j; - GEN p1,p2; - - p1=gun; p2=gmodulcp(polx[vnf],R); - for (i=0; i<=m-1; i++) - { - p1=gmul(p1,gsub(polx[0],p2)); - if (iSm = 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); + } + } + } } - /* q^ell = (v) */ - p1 = isprincipalgenforce(bnfz,q); - logdisc = (GEN)p1[1]; - ga = basistoalg(nfz,(GEN)p1[2]); - for (j=rc+1; jSl,pr,tau)) appendL(L->Sl, pr); } - eps = gdiv(v,eps); - p1 = cgetg(3,t_VEC); - p1[1] = (long)concatsp(vecy, lift(isunit(bnfz,eps))); - p1[2] = (long)ga; - return p1; + return 0; /* OK */ } static GEN -lifttokz(GEN id, GEN A1) +logall(GEN nf, GEN vec, long lW, long mginv, long ell, GEN pr, long ex) { - long i,j; - GEN p1,p2,p3; + GEN m, M, bid = zidealstarinitgen(nf, idealpows(nf, pr, ex)); + long ellrank, i, l = lg(vec); - p1=gsubst(gmul((GEN)nf[7],id),vnf,A1); - p2=gmodulcp((GEN)nfz[7],R); - p3=cgetg(degK*degKz+1,t_MAT); - for (i=1; i<=degK; i++) - for (j=1; j<=degKz; j++) - p3[(i-1)*degKz+j]=(long)algtobasis(nfz,gmul((GEN)p1[i],(GEN)p2[j])); - return hnfmod(p3,detint(p3)); -} - -static GEN -steinitzaux(GEN id, GEN polrel) -{ - long i,j; - GEN p1,p2,p3,vecid,matid,pseudomat,pid; - - p1=gsubst(gmul((GEN)nfz[7],id),vnf,polx[0]); - for (j=1; j<=degKz; j++) - p1[j]=(long)gmod((GEN)p1[j],polrel); - p2=cgetg(degKz+1,t_MAT); - for (j=1; j<=degKz; j++) + 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 */ +} - valal = element_val(nfz,al,(GEN)listprSp[i]); - al = gmul(al,gpuigs((GEN)listunif[i],valal)); - p1 = zideallog(nfz,al,(GEN)listbidsup[i]); - llogli = listellranksup[i]; - setlg(p1,llogli+1); return p1; +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 -vectau(GEN list) +rnfkummersimple(GEN bnr, GEN subgroup, GEN gell, long all) { - long i,j,k,n; - GEN listz,listc,yz,yc,listfl,s, y = cgetg(3,t_VEC); + long ell, i, j, degK, dK; + long lSml2, lSl2, lSp, rc, lW; + long prec; - listz = (GEN)list[1]; - listc = (GEN)list[2]; n = lg(listz); - yz = cgetg(n,t_VEC); y[1] = (long)yz; - yc = cgetg(n,t_VEC); y[2] = (long)yc; - listfl=cgetg(n,t_VECSMALL); for (i=1; i> 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) { - if (listfl[j] && gegal((GEN)listz[j],(GEN)listz[i])) - { - s = gadd(s,(GEN)listc[j]); - listfl[j] = 0; - } + z += 1 - L.ESml2[i]; + vecMsup[i] = (long)logall(nf, vecWB, 0,0, ell, pr,z+1); } - yc[k] = (long)s; k++; + M = vconcat(M, logall(nf, vecWB, 0,0, ell, pr,z)); } - setlg(yz, k); - setlg(yc, k); return y; -} + lW = lg(vecW); + M = vconcat(M, concatsp(zeromat(rc,lW-1), matP)); -static GEN -subtau(GEN listx, GEN listy) -{ - GEN y = cgetg(3,t_VEC); - y[1] = (long)concatsp((GEN)listx[1], (GEN)listy[1]); - y[2] = (long)concatsp((GEN)listx[2], gneg_i((GEN)listy[2])); - return vectau(y); + 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 -computepolrelbeta(GEN be) +invimsubgroup(GEN bnrz, GEN bnr, GEN subgroup, toK_s *T) { - long i,a,b,j; - GEN e,u,u1,u2,u3,p1,p2,p3,p4,zet,be1,be2,listr,s,veczi,vecci,powtaubet; + long l, j; + GEN P,raycycz,rayclgpz,raygenz,U,polrel,steinitzZk; + GEN nf = checknf(bnr), nfz = checknf(bnrz), polz = (GEN)nfz[1]; - switch (ell) + 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=7"); return gzero; + GEN g, id = idealhermite(nfz, (GEN)raygenz[j]); + g = steinitzaux(nf, gmul((GEN)nfz[7], id), polrel); + g = idealdiv(nf, g, steinitzZk); /* N_{Kz/K}(gen[j]) */ + P[j] = (long)isprincipalray(bnr, g); } - return NULL; /* not reached */ + U = (GEN)hnfall(concatsp(P, subgroup))[2]; + setlg(U, l); for (j=1; j 1) z = diviiexact(z, mpfact(m)); + a = b[i]; m = 1; + } } - for (i=1; i<=r1;i++) y[i] = lexp((GEN)x[i],prec); - for ( ; i 1) z = diviiexact(z, mpfact(m)); + return z; } -/* multiply be by ell-th powers of units as to find small L2-norm for new be */ +/* 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 -reducebetanaive(GEN be, GEN b) +pol_from_Newton(GEN S) { - long i,k,n,ru,r1, prec = nfgetprec(bnfz); - GEN z,p1,p2,nmax,c, nf = checknf(bnfz); + long i, k, l = lg(S); + GEN c = cgetg(l, t_VEC); - if (DEBUGLEVEL) fprintferr("reduce modulo (Z_K^*)^l\n"); - r1 = nf_get_r1(nf); - if (!b) b = gmul(gmael(nf,5,1), algtobasis(nf,be)); - n = max((ell>>1), 3); - z = cgetg(n+1, t_VEC); - c = gmulgs(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(;;) + c[1] = S[1]; + for (k = 2; k < l; k++) { - 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); + 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); } - if (DEBUGLEVEL) fprintferr("unit exponents = %Z\n",c); - return fix_be(be,c); + return gadd(gpowgs(polx[0], l-1), gtopoly(c, 0)); } +/* th. 5.3.5. and prop. 5.3.9. */ static GEN -reducebeta(GEN be) +compute_polrel(GEN nfz, toK_s *T, GEN be, long g, long ell) { - long j,ru, prec = nfgetprec(bnfz); - GEN emb,z,u,matunit, nf = checknf(bnfz); - - if (gcmp1(gnorm(be))) return reducebetanaive(be,NULL); - matunit = gmulgs(greal((GEN)bnfz[3]), ell); /* log. embeddings of fu^ell */ - for (;;) + 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++) { - 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); + 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)); } - z = concatsp(matunit, z); - u = lllintern(z, 1, prec); - if (!u) return reducebetanaive(be,emb); /* shouldn't occur */ - ru = lg(u); - for (j=1; j1) fprintferr("reducing beta = %Z\n",be); - be = reducebeta(be); - if (DEBUGLEVEL>1) fprintferr("beta reduced = %Z\n",be); - polrelbe = computepolrelbeta(be); - v = varn(polrelbe); - p1 = unifpol((GEN)bnf[7],polrelbe,0); - p1 = denom(gtovec(p1)); - polrelbe = gsubst(polrelbe,v, gdiv(polx[v],p1)); - polrelbe = gmul(polrelbe, gpowgs(p1, degpol(polrelbe))); - if (DEBUGLEVEL>1) fprintferr("polrelbe = %Z\n",polrelbe); - p1 = rnfconductor(bnf,polrelbe,0); - if (!gegal((GEN)p1[1],module) || !gegal((GEN)p1[3],subgroup)) return NULL; - return polrelbe; + 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]); +} -GEN -rnfkummer(GEN bnr, GEN subgroup, long all, long prec) +static GEN +_rnfkummer(GEN bnr, GEN subgroup, long all, long prec) { - long i,j,l,av=avma,e,vp,vd,dK,lSl,lSp,lSl2,lSml2,dc,ru,rv,nbcol; - GEN p1,p2,p3,p4,wk,pr; - GEN bnf,rayclgp,bid,ideal,cycgen,vselmer; - GEN kk,clgp,fununits,torsunit,vecB,vecC,Tc,Tv,P; - GEN Q,Qt,idealz,gothf,factgothf,listpr,listex,factell,p,vecnul; - GEN M,al,K,Msup,X,finalresult,y,module,A1,A2,vecMsup; - GEN listmodsup,vecalphap,vecbetap,mginv,matP,ESml2,Sp,Sm,Sml1,Sml2,Sl; + 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); - wk = gmael4(bnr,1,8,4,1); - if (all) gell = stoi(all); - else - { - if (!gcmp0(subgroup)) gell = det(subgroup); - else gell = det(diagonal(gmael(bnr,5,2))); - } - if (gcmp1(gell)) { avma = av; return polx[varn(gmael3(bnr,1,7,1))]; } - if (!isprime(gell)) err(impl,"kummer for composite relative degree"); - if (divise(wk,gell)) - return gerepileupto(av,rnfkummersimple(bnr,subgroup,all)); - if (all && gcmp0(subgroup)) - err(talker,"kummer when zeta not in K requires a specific subgroup"); bnf = (GEN)bnr[1]; - nf = (GEN)bnf[7]; - polnf = (GEN)nf[1]; vnf = varn(polnf); degK = degpol(polnf); + nf = (GEN)bnf[7]; + polnf = (GEN)nf[1]; vnf = varn(polnf); if (!vnf) err(talker,"main variable in kummer must not be x"); - /* step 7 */ - p1 = conductor(bnr,subgroup,2); - /* fin step 7 */ - bnr = (GEN)p1[2]; + 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]; - rayclgp = (GEN)bnr[5]; - raycyc = (GEN)rayclgp[2]; - bid = (GEN)bnr[2]; module=(GEN)bid[1]; - ideal = (GEN)module[1]; - if (gcmp0(subgroup)) subgroup = diagonal(raycyc); + 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. */ + /* step 1 of alg 5.3.5. */ if (DEBUGLEVEL>2) fprintferr("Step 1\n"); - - p1 = (GEN)compositum2(polnf, cyclo(ell,vnf))[1]; - R = (GEN)p1[1]; - A1= (GEN)p1[2]; - A2= (GEN)p1[3]; - kk= (GEN)p1[4]; - if (signe(leadingcoeff(R)) < 0) - { - R = gneg_i(R); - A1 = gmodulcp(lift(A1),R); - A2 = gmodulcp(lift(A2),R); - } - /* step 2 */ + compositum_red(&COMPO, polnf, cyclo(ell,vnf)); + /* step 2 */ if (DEBUGLEVEL>2) fprintferr("Step 2\n"); - degKz = degpol(R); - m = degKz/degK; - d = (ell-1)/m; - g = lift(gpuigs(gener(gell),d)); /* g has order m in all (Z/ell^k)^* */ - if (gcmp1(powmodulo(g, stoi(m), stoi(ell*ell)))) g = addsi(ell,g); - /* step reduction of R */ - if (degKz<=20) - { - GEN A3,A3rev; - - if (DEBUGLEVEL>2) fprintferr("Step reduction\n"); - p1 = polredabs2(R,prec); - if (DEBUGLEVEL>2) fprintferr("polredabs = %Z",p1[1]); - R = (GEN)p1[1]; - A3= (GEN)p1[2]; - A1 = poleval(lift(A1), A3); - A2 = poleval(lift(A2), A3); - A3rev= polymodrecip(A3); - U = gadd(powgi(A2,g), gmul(kk,A1)); - U = poleval(lift(A3rev), U); - } - else U = gadd(powgi(A2,g), gmul(kk,A1)); - /* step 3 */ - /* one could factor disc(R) using th. 2.1.6. */ + 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"); - bnfz = bnfinit0(R,1,NULL,prec); + /* 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 = ellrank(cyc,ell); - gencyc= (GEN)clgp[3]; l = lg(cyc); - vecalpha=cgetg(l,t_VEC); - cycgen = check_and_build_cycgen(bnfz); - for (j=1; j>1)-1; - rv=rc+ru+1; - vselmer = cgetg(rv+1,t_VEC); - for (j=1; j<=rc; j++) vselmer[j] = vecalpha[j]; - for ( ; j< rv; j++) vselmer[j] = lmodulcp((GEN)fununits[j-rc],R); - vselmer[rv]=(long)gmodulcp((GEN)torsunit,R); - /* step 4 */ + 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 = isprincipalell(tauofideal((GEN)gencyc[j])); + p1 = tauofideal(nfz, (GEN)gen[j], tau); + p1 = isprincipalell(bnfz, p1, cycgen,u,gell,rc); Tc[j] = p1[1]; vecB[j]= p1[2]; } - 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=cgetg(rc+1,t_VEC); - for (j=1; j<=rc; j++) p2[j]=un; - p3=vecB; + + 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++) { - p3 = gsubst(lift(p3),vnf,U); - p4 = groupproduct(grouppows(p3,(j*d)%ell),(GEN)p1[m-j]); - for (i=1; i<=rc; i++) p2[i] = lmul((GEN)p2[i],(GEN)p4[i]); + 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])); } - vecC=p2; - /* step 5 */ + 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++) { - Tv[j] = isvirtualunit(gsubst(lift((GEN)vselmer[j]),vnf,U))[1]; - if (DEBUGLEVEL>2) fprintferr(" %ld\n",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(gsub(Tv, g), gell); - dv= lg(P)-1; vecw = cgetg(dv+1,t_VEC); - for (j=1; j<=dv; j++) - { - p1 = gun; - for (i=1; i<=rv; i++) p1 = gmul(p1, powgi((GEN)vselmer[i],gcoeff(P,i,j))); - vecw[j] = (long)p1; - } - /* step 6 */ + 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(gsub(gtrans(Tc), g), gell); - Qt = gtrans(Q); dc = lg(Q)-1; - /* step 7 done above */ - /* step 8 */ - if (DEBUGLEVEL>2) fprintferr("Step 7 and 8\n"); - idealz=lifttokz(ideal, A1); - computematexpoteta1(lift(A1), R); - if (!divise(idealnorm(nf,ideal),gell)) gothf = idealz; + 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 - { - GEN bnrz, subgroupz; - bnrz = buchrayinitgen(bnfz,idealz); - subgroupz = invimsubgroup(bnrz,bnr,subgroup); + { /* ell | N(ideal) */ + GEN bnrz = buchrayinitgen(bnfz, idealz); + GEN subgroupz = invimsubgroup(bnrz, bnr, subgroup, &T); gothf = conductor(bnrz,subgroupz,0); } - /* step 9 */ - if (DEBUGLEVEL>2) fprintferr("Step 9\n"); - factgothf=idealfactor(nfz,gothf); - listpr = (GEN)factgothf[1]; - listex = (GEN)factgothf[2]; l = lg(listpr); - /* step 10 and step 11 */ - if (DEBUGLEVEL>2) fprintferr("Step 10 and 11\n"); - Sm = cgetg(l,t_VEC); setlg(Sm,1); - Sml1= cgetg(l,t_VEC); setlg(Sml1,1); - Sml2= cgetg(l,t_VEC); setlg(Sml2,1); - Sl = cgetg(l+degKz,t_VEC); setlg(Sl,1); - ESml2=cgetg(l,t_VECSMALL); setlg(ESml2,1); - for (i=1; i 0) { avma = av; return gzero; } - if (vd==0) - { - if (!isconjinprimelist(Sml1,pr)) _append(Sml1, pr); - } - else - { - if (vp==1) { avma = av; return gzero; } - if (!isconjinprimelist(Sml2,pr)) - { - _append(Sml2, pr); - _append(ESml2,(GEN)vp); - } - } - } - } - factell = primedec(nfz,gell); l = lg(factell); - for (i=1; i2) 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"); - vecbetap=cgetg(lSp+1,t_VEC); - vecalphap=cgetg(lSp+1,t_VEC); - matP=cgetg(lSp+1,t_MAT); + vecAp = cgetg(lSp+1, t_VEC); + vecBp = cgetg(lSp+1, t_VEC); + matP = cgetg(lSp+1, t_MAT); for (j=1; j<=lSp; j++) { - p1=isprincipalell((GEN)Sp[j]); - matP[j]=p1[1]; - p2=gun; - for (i=1; i<=rc; i++) - p2 = gmul(p2, powgi((GEN)vecC[i],gmael(p1,1,i))); - p3=gdiv((GEN)p1[2],p2); vecbetap[j]=(long)p3; - p2=gun; + 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"); - nbcol=lSp+dv; - vecw=concatsp(vecw,vecbetap); - listmod=cgetg(lSl2+1,t_VEC); - listunif=cgetg(lSl2+1,t_VEC); - listprSp = concatsp(Sml2, Sl); - for (j=1; j<=lSl2; j++) + 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[j]; + GEN pr = (GEN)listprSp[i]; long e = itos((GEN)pr[3]), z = ell * (e / (ell-1)); - if (j <= lSml2) z += 1 - ESml2[j]; - listmod[j]=(long)idealpows(nfz,pr, z); - listunif[j]=(long)basistoalg(nfz,gdiv((GEN)pr[5],(GEN)pr[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)); } - /* step 14 and step 15 */ - if (DEBUGLEVEL>2) fprintferr("Step 14 and 15\n"); - listbid=cgetg(lSl2+1,t_VEC); - listellrank = cgetg(lSl2+1,t_VECSMALL); - for (i=1; i<=lSl2; i++) + dc = lg(Q)-1; + if (dc) { - listbid[i]=(long)zidealstarinitgen(nfz,(GEN)listmod[i]); - listellrank[i] = ellrank(gmael3(listbid,i,2,2), ell); + GEN QtP = gmul(gtrans_i(Q), matP); + M = vconcat(M, concatsp(zeromat(dc,lW-1), QtP)); } - mginv = modii(mulsi(m, mpinvmod(g,gell)), gell); - vecnul=cgetg(dc+1,t_COL); for (i=1; i<=dc; i++) vecnul[i]=zero; - M=cgetg(nbcol+1,t_MAT); - for (j=1; j<=dv; j++) - { - p1=cgetg(1,t_COL); - al=(GEN)vecw[j]; - for (i=1; i<=lSl2; i++) p1 = concatsp(p1,ideallogaux(i,al)); - p1=gmul(mginv,p1); - M[j]=(long)concatsp(p1,vecnul); - } - for ( ; j<=nbcol; j++) - { - p1=cgetg(1,t_COL); - al=(GEN)vecalphap[j-dv]; - for (i=1; i<=lSl2; i++) p1 = concatsp(p1,ideallogaux(i,al)); - M[j]=(long)concatsp(p1,gmul(Qt,(GEN)matP[j-dv])); - } - /* step 16 */ + if (!M) M = zeromat(1, lSp + lW - 1); + /* step 16 */ if (DEBUGLEVEL>2) fprintferr("Step 16\n"); K = FpM_ker(M, gell); - dK= lg(K)-1; if (!dK) { avma=av; return gzero; } - /* step 17 */ - if (DEBUGLEVEL>2) fprintferr("Step 17\n"); - listmodsup=cgetg(lSml2+1,t_VEC); - listbidsup=cgetg(lSml2+1,t_VEC); - listellranksup=cgetg(lSml2+1,t_VECSMALL); - for (i=1; i<=lSml2; i++) - { - listmodsup[i]=(long)idealmul(nfz,(GEN)listprSp[i],(GEN)listmod[i]); - listbidsup[i]=(long)zidealstarinitgen(nfz,(GEN)listmodsup[i]); - listellranksup[i] = ellrank(gmael3(listbidsup,i,2,2), ell); - } - vecMsup=cgetg(lSml2+1,t_VEC); - for (i=1; i<=lSml2; i++) - { - Msup=cgetg(nbcol+1,t_MAT); vecMsup[i]=(long)Msup; - for (j=1; j<=dv; j++) Msup[j]=lmul(mginv,ideallogauxsup(i,(GEN)vecw[j])); - for ( ; j<=nbcol; j++) Msup[j]=(long)ideallogauxsup(i,(GEN)vecalphap[j-dv]); - } - /* step 18 */ + /* step 18 & ff */ if (DEBUGLEVEL>2) fprintferr("Step 18\n"); - do + dK = lg(K)-1; + y = cgetg(dK+1,t_VECSMALL); + res = cgetg(1, t_VEC); /* in case all = 1 */ + while (dK) { - y = cgetg(dK,t_VECSMALL); for (i=1; i= ell); - } -DECREASE: - dK--; + be = compute_beta(X, vecWB, gell, bnfz); + P = compute_polrel(nfz, &T, be, g, ell); + if (DEBUGLEVEL>1) 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; } - while (dK); - avma = av; return gzero; + 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)); }