/*******************************************************************/ /* */ /* S-CLASS GROUP AND NORM SYMBOLS */ /* (Denis Simon, desimon@math.u-bordeaux.fr) */ /* */ /*******************************************************************/ /* $Id: buch4.c,v 1.1.1.1 1999/09/16 13:47:29 karim Exp $ */ #include "pari.h" static long psquare(GEN a,GEN p) { long v; GEN ap; if (gcmp0(a) || gcmp1(a)) return 1; if (!cmpis(p,2)) { v=vali(a); if (v&1) return 0; return (smodis(shifti(a,-v),8)==1); } ap=stoi(1); v=pvaluation(a,p,&ap); if (v&1) return 0; return (kronecker(ap,p)==1); } static long lemma6(GEN pol,GEN p,long nu,GEN x) { long i,lambda,mu,ltop=avma; GEN gx,gpx; for (i=lgef(pol)-2,gx=(GEN) pol[i+1]; i>1; i--) gx=addii(mulii(gx,x),(GEN) pol[i]); if (psquare(gx,p)) return 1; for (i=lgef(pol)-2,gpx=mulis((GEN) pol[i+1],i-1); i>2; i--) gpx=addii(mulii(gpx,x),mulis((GEN) pol[i],i-2)); lambda=pvaluation(gx,p,&gx); if (gcmp0(gpx)) mu=BIGINT; else mu=pvaluation(gpx,p,&gpx); avma=ltop; if (lambda>(mu<<1)) return 1; if (lambda>=(nu<<1) && mu>=nu) return 0; return -1; } static long lemma7(GEN pol,long nu,GEN x) { long i,odd4,lambda,mu,mnl,ltop=avma; GEN gx,gpx,oddgx; for (i=lgef(pol)-2,gx=(GEN) pol[i+1]; i>1; i--) gx=addii(mulii(gx,x),(GEN) pol[i]); if (psquare(gx,gdeux)) return 1; for (i=lgef(pol)-2,gpx=gmulgs((GEN) pol[i+1],i-1); i>2; i--) gpx=gadd(gmul(gpx,x),gmulgs((GEN) pol[i],i-2)); lambda=vali(gx); if (gcmp0(gpx)) mu=BIGINT; else mu=vali(gpx); oddgx=shifti(gx,-lambda); mnl=mu+nu-lambda; odd4=smodis(oddgx,4); avma=ltop; if (lambda>(mu<<1)) return 1; if (nu > mu) { if (mnl==1 && (lambda&1) == 0) return 1; if (mnl==2 && (lambda&1) == 0 && odd4==1) return 1; } else { if (lambda>=(nu<<1)) return 0; if (lambda==((nu-1)<<1) && odd4==1) return 0; } return -1; } static long zpsol(GEN pol,GEN p,long nu,GEN pnu,GEN x0) { long i,result,ltop=avma; GEN x,pnup; result = (cmpis(p,2)) ? lemma6(pol,p,nu,x0) : lemma7(pol,nu,x0); if (result==+1) return 1; if (result==-1) return 0; x=gcopy(x0); pnup=mulii(pnu,p); for (i=0; i0); } static long check2(GEN nf, GEN a, GEN zinit) { GEN zlog=zideallog(nf,a,zinit), p1 = gmael(zinit,2,2); long i; for (i=1; i1; i--) gx = gadd(gmul(gx,x),(GEN) pol[i]); if (psquarenf(nf,gx,p)) { avma=ltop; return 1; } lambda = idealval(nf,gx,p); for (i=lgef(pol)-2,gpx=gmulgs((GEN) pol[i+1],i-1); i>2; i--) gpx=gadd(gmul(gpx,x),gmulgs((GEN) pol[i],i-2)); mu = gcmp0(gpx)? BIGINT: idealval(nf,gpx,p); avma=ltop; if (lambda > mu<<1) return 1; if (lambda >= nu<<1 && mu >= nu) return 0; return -1; } static long lemma7nf(GEN nf,GEN pol,GEN p,long nu,GEN x,GEN zinit) { long res,i,lambda,mu,q,ltop=avma; GEN gx,gpx,p1; for (i=lgef(pol)-2, gx=(GEN) pol[i+1]; i>1; i--) gx=gadd(gmul(gx,x),(GEN) pol[i]); if (psquare2nf(nf,gx,p,zinit)) { avma=ltop; return 1; } lambda=idealval(nf,gx,p); for (i=lgef(pol)-2,gpx=gmulgs((GEN) pol[i+1],i-1); i>2; i--) gpx=gadd(gmul(gpx,x),gmulgs((GEN) pol[i],i-2)); if (!gcmp0(gpx)) mu=idealval(nf,gpx,p); else mu=BIGINT; if (lambda>(mu<<1)) { avma=ltop; return 1; } if (nu > mu) { if (lambda&1) { avma=ltop; return -1; } q=mu+nu-lambda; res=1; } else { if (lambda>=(nu<<1)) { avma=ltop; return 0; } if (lambda&1) { avma=ltop; return -1; } q=(nu<<1)-lambda; res=0; } if (q > itos((GEN) p[3])<<1) { avma=ltop; return -1; } p1 = gmodulcp(gpuigs(gmul((GEN)nf[7],(GEN)p[2]), lambda), (GEN)nf[1]); if (!psquare2qnf(nf,gdiv(gx,p1), p,q)) res = -1; avma=ltop; return res; } static long zpsolnf(GEN nf,GEN pol,GEN p,long nu,GEN pnu,GEN x0,GEN repr,GEN zinit) { long i,result,ltop=avma; GEN pnup; nf=checknf(nf); if (cmpis((GEN) p[1],2)) result=lemma6nf(nf,pol,p,nu,x0); else result=lemma7nf(nf,pol,p,nu,x0,zinit); if (result== 1) return 1; if (result==-1) return 0; pnup=gmul(pnu,gmodulcp(gmul((GEN) nf[7],(GEN) p[2]),(GEN) nf[1])); nu++; for (i=1; i=1); avma=ltop; return rep? 1: -1; } /* calcule le symbole de Hilbert quadratique global (a,b): * = 1 si l'equation X^2-aY^2-bZ^2=0 a une solution non triviale, * =-1 sinon, * a et b doivent etre non nuls. */ long nfhilbert(GEN nf,GEN a,GEN b) { long ta=typ(a),tb=typ(b),r1,i,ltop=avma; GEN S,al,bl; nf=checknf(nf); if ((ta!=t_INT && ta!=t_POLMOD && ta!=t_POL) || (tb!=t_INT && tb!=t_POLMOD && tb!=t_POL)) err (typeer,"nfhilbert"); if (gcmp0(a) || gcmp0(b)) err (talker,"0 argument in nfhilbert"); al=lift(a); bl=lift(b); /* solutions locales aux places infinies reelles */ r1=itos(gmael(nf,2,1)); for (i=1; i<=r1; i++) if (signe(poleval(al,gmael(nf,6,i))) < 0 && signe(poleval(bl,gmael(nf,6,i))) < 0) { if (DEBUGLEVEL>=4) { fprintferr("nfhilbert not soluble at a real place\n"); flusherr(); } avma=ltop; return -1; } if (ta!=t_POLMOD) a=gmodulcp(a,(GEN)nf[1]); if (tb!=t_POLMOD) b=gmodulcp(b,(GEN)nf[1]); /* solutions locales aux places finies (celles qui divisent 2ab)*/ S=(GEN) idealfactor(nf,gmul(gmulsg(2,a),b))[1]; /* formule du produit ==> on peut eviter un premier */ for (i=lg(S)-1; i>1; i--) if (nfhilbertp(nf,a,b,(GEN) S[i])==-1) { if (DEBUGLEVEL >=4) { fprintferr("nfhilbert not soluble at finite place: "); outerr((GEN)S[i]); flusherr(); } avma=ltop; return -1; } avma=ltop; return 1; } long nfhilbert0(GEN nf,GEN a,GEN b,GEN p) { if (p) return nfhilbertp(nf,a,b,p); return nfhilbert(nf,a,b); } GEN vconcat(GEN Q1, GEN Q2); GEN mathnfspec(GEN x, GEN *ptperm, GEN *ptdep, GEN *ptB, GEN *ptC); /* S a list of prime ideal in primedec format. Return res: * res[1] = generators of (S-units / units), as polynomials * res[2] = [perm, HB, den], for bnfissunit * res[3] = [] (was: log. embeddings of res[1]) * res[4] = S-regulator ( = R * det(res[2]) * \prod log(Norm(S[i]))) * res[5] = S class group * res[6] = S */ GEN bnfsunit(GEN bnf,GEN S,long prec) { long i,j,ls,ltop=avma,lbot; GEN p1,nf,classgp,gen,M,U,H; GEN sunit,card,sreg,res,pow,fa = cgetg(3, t_MAT); if (typ(S) != t_VEC) err(typeer,"bnfsunit"); bnf = checkbnf(bnf); nf=(GEN)bnf[7]; classgp=gmael(bnf,8,1); gen = (GEN)classgp[3]; sreg = gmael(bnf,8,2); res=cgetg(7,t_VEC); res[1]=res[2]=res[3]=lgetg(1,t_VEC); res[4]=(long)sreg; res[5]=(long)classgp; res[6]=(long)S; ls=lg(S); /* M = relation matrix for the S class group (in terms of the class group * generators given by gen) * 1) ideals in S */ M = cgetg(ls,t_MAT); for (i=1; i 1) { /* non trivial (rare!) */ GEN SNF, ClS = cgetg(4,t_VEC); SNF = smith2(H); p1 = (GEN)SNF[3]; card = dethnf_i(p1); ClS[1] = (long)card; /* h */ for(i=1; i1) { GEN den, Sperm, perm, dep, B, U1 = U; long lH, lB; /* U1 = upper left corner of U, invertible. S * U1 = principal ideals * whose generators generate the S-units */ setlg(U1,ls); p1 = cgetg(ls, t_MAT); /* p1 is junk for mathnfspec */ for (i=1; i 1 && lg(dep[1]) > 1) err(bugparier,"bnfsunit"); /* [ H B ] [ H^-1 - H^-1 B ] * perm o HNF(U1) = [ 0 Id ], inverse = [ 0 Id ] * (permute the rows) * S * HNF(U1) = _integral_ generators for S-units = sunit */ Sperm = cgetg(ls, t_VEC); sunit = cgetg(ls, t_VEC); for (i=1; i 0) xp = gmul(xp, gpuigs(p1, k)); else xm = gmul(xm, gpuigs(p1,-k)); } if (xp != gun) x = gmul(x,xp); if (xm != gun) x = gdiv(x,xm); p1 = isunit(bnf,x); if (lg(p1)==1) { avma = av; return cgetg(1,t_COL); } tetpil=avma; return gerepile(av,tetpil,concat(p1,v)); } static void vecconcat(GEN bnf,GEN relnf,GEN vec,GEN *prod,GEN *S1,GEN *S2) { long i; for (i=1; i0 alors on ajoue dans S tous les ideaux qui divisent p<=flag. * si flag<0 alors on ajoute dans S tous les ideaux qui divisent -flag. * la reponse est un vecteur v a 2 composantes telles que * x=N(v[1])*v[2]. * x est une norme ssi v[2]=1. */ GEN rnfisnorm(GEN bnf,GEN ext,GEN x,long flag,long PREC) { long lgsunitrelnf,i,lbot, ltop = avma; GEN relnf,aux,vec,tors,xnf,H,Y,M,A,suni,sunitrelnf,sunitnormnf,prod; GEN res = cgetg(3,t_VEC), S1,S2; if (typ(ext)!=t_VEC || lg(ext)!=4) err (typeer,"bnfisnorm"); bnf = checkbnf(bnf); relnf = (GEN)ext[3]; if (gcmp0(x) || gcmp1(x) || (gcmp_1(x) && (degree((GEN)ext[1])&1))) { res[1]=lcopy(x); res[2]=un; return res; } /* construction de l'ensemble S des ideaux qui interviennent dans les solutions */ prod=gun; S1=S2=cgetg(1,t_VEC); if (!gcmp1(gmael3(relnf,8,1,1))) { GEN genclass=gmael3(relnf,8,1,3); vec=cgetg(1,t_VEC); for(i=1;i1) { for (i=2; i<=flag; i++) if (isprime(stoi(i)) && signe(resis(prod,i))) { prod=mulis(prod,i); S1=concatsp(S1,primedec(bnf,stoi(i))); S2=concatsp(S2,primedec(relnf,stoi(i))); } } else if (flag<0) vecconcat(bnf,relnf,(GEN)factor(stoi(-flag))[1],&prod,&S1,&S2); if (flag) { GEN normdiscrel=divii(gmael(relnf,7,3), gpuigs(gmael(bnf,7,3),lg(ext[1])-3)); vecconcat(bnf,relnf,(GEN) factor(absi(normdiscrel))[1], &prod,&S1,&S2); } vec=(GEN) idealfactor(bnf,x)[1]; aux=cgetg(2,t_VEC); for (i=1; i1) { sunitrelnf=lift(basistoalg(relnf,sunitrelnf)); sunitrelnf=concatsp(tors,sunitrelnf); } else sunitrelnf=tors; aux=(GEN)relnf[8]; if (lg(aux)>=6) aux=(GEN)aux[5]; else { aux=buchfu(relnf); if(gcmp0((GEN)aux[2])) err(talker,"please increase precision to have units in bnfisnorm"); aux=(GEN)aux[1]; } if (lg(aux)>1) sunitrelnf=concatsp(gtrans(aux),sunitrelnf); lgsunitrelnf=lg(sunitrelnf); M=cgetg(lgsunitrelnf+1,t_MAT); sunitnormnf=cgetg(lgsunitrelnf,t_VEC); for (i=1; i