/* $Id: kummer.c,v 1.17 2001/10/01 12:11:33 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" 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); 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; /* 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; 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; } static GEN grouppows(GEN B, long ex) { long lB = lg(B),j; GEN c; c = cgetg(lB,t_VEC); for (j=1; j= ell); } } 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 */ { 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 0) return no_sol(all,4); if (vd==0) _append(Sml1, pr); else { if (vp==1) return no_sol(all,2); _append(Sml2, pr); _append(ESml2,(GEN)vp); } } } factell = primedec(nf,gell); l = lg(factell); for (i=1; i=7"); return gzero; } return NULL; /* not reached */ } static GEN fix_be(GEN be, GEN u) { GEN e,g, nf = checknf(bnfz), fu = gmael(bnfz,8,5); long i,lu; lu = lg(u); for (i=1; i>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(;;) { 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("unit exponents = %Z\n",c); return fix_be(be,c); } static GEN reducebeta(GEN be) { 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 (;;) { 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, 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 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; 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); 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]; 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); ell = itos(gell); /* 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 */ 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. */ if (DEBUGLEVEL>2) fprintferr("Step 3\n"); bnfz = bnfinit0(R,1,NULL,prec); 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 */ 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])); 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; 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]); } vecC=p2; /* 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); } 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 */ if (DEBUGLEVEL>2) 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; else { GEN bnrz, subgroupz; bnrz = buchrayinitgen(bnfz,idealz); subgroupz = invimsubgroup(bnrz,bnr,subgroup); 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 12\n"); vecbetap=cgetg(lSp+1,t_VEC); vecalphap=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; 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++) { GEN pr = (GEN)listprSp[j]; 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])); } /* 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++) { listbid[i]=(long)zidealstarinitgen(nfz,(GEN)listmod[i]); listellrank[i] = ellrank(gmael3(listbid,i,2,2), ell); } 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 (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 */ if (DEBUGLEVEL>2) fprintferr("Step 18\n"); do { y = cgetg(dK,t_VECSMALL); for (i=1; i= ell); } DECREASE: dK--; } while (dK); avma = av; return gzero; }