Annotation of OpenXM_contrib/pari/src/basemath/buch4.c, Revision 1.1
1.1 ! maekawa 1: /*******************************************************************/
! 2: /* */
! 3: /* S-CLASS GROUP AND NORM SYMBOLS */
! 4: /* (Denis Simon, desimon@math.u-bordeaux.fr) */
! 5: /* */
! 6: /*******************************************************************/
! 7: /* $Id: buch4.c,v 1.1.1.1 1999/09/16 13:47:29 karim Exp $ */
! 8: #include "pari.h"
! 9:
! 10: static long
! 11: psquare(GEN a,GEN p)
! 12: {
! 13: long v;
! 14: GEN ap;
! 15:
! 16: if (gcmp0(a) || gcmp1(a)) return 1;
! 17:
! 18: if (!cmpis(p,2))
! 19: {
! 20: v=vali(a); if (v&1) return 0;
! 21: return (smodis(shifti(a,-v),8)==1);
! 22: }
! 23:
! 24: ap=stoi(1); v=pvaluation(a,p,&ap);
! 25: if (v&1) return 0;
! 26: return (kronecker(ap,p)==1);
! 27: }
! 28:
! 29: static long
! 30: lemma6(GEN pol,GEN p,long nu,GEN x)
! 31: {
! 32: long i,lambda,mu,ltop=avma;
! 33: GEN gx,gpx;
! 34:
! 35: for (i=lgef(pol)-2,gx=(GEN) pol[i+1]; i>1; i--)
! 36: gx=addii(mulii(gx,x),(GEN) pol[i]);
! 37: if (psquare(gx,p)) return 1;
! 38:
! 39: for (i=lgef(pol)-2,gpx=mulis((GEN) pol[i+1],i-1); i>2; i--)
! 40: gpx=addii(mulii(gpx,x),mulis((GEN) pol[i],i-2));
! 41:
! 42: lambda=pvaluation(gx,p,&gx);
! 43: if (gcmp0(gpx)) mu=BIGINT; else mu=pvaluation(gpx,p,&gpx);
! 44: avma=ltop;
! 45:
! 46: if (lambda>(mu<<1)) return 1;
! 47: if (lambda>=(nu<<1) && mu>=nu) return 0;
! 48: return -1;
! 49: }
! 50:
! 51: static long
! 52: lemma7(GEN pol,long nu,GEN x)
! 53: { long i,odd4,lambda,mu,mnl,ltop=avma;
! 54: GEN gx,gpx,oddgx;
! 55:
! 56: for (i=lgef(pol)-2,gx=(GEN) pol[i+1]; i>1; i--)
! 57: gx=addii(mulii(gx,x),(GEN) pol[i]);
! 58: if (psquare(gx,gdeux)) return 1;
! 59:
! 60: for (i=lgef(pol)-2,gpx=gmulgs((GEN) pol[i+1],i-1); i>2; i--)
! 61: gpx=gadd(gmul(gpx,x),gmulgs((GEN) pol[i],i-2));
! 62:
! 63: lambda=vali(gx);
! 64: if (gcmp0(gpx)) mu=BIGINT; else mu=vali(gpx);
! 65: oddgx=shifti(gx,-lambda);
! 66: mnl=mu+nu-lambda;
! 67: odd4=smodis(oddgx,4);
! 68: avma=ltop;
! 69: if (lambda>(mu<<1)) return 1;
! 70: if (nu > mu)
! 71: { if (mnl==1 && (lambda&1) == 0) return 1;
! 72: if (mnl==2 && (lambda&1) == 0 && odd4==1) return 1;
! 73: }
! 74: else
! 75: { if (lambda>=(nu<<1)) return 0;
! 76: if (lambda==((nu-1)<<1) && odd4==1) return 0;
! 77: }
! 78: return -1;
! 79: }
! 80:
! 81: static long
! 82: zpsol(GEN pol,GEN p,long nu,GEN pnu,GEN x0)
! 83: {
! 84: long i,result,ltop=avma;
! 85: GEN x,pnup;
! 86:
! 87: result = (cmpis(p,2)) ? lemma6(pol,p,nu,x0) : lemma7(pol,nu,x0);
! 88: if (result==+1) return 1; if (result==-1) return 0;
! 89: x=gcopy(x0); pnup=mulii(pnu,p);
! 90: for (i=0; i<itos(p); i++)
! 91: {
! 92: x=addii(x,pnu);
! 93: if (zpsol(pol,p,nu+1,pnup,x)) { avma=ltop; return 1; }
! 94: }
! 95: avma=ltop; return 0;
! 96: }
! 97:
! 98: /* vaut 1 si l'equation y^2=Pol(x) a une solution p-adique entiere
! 99: * 0 sinon. Les coefficients sont entiers.
! 100: */
! 101: long
! 102: zpsoluble(GEN pol,GEN p)
! 103: {
! 104: if ((typ(pol)!=t_POL && typ(pol)!=t_INT) || typ(p)!=t_INT )
! 105: err(typeer,"zpsoluble");
! 106: return zpsol(pol,p,0,gun,gzero);
! 107: }
! 108:
! 109: /* vaut 1 si l'equation y^2=Pol(x) a une solution p-adique rationnelle
! 110: * (eventuellement infinie), 0 sinon. Les coefficients sont entiers.
! 111: */
! 112: long
! 113: qpsoluble(GEN pol,GEN p)
! 114: {
! 115: if ((typ(pol)!=t_POL && typ(pol)!=t_INT) || typ(p)!=t_INT )
! 116: err(typeer,"qpsoluble");
! 117: if (zpsol(pol,p,0,gun,gzero)) return 1;
! 118: return (zpsol(polrecip(pol),p,1,p,gzero));
! 119: }
! 120:
! 121: /* p premier a 2. renvoie 1 si a est un carre dans ZK_p, 0 sinon */
! 122: static long
! 123: psquarenf(GEN nf,GEN a,GEN p)
! 124: {
! 125: long v,ltop=avma;
! 126: GEN norm,ap;
! 127:
! 128: if (gcmp0(a)) return 1;
! 129: v=idealval(nf,a,p); if (v&1) return 0;
! 130: ap=gdiv(a,gpuigs(basistoalg(nf,(GEN)p[2]),v));
! 131:
! 132: norm=gshift(idealnorm(nf,p),-1);
! 133: ap=gmul(ap,gmodulsg(1,(GEN)p[1]));
! 134: ap=gaddgs(gpui(ap,norm,0),-1);
! 135: if (gcmp0(ap)) { avma=ltop; return 1; }
! 136: ap=lift(lift(ap));
! 137: v = idealval(nf,ap,p); avma=ltop;
! 138: return (v>0);
! 139: }
! 140:
! 141: static long
! 142: check2(GEN nf, GEN a, GEN zinit)
! 143: {
! 144: GEN zlog=zideallog(nf,a,zinit), p1 = gmael(zinit,2,2);
! 145: long i;
! 146:
! 147: for (i=1; i<lg(p1); i++)
! 148: if (!mpodd((GEN)p1[i]) && mpodd((GEN)zlog[i])) return 0;
! 149: return 1;
! 150: }
! 151:
! 152: /* p divise 2. renvoie 1 si a est un carre dans ZK_p, 0 sinon */
! 153: static long
! 154: psquare2nf(GEN nf,GEN a,GEN p,GEN zinit)
! 155: {
! 156: long v, ltop=avma;
! 157:
! 158: if (gcmp0(a)) return 1;
! 159: v=idealval(nf,a,p); if (v&1) return 0;
! 160: a = gdiv(a,gmodulcp(gpuigs(gmul((GEN)nf[7],(GEN)p[2]),v),(GEN)nf[1]));
! 161: v = check2(nf,a,zinit); avma = ltop; return v;
! 162: }
! 163:
! 164: /* p divise 2, (a,p)=1. renvoie 1 si a est un carre de (ZK / p^q)*, 0 sinon. */
! 165: static long
! 166: psquare2qnf(GEN nf,GEN a,GEN p,long q)
! 167: {
! 168: long v, ltop=avma;
! 169: GEN zinit = zidealstarinit(nf,idealpows(nf,p,q));
! 170:
! 171: v = check2(nf,a,zinit); avma = ltop; return v;
! 172: }
! 173:
! 174: static long
! 175: lemma6nf(GEN nf,GEN pol,GEN p,long nu,GEN x)
! 176: {
! 177: long i,lambda,mu,ltop=avma;
! 178: GEN gx,gpx;
! 179:
! 180: for (i=lgef(pol)-2,gx=(GEN) pol[i+1]; i>1; i--)
! 181: gx = gadd(gmul(gx,x),(GEN) pol[i]);
! 182: if (psquarenf(nf,gx,p)) { avma=ltop; return 1; }
! 183: lambda = idealval(nf,gx,p);
! 184:
! 185: for (i=lgef(pol)-2,gpx=gmulgs((GEN) pol[i+1],i-1); i>2; i--)
! 186: gpx=gadd(gmul(gpx,x),gmulgs((GEN) pol[i],i-2));
! 187: mu = gcmp0(gpx)? BIGINT: idealval(nf,gpx,p);
! 188:
! 189: avma=ltop;
! 190: if (lambda > mu<<1) return 1;
! 191: if (lambda >= nu<<1 && mu >= nu) return 0;
! 192: return -1;
! 193: }
! 194:
! 195: static long
! 196: lemma7nf(GEN nf,GEN pol,GEN p,long nu,GEN x,GEN zinit)
! 197: {
! 198: long res,i,lambda,mu,q,ltop=avma;
! 199: GEN gx,gpx,p1;
! 200:
! 201: for (i=lgef(pol)-2, gx=(GEN) pol[i+1]; i>1; i--)
! 202: gx=gadd(gmul(gx,x),(GEN) pol[i]);
! 203: if (psquare2nf(nf,gx,p,zinit)) { avma=ltop; return 1; }
! 204: lambda=idealval(nf,gx,p);
! 205:
! 206: for (i=lgef(pol)-2,gpx=gmulgs((GEN) pol[i+1],i-1); i>2; i--)
! 207: gpx=gadd(gmul(gpx,x),gmulgs((GEN) pol[i],i-2));
! 208: if (!gcmp0(gpx)) mu=idealval(nf,gpx,p); else mu=BIGINT;
! 209:
! 210: if (lambda>(mu<<1)) { avma=ltop; return 1; }
! 211: if (nu > mu)
! 212: {
! 213: if (lambda&1) { avma=ltop; return -1; }
! 214: q=mu+nu-lambda; res=1;
! 215: }
! 216: else
! 217: {
! 218: if (lambda>=(nu<<1)) { avma=ltop; return 0; }
! 219: if (lambda&1) { avma=ltop; return -1; }
! 220: q=(nu<<1)-lambda; res=0;
! 221: }
! 222: if (q > itos((GEN) p[3])<<1) { avma=ltop; return -1; }
! 223: p1 = gmodulcp(gpuigs(gmul((GEN)nf[7],(GEN)p[2]), lambda), (GEN)nf[1]);
! 224: if (!psquare2qnf(nf,gdiv(gx,p1), p,q)) res = -1;
! 225: avma=ltop; return res;
! 226: }
! 227:
! 228: static long
! 229: zpsolnf(GEN nf,GEN pol,GEN p,long nu,GEN pnu,GEN x0,GEN repr,GEN zinit)
! 230: {
! 231: long i,result,ltop=avma;
! 232: GEN pnup;
! 233:
! 234: nf=checknf(nf);
! 235: if (cmpis((GEN) p[1],2))
! 236: result=lemma6nf(nf,pol,p,nu,x0);
! 237: else
! 238: result=lemma7nf(nf,pol,p,nu,x0,zinit);
! 239: if (result== 1) return 1;
! 240: if (result==-1) return 0;
! 241: pnup=gmul(pnu,gmodulcp(gmul((GEN) nf[7],(GEN) p[2]),(GEN) nf[1]));
! 242: nu++;
! 243: for (i=1; i<lg(repr); i++)
! 244: if (zpsolnf(nf,pol,p,nu,pnup,gadd(x0,gmul(pnu,(GEN)repr[i])),repr,zinit))
! 245: { avma=ltop; return 1; }
! 246: avma=ltop; return 0;
! 247: }
! 248:
! 249: /* calcule un systeme de representants Zk/p */
! 250: static GEN
! 251: repres(GEN nf,GEN p)
! 252: {
! 253: long i,j,k,f,pp,ppf,ppi;
! 254: GEN mat,fond,rep;
! 255:
! 256: fond=cgetg(1,t_VEC);
! 257: mat=idealhermite(nf,p);
! 258: for (i=1; i<lg(mat); i++)
! 259: if (!gcmp1(gmael(mat,i,i)))
! 260: fond = concatsp(fond,gmael(nf,7,i));
! 261: f=lg(fond)-1;
! 262: pp=itos((GEN) p[1]);
! 263: for (i=1,ppf=1; i<=f; i++) ppf*=pp;
! 264: rep=cgetg(ppf+1,t_VEC);
! 265: rep[1]=zero; ppi=1;
! 266: for (i=0; i<f; i++,ppi*=pp)
! 267: for (j=1; j<pp; j++)
! 268: for (k=1; k<=ppi; k++)
! 269: rep[j*ppi+k]=ladd((GEN) rep[k],gmulsg(j,(GEN) fond[i+1]));
! 270: return gmodulcp(rep,(GEN) nf[1]);
! 271: }
! 272:
! 273: /* =1 si l'equation y^2 = z^deg(pol) * pol(x/z) a une solution rationnelle
! 274: * p-adique (eventuellement (1,y,0) = oo)
! 275: * =0 sinon.
! 276: * Les coefficients de pol doivent etre des entiers de nf.
! 277: * p est un ideal premier sous forme primedec.
! 278: */
! 279: long
! 280: qpsolublenf(GEN nf,GEN pol,GEN p)
! 281: {
! 282: GEN repr,zinit,p1;
! 283: long ltop=avma;
! 284:
! 285: if (gcmp0(pol)) return 1;
! 286: if (typ(pol)!=t_POL) err(notpoler,"qpsolublenf");
! 287: if (typ(p)!=t_VEC || lg(p)!=6)
! 288: err(talker,"not a prime ideal in qpsolublenf");
! 289: nf=checknf(nf);
! 290:
! 291: if (cmpis((GEN) p[1],2))
! 292: {
! 293: if (psquarenf(nf,(GEN) pol[2],p)) return 1;
! 294: if (psquarenf(nf, leading_term(pol),p)) return 1;
! 295: zinit=gzero;
! 296: }
! 297: else
! 298: {
! 299: zinit=zidealstarinit(nf,idealpows(nf,p,1+2*idealval(nf,gdeux,p)));
! 300: if (psquare2nf(nf,(GEN) pol[2],p,zinit)) return 1;
! 301: if (psquare2nf(nf, leading_term(pol),p,zinit)) return 1;
! 302: }
! 303: repr=repres(nf,p);
! 304: if (zpsolnf(nf,pol,p,0,gun,gzero,repr,zinit)) { avma=ltop; return 1; }
! 305: p1 = gmodulcp(gmul((GEN) nf[7],(GEN) p[2]),(GEN) nf[1]);
! 306: if (zpsolnf(nf,polrecip(pol),p,1,p1,gzero,repr,zinit))
! 307: { avma=ltop; return 1; }
! 308:
! 309: avma=ltop; return 0;
! 310: }
! 311:
! 312: /* =1 si l'equation y^2 = pol(x) a une solution entiere p-adique
! 313: * =0 sinon.
! 314: * Les coefficients de pol doivent etre des entiers de nf.
! 315: * p est un ideal premier sous forme primedec.
! 316: */
! 317: long
! 318: zpsolublenf(GEN nf,GEN pol,GEN p)
! 319: {
! 320: GEN repr,zinit;
! 321: long ltop=avma;
! 322:
! 323: if (gcmp0(pol)) return 1;
! 324: if (typ(pol)!=t_POL) err(notpoler,"zpsolublenf");
! 325: if (typ(p)!=t_VEC || lg(p)!=6)
! 326: err(talker,"not a prime ideal in zpsolublenf");
! 327: nf=checknf(nf);
! 328:
! 329: if (cmpis((GEN)p[1],2))
! 330: {
! 331: if (psquarenf(nf,(GEN) pol[2],p)) return 1;
! 332: zinit=gzero;
! 333: }
! 334: else
! 335: {
! 336: zinit=zidealstarinit(nf,idealpows(nf,p,1+2*idealval(nf,gdeux,p)));
! 337: if (psquare2nf(nf,(GEN) pol[2],p,zinit)) return 1;
! 338: }
! 339: repr=repres(nf,p);
! 340: if (zpsolnf(nf,pol,p,0,gun,gzero,repr,zinit)) { avma=ltop; return 1; }
! 341: avma=ltop; return 0;
! 342: }
! 343:
! 344: static long
! 345: hilb2nf(GEN nf,GEN a,GEN b,GEN p)
! 346: {
! 347: GEN pol;
! 348: long ltop=avma;
! 349:
! 350: a=lift(a); b=lift(b);
! 351: pol=polx[0]; pol=gadd(gmul(a,gsqr(pol)),b);
! 352: if (qpsolublenf(nf,pol,p)) { avma=ltop; return 1; }
! 353: avma=ltop; return -1;
! 354: }
! 355:
! 356: /* pr doit etre sous la forme primedec */
! 357: static GEN
! 358: nfmodid2(GEN nf,GEN x,GEN pr)
! 359: {
! 360: x=lift(x);
! 361: x=gmod(x,lift(basistoalg(nf,(GEN)pr[2])));
! 362: return gmul(x,gmodulsg(1,(GEN)pr[1]));
! 363: }
! 364:
! 365: long
! 366: nfhilbertp(GEN nf,GEN a,GEN b,GEN p)
! 367: /* calcule le symbole de Hilbert quadratique local (a,b)_p
! 368: * en l'ideal premier p du corps nf,
! 369: * a et b sont des elements non nuls de nf, sous la forme
! 370: * de polymods ou de polynomes, et p renvoye par primedec.
! 371: */
! 372: {
! 373: GEN aux,aux2;
! 374: long ta=typ(a),tb=typ(b),alpha,beta,sign,rep,ltop=avma;
! 375:
! 376: if ((ta!=t_INT && ta!=t_POLMOD && ta!=t_POL)
! 377: || (tb!=t_INT && tb!=t_POLMOD && tb!=t_POL))
! 378: err (typeer,"nfhilbertp");
! 379: if (gcmp0(a) || gcmp0(b))
! 380: err (talker,"0 argument in nfhilbertp");
! 381: checkprimeid(p); nf=checknf(nf);
! 382:
! 383: if (!cmpis((GEN) p[1],2)) return hilb2nf(nf,a,b,p);
! 384:
! 385: if (ta != t_POLMOD) a=gmodulcp(a,(GEN)nf[1]);
! 386: if (tb != t_POLMOD) b=gmodulcp(b,(GEN)nf[1]);
! 387:
! 388: alpha=idealval(nf,a,p); beta=idealval(nf,b,p);
! 389: if ((alpha&1) == 0 && (beta&1) == 0) { avma=ltop; return 1; }
! 390: aux2=shifti(idealnorm(nf,p),-1);
! 391: if (alpha&1 && beta&1 && mpodd(aux2)) sign=1; else sign=-1;
! 392: aux=nfmodid2(nf,gdiv(gpuigs(a,beta),gpuigs(b,alpha)),p); /* ?????? */
! 393: aux=gaddgs(powgi(aux,aux2),sign);
! 394: aux=lift(lift(aux));
! 395: if (gcmp0(aux)) rep=1; else rep=(idealval(nf,aux,p)>=1);
! 396: avma=ltop; return rep? 1: -1;
! 397: }
! 398:
! 399: /* calcule le symbole de Hilbert quadratique global (a,b):
! 400: * = 1 si l'equation X^2-aY^2-bZ^2=0 a une solution non triviale,
! 401: * =-1 sinon,
! 402: * a et b doivent etre non nuls.
! 403: */
! 404: long
! 405: nfhilbert(GEN nf,GEN a,GEN b)
! 406: {
! 407: long ta=typ(a),tb=typ(b),r1,i,ltop=avma;
! 408: GEN S,al,bl;
! 409:
! 410: nf=checknf(nf);
! 411: if ((ta!=t_INT && ta!=t_POLMOD && ta!=t_POL)
! 412: || (tb!=t_INT && tb!=t_POLMOD && tb!=t_POL))
! 413: err (typeer,"nfhilbert");
! 414: if (gcmp0(a) || gcmp0(b))
! 415: err (talker,"0 argument in nfhilbert");
! 416:
! 417: al=lift(a); bl=lift(b);
! 418: /* solutions locales aux places infinies reelles */
! 419: r1=itos(gmael(nf,2,1));
! 420: for (i=1; i<=r1; i++)
! 421: if (signe(poleval(al,gmael(nf,6,i))) < 0 &&
! 422: signe(poleval(bl,gmael(nf,6,i))) < 0)
! 423: {
! 424: if (DEBUGLEVEL>=4)
! 425: {
! 426: fprintferr("nfhilbert not soluble at a real place\n");
! 427: flusherr();
! 428: }
! 429: avma=ltop; return -1;
! 430: }
! 431: if (ta!=t_POLMOD) a=gmodulcp(a,(GEN)nf[1]);
! 432: if (tb!=t_POLMOD) b=gmodulcp(b,(GEN)nf[1]);
! 433:
! 434: /* solutions locales aux places finies (celles qui divisent 2ab)*/
! 435:
! 436: S=(GEN) idealfactor(nf,gmul(gmulsg(2,a),b))[1];
! 437: /* formule du produit ==> on peut eviter un premier */
! 438: for (i=lg(S)-1; i>1; i--)
! 439: if (nfhilbertp(nf,a,b,(GEN) S[i])==-1)
! 440: {
! 441: if (DEBUGLEVEL >=4)
! 442: {
! 443: fprintferr("nfhilbert not soluble at finite place: ");
! 444: outerr((GEN)S[i]); flusherr();
! 445: }
! 446: avma=ltop; return -1;
! 447: }
! 448: avma=ltop; return 1;
! 449: }
! 450:
! 451: long
! 452: nfhilbert0(GEN nf,GEN a,GEN b,GEN p)
! 453: {
! 454: if (p) return nfhilbertp(nf,a,b,p);
! 455: return nfhilbert(nf,a,b);
! 456: }
! 457:
! 458: GEN vconcat(GEN Q1, GEN Q2);
! 459: GEN mathnfspec(GEN x, GEN *ptperm, GEN *ptdep, GEN *ptB, GEN *ptC);
! 460: /* S a list of prime ideal in primedec format. Return res:
! 461: * res[1] = generators of (S-units / units), as polynomials
! 462: * res[2] = [perm, HB, den], for bnfissunit
! 463: * res[3] = [] (was: log. embeddings of res[1])
! 464: * res[4] = S-regulator ( = R * det(res[2]) * \prod log(Norm(S[i])))
! 465: * res[5] = S class group
! 466: * res[6] = S
! 467: */
! 468: GEN
! 469: bnfsunit(GEN bnf,GEN S,long prec)
! 470: {
! 471: long i,j,ls,ltop=avma,lbot;
! 472: GEN p1,nf,classgp,gen,M,U,H;
! 473: GEN sunit,card,sreg,res,pow,fa = cgetg(3, t_MAT);
! 474:
! 475: if (typ(S) != t_VEC) err(typeer,"bnfsunit");
! 476: bnf = checkbnf(bnf); nf=(GEN)bnf[7];
! 477: classgp=gmael(bnf,8,1);
! 478: gen = (GEN)classgp[3];
! 479:
! 480: sreg = gmael(bnf,8,2);
! 481: res=cgetg(7,t_VEC);
! 482: res[1]=res[2]=res[3]=lgetg(1,t_VEC);
! 483: res[4]=(long)sreg;
! 484: res[5]=(long)classgp;
! 485: res[6]=(long)S; ls=lg(S);
! 486:
! 487: /* M = relation matrix for the S class group (in terms of the class group
! 488: * generators given by gen)
! 489: * 1) ideals in S
! 490: */
! 491: M = cgetg(ls,t_MAT);
! 492: for (i=1; i<ls; i++)
! 493: {
! 494: p1 = (GEN)S[i]; checkprimeid(p1);
! 495: M[i] = (long)isprincipal(bnf,p1);
! 496: }
! 497: /* 2) relations from bnf class group */
! 498: M = concatsp(M, diagonal((GEN) classgp[2]));
! 499:
! 500: /* S class group */
! 501: H = hnfall(M); U = (GEN)H[2]; H= (GEN)H[1];
! 502: card = gun;
! 503: if (lg(H) > 1)
! 504: { /* non trivial (rare!) */
! 505: GEN SNF, ClS = cgetg(4,t_VEC);
! 506:
! 507: SNF = smith2(H); p1 = (GEN)SNF[3];
! 508: card = dethnf_i(p1);
! 509: ClS[1] = (long)card; /* h */
! 510: for(i=1; i<lg(p1); i++)
! 511: if (gcmp1((GEN)p1[i])) break;
! 512: setlg(p1,i);
! 513: ClS[2]=(long)p1; /* cyc */
! 514:
! 515: p1=cgetg(i,t_VEC); pow=invmat((GEN)SNF[1]);
! 516: fa[1] = (long)gen;
! 517: for(i--; i; i--)
! 518: {
! 519: fa[2] = pow[i];
! 520: p1[i] = (long)factorback(fa, nf);
! 521: }
! 522: ClS[3]=(long)p1; /* gen */
! 523: res[5]=(long) ClS;
! 524: }
! 525:
! 526: /* S-units */
! 527: if (ls>1)
! 528: {
! 529: GEN den, Sperm, perm, dep, B, U1 = U;
! 530: long lH, lB;
! 531:
! 532: /* U1 = upper left corner of U, invertible. S * U1 = principal ideals
! 533: * whose generators generate the S-units */
! 534: setlg(U1,ls); p1 = cgetg(ls, t_MAT); /* p1 is junk for mathnfspec */
! 535: for (i=1; i<ls; i++) { setlg(U1[i],ls); p1[i] = lgetg(1,t_COL); }
! 536: H = mathnfspec(U1,&perm,&dep,&B,&p1);
! 537: lH = lg(H);
! 538: lB = lg(B);
! 539: if (lg(dep) > 1 && lg(dep[1]) > 1) err(bugparier,"bnfsunit");
! 540: /* [ H B ] [ H^-1 - H^-1 B ]
! 541: * perm o HNF(U1) = [ 0 Id ], inverse = [ 0 Id ]
! 542: * (permute the rows)
! 543: * S * HNF(U1) = _integral_ generators for S-units = sunit */
! 544: Sperm = cgetg(ls, t_VEC); sunit = cgetg(ls, t_VEC);
! 545: for (i=1; i<ls; i++) Sperm[i] = S[perm[i]]; /* S o perm */
! 546:
! 547: setlg(Sperm, lH); fa[1] = (long)Sperm;
! 548: for (i=1; i<lH; i++)
! 549: {
! 550: fa[2] = H[i];
! 551: sunit[i] = (long)factorback(fa, nf);
! 552: }
! 553: for (i=1; i<lB; i++)
! 554: {
! 555: fa[2] = B[i]; j = lH-1 + i;
! 556: sunit[j] = (long)idealmul(nf, (GEN)Sperm[j], factorback(fa, nf));
! 557: }
! 558: for (i=1; i<ls; i++)
! 559: sunit[i] = isprincipalgenforce(bnf, (GEN)sunit[i])[2];
! 560:
! 561: p1 = cgetg(4,t_VEC);
! 562: den = dethnf_i(H); H = gmul(den, invmat(H));
! 563: p1[1] = (long)perm;
! 564: p1[2] = (long)concatsp(H, gneg(gmul(H,B))); /* top part of inverse * den */
! 565: p1[3] = (long)den; /* keep denominator separately */
! 566: sunit = basistoalg(nf,sunit);
! 567: res[2] = (long)p1; /* HNF in split form perm + (H B) [0 Id missing] */
! 568: res[1] = (long)lift_intern(sunit);
! 569: }
! 570:
! 571: /* S-regulator */
! 572: sreg = gmul(sreg,card);
! 573: for (i=1; i<ls; i++)
! 574: {
! 575: GEN p = (GEN)S[i];
! 576: if (typ(p) == t_VEC) p = (GEN) p[1];
! 577: sreg = gmul(sreg,glog(p,prec));
! 578: }
! 579: res[4]=(long) sreg; lbot=avma;
! 580: return gerepile(ltop,lbot,gcopy(res));
! 581: }
! 582:
! 583: /* cette fonction est l'equivalent de isunit, sauf qu'elle donne le resultat
! 584: * avec des s-unites: si x n'est pas une s-unite alors issunit=[]~;
! 585: * si x est une s-unite alors
! 586: * x=\prod_{i=0}^r {e_i^issunit[i]}*prod{i=r+1}^{r+s} {s_i^issunit[i]}
! 587: * ou les e_i sont les unites du corps (comme dans isunit)
! 588: * et les s_i sont les s-unites calculees par sunit (dans le meme ordre).
! 589: */
! 590: GEN
! 591: bnfissunit(GEN bnf,GEN suni,GEN x)
! 592: {
! 593: long lB,cH,i,k,ls,tetpil, av = avma;
! 594: GEN den,gen,S,v,p1,xp,xm,xb,N,HB,perm;
! 595:
! 596: bnf = checkbnf(bnf);
! 597: if (typ(suni)!=t_VEC || lg(suni)!=7) err(typeer,"bnfissunit");
! 598: switch (typ(x))
! 599: {
! 600: case t_INT: case t_FRAC: case t_FRACN:
! 601: case t_POL: case t_COL:
! 602: x = basistoalg(bnf,x); break;
! 603: case t_POLMOD: break;
! 604: default: err(typeer,"bnfissunit");
! 605: }
! 606: if (gcmp0(x)) return cgetg(1,t_COL);
! 607:
! 608: S = (GEN) suni[6]; ls=lg(S);
! 609: if (ls==1) return isunit(bnf,x);
! 610:
! 611: p1 = (GEN)suni[2];
! 612: perm = (GEN)p1[1];
! 613: HB = (GEN)p1[2]; den = (GEN)p1[3];
! 614: cH = lg(HB[1]) - 1;
! 615: lB = lg(HB) - cH;
! 616: xb = algtobasis(bnf,x); p1 = denom(content(xb));
! 617: N = mulii(gnorm(gmul(x,p1)), p1); /* relevant primes divide N */
! 618: v = cgetg(ls, t_VECSMALL);
! 619: for (i=1; i<ls; i++)
! 620: {
! 621: GEN P = (GEN)S[i];
! 622: v[i] = (resii(N, (GEN)P[1]) == gzero)? element_val(bnf,xb,P): 0;
! 623: }
! 624: /* here, x = S v */
! 625: p1 = cgetg(ls, t_COL);
! 626: for (i=1; i<ls; i++) p1[i] = lstoi(v[perm[i]]); /* p1 = v o perm */
! 627: v = gmul(HB, p1);
! 628: for (i=1; i<=cH; i++)
! 629: {
! 630: GEN w = gdiv((GEN)v[i], den);
! 631: if (typ(w) != t_INT) { avma = av; return cgetg(1,t_COL); }
! 632: v[i] = (long)w;
! 633: }
! 634: p1 += cH;
! 635: p1[0] = evaltyp(t_COL) | evallg(lB);
! 636: v = concatsp(v, p1); /* append bottom of p1 (= [0 Id] part) */
! 637:
! 638: xp = gun; xm = gun; gen = (GEN)suni[1];
! 639: for (i=1; i<ls; i++)
! 640: {
! 641: k = -itos((GEN)v[i]); if (!k) continue;
! 642: p1 = basistoalg(bnf, (GEN)gen[i]);
! 643: if (k > 0) xp = gmul(xp, gpuigs(p1, k));
! 644: else xm = gmul(xm, gpuigs(p1,-k));
! 645: }
! 646: if (xp != gun) x = gmul(x,xp);
! 647: if (xm != gun) x = gdiv(x,xm);
! 648: p1 = isunit(bnf,x);
! 649: if (lg(p1)==1) { avma = av; return cgetg(1,t_COL); }
! 650: tetpil=avma; return gerepile(av,tetpil,concat(p1,v));
! 651: }
! 652:
! 653: static void
! 654: vecconcat(GEN bnf,GEN relnf,GEN vec,GEN *prod,GEN *S1,GEN *S2)
! 655: {
! 656: long i;
! 657:
! 658: for (i=1; i<lg(vec); i++)
! 659: if (signe(resii(*prod,(GEN)vec[i])))
! 660: {
! 661: *prod=mulii(*prod,(GEN)vec[i]);
! 662: *S1=concatsp(*S1,primedec(bnf,(GEN)vec[i]));
! 663: *S2=concatsp(*S2,primedec(relnf,(GEN)vec[i]));
! 664: }
! 665: }
! 666:
! 667: /* bnf est le corps de base (buchinitfu).
! 668: * ext definit l'extension relative:
! 669: * ext[1] est une equation relative du corps,
! 670: * telle qu'une de ses racines engendre le corps sur Q.
! 671: * ext[2] exprime le generateur (y) du corps de base,
! 672: * en fonction de la racine (x) de ext[1],
! 673: * ext[3] est le buchinitfu (sur Q) de l'extension.
! 674:
! 675: * si flag=0 c'est qu'on sait a l'avance que l'extension est galoisienne,
! 676: * et dans ce cas la reponse est exacte.
! 677: * si flag>0 alors on ajoue dans S tous les ideaux qui divisent p<=flag.
! 678: * si flag<0 alors on ajoute dans S tous les ideaux qui divisent -flag.
! 679:
! 680: * la reponse est un vecteur v a 2 composantes telles que
! 681: * x=N(v[1])*v[2].
! 682: * x est une norme ssi v[2]=1.
! 683: */
! 684: GEN
! 685: rnfisnorm(GEN bnf,GEN ext,GEN x,long flag,long PREC)
! 686: {
! 687: long lgsunitrelnf,i,lbot, ltop = avma;
! 688: GEN relnf,aux,vec,tors,xnf,H,Y,M,A,suni,sunitrelnf,sunitnormnf,prod;
! 689: GEN res = cgetg(3,t_VEC), S1,S2;
! 690:
! 691: if (typ(ext)!=t_VEC || lg(ext)!=4) err (typeer,"bnfisnorm");
! 692: bnf = checkbnf(bnf); relnf = (GEN)ext[3];
! 693: if (gcmp0(x) || gcmp1(x) || (gcmp_1(x) && (degree((GEN)ext[1])&1)))
! 694: {
! 695: res[1]=lcopy(x); res[2]=un; return res;
! 696: }
! 697:
! 698: /* construction de l'ensemble S des ideaux
! 699: qui interviennent dans les solutions */
! 700:
! 701: prod=gun; S1=S2=cgetg(1,t_VEC);
! 702: if (!gcmp1(gmael3(relnf,8,1,1)))
! 703: {
! 704: GEN genclass=gmael3(relnf,8,1,3);
! 705: vec=cgetg(1,t_VEC);
! 706: for(i=1;i<lg(genclass);i++)
! 707: if (!gcmp1(ggcd(gmael4(relnf,8,1,2,i), stoi(degree((GEN)ext[1])))))
! 708: vec=concatsp(vec,(GEN)factor(gmael3(genclass,i,1,1))[1]);
! 709: vecconcat(bnf,relnf,vec,&prod,&S1,&S2);
! 710: }
! 711:
! 712: if (flag>1)
! 713: {
! 714: for (i=2; i<=flag; i++)
! 715: if (isprime(stoi(i)) && signe(resis(prod,i)))
! 716: {
! 717: prod=mulis(prod,i);
! 718: S1=concatsp(S1,primedec(bnf,stoi(i)));
! 719: S2=concatsp(S2,primedec(relnf,stoi(i)));
! 720: }
! 721: }
! 722: else if (flag<0)
! 723: vecconcat(bnf,relnf,(GEN)factor(stoi(-flag))[1],&prod,&S1,&S2);
! 724:
! 725: if (flag)
! 726: {
! 727: GEN normdiscrel=divii(gmael(relnf,7,3),
! 728: gpuigs(gmael(bnf,7,3),lg(ext[1])-3));
! 729: vecconcat(bnf,relnf,(GEN) factor(absi(normdiscrel))[1],
! 730: &prod,&S1,&S2);
! 731: }
! 732: vec=(GEN) idealfactor(bnf,x)[1]; aux=cgetg(2,t_VEC);
! 733: for (i=1; i<lg(vec); i++)
! 734: if (signe(resii(prod,gmael(vec,i,1))))
! 735: {
! 736: aux[1]=vec[i]; S1=concatsp(S1,aux);
! 737: }
! 738: xnf=lift(x);
! 739: xnf=gsubst(xnf,varn(xnf),(GEN)ext[2]);
! 740: vec=(GEN) idealfactor(relnf,xnf)[1];
! 741: for (i=1; i<lg(vec); i++)
! 742: if (signe(resii(prod,gmael(vec,i,1))))
! 743: {
! 744: aux[1]=vec[i]; S2=concatsp(S2,aux);
! 745: }
! 746:
! 747: res[1]=un; res[2]=(long)x;
! 748: tors=cgetg(2,t_VEC); tors[1]=mael3(relnf,8,4,2);
! 749:
! 750: /* calcul sur les S-unites */
! 751:
! 752: suni=bnfsunit(bnf,S1,PREC);
! 753: A=lift(bnfissunit(bnf,suni,x));
! 754: sunitrelnf=(GEN) bnfsunit(relnf,S2,PREC)[1];
! 755: if (lg(sunitrelnf)>1)
! 756: {
! 757: sunitrelnf=lift(basistoalg(relnf,sunitrelnf));
! 758: sunitrelnf=concatsp(tors,sunitrelnf);
! 759: }
! 760: else sunitrelnf=tors;
! 761: aux=(GEN)relnf[8];
! 762: if (lg(aux)>=6) aux=(GEN)aux[5];
! 763: else
! 764: {
! 765: aux=buchfu(relnf);
! 766: if(gcmp0((GEN)aux[2]))
! 767: err(talker,"please increase precision to have units in bnfisnorm");
! 768: aux=(GEN)aux[1];
! 769: }
! 770: if (lg(aux)>1)
! 771: sunitrelnf=concatsp(gtrans(aux),sunitrelnf);
! 772: lgsunitrelnf=lg(sunitrelnf);
! 773: M=cgetg(lgsunitrelnf+1,t_MAT);
! 774: sunitnormnf=cgetg(lgsunitrelnf,t_VEC);
! 775: for (i=1; i<lgsunitrelnf; i++)
! 776: {
! 777: sunitnormnf[i]=lnorm(gmodulcp((GEN) sunitrelnf[i],(GEN)ext[1]));
! 778: M[i]=llift(bnfissunit(bnf,suni,(GEN) sunitnormnf[i]));
! 779: }
! 780: M[lgsunitrelnf]=lgetg(lg(A),t_COL);
! 781: for (i=1; i<lg(A); i++) mael(M,lgsunitrelnf,i)=zero;
! 782: mael(M,lgsunitrelnf,lg(mael(bnf,7,6))-1)=mael3(bnf,8,4,1);
! 783: H=hnfall(M); Y=inverseimage(gmul(M,(GEN) H[2]),A);
! 784: Y=gmul((GEN) H[2],Y);
! 785: for (aux=(GEN)res[1],i=1; i<lgsunitrelnf; i++)
! 786: aux=gmul(aux,gpuigs(gmodulcp((GEN) sunitrelnf[i],(GEN)ext[1]),
! 787: itos(gfloor((GEN)Y[i]))));
! 788: res[1]=(long)aux;
! 789: res[2]=ldiv(x,gnorm(gmodulcp(lift(aux),(GEN)ext[1])));
! 790:
! 791: lbot=avma; return gerepile(ltop,lbot,gcopy(res));
! 792: }
! 793:
! 794: GEN
! 795: bnfisnorm(GEN bnf,GEN x,long flag,long PREC)
! 796: {
! 797: long ltop = avma, lbot;
! 798: GEN ext = cgetg(4,t_VEC);
! 799:
! 800: bnf = checkbnf(bnf);
! 801: ext[1] = mael(bnf,7,1);
! 802: ext[2] = zero;
! 803: ext[3] = (long) bnf;
! 804: bnf = buchinitfu(polx[MAXVARN],NULL,NULL,0); lbot = avma;
! 805: return gerepile(ltop,lbot,rnfisnorm(bnf,ext,x,flag,PREC));
! 806: }
! 807:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>