/* $Id: buch4.c,v 1.15 2001/10/01 12:11:30 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. */ /*******************************************************************/ /* */ /* S-CLASS GROUP AND NORM SYMBOLS */ /* (Denis Simon, desimon@math.u-bordeaux.fr) */ /* */ /*******************************************************************/ #include "pari.h" #include "parinf.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, basistoalg(nf,(GEN)p[2])); nu++; for (i=1; i=4) fprintferr("nfhilbert not soluble at real place %ld\n",i); avma = av; return -1; } /* local solutions in finite completions ? (pr | 2ab) * primes above 2 are toughest. Try the others first */ S = (GEN) idealfactor(nf,gmul(gmulsg(2,a),b))[1]; /* product of all hilbertp is 1 ==> remove one prime (above 2!) */ for (i=lg(S)-1; i>1; i--) if (nfhilbertp(nf,a,b,(GEN) S[i]) < 0) { if (DEBUGLEVEL >=4) fprintferr("nfhilbert not soluble at finite place: %Z\n",S[i]); avma = av; return -1; } avma = av; 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); } extern GEN isprincipalfact(GEN bnf,GEN P, GEN e, GEN C, long flag); extern GEN vconcat(GEN Q1, GEN Q2); extern GEN mathnfspec(GEN x, GEN *ptperm, GEN *ptdep, GEN *ptB, GEN *ptC); extern GEN factorback_i(GEN fa, GEN nf, int red); /* 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) { ulong ltop = avma; long i,j,ls; 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, fl = nf_GEN|nf_FORCE; /* 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; ulong 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"); if (typ(x)!=t_POL) x = basistoalg(bnf,x); bnf = checkbnf(bnf); relnf = (GEN)ext[3]; if (gcmp0(x) || gcmp1(x) || (gcmp_1(x) && (degpol(ext[1])&1))) { avma = (long)res; 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(precer,"bnfisnorm, please increase precision and try again"); aux=(GEN)aux[1]; } if (lg(aux)>1) sunitrelnf=concatsp(aux,sunitrelnf); lgsunitrelnf=lg(sunitrelnf); M=cgetg(lgsunitrelnf+1,t_MAT); sunitnormnf=cgetg(lgsunitrelnf,t_VEC); for (i=1; i