Annotation of OpenXM_contrib/pari/src/modules/thue.c, Revision 1.1
1.1 ! maekawa 1: /* thue.c -- Thue equation solver. In all the forthcoming remarks, "paper"
! 2: * designs the paper "Thue Equations of High Degree", by Yu. Bilu and
! 3: * G. Hanrot, J. Number Theory (1996). Note that numbering of the constants
! 4: * is that of Hanrot's thesis rather than that of the paper.
! 5: * The last part of the program (bnfisintnorm) was written by K. Belabas.
! 6: */
! 7: /* $Id: thue.c,v 1.1.1.1 1999/09/16 13:48:20 karim Exp $ */
! 8: #include "pari.h"
! 9:
! 10: static int curne,r,s,t,deg,Prec,ConstPrec,numroot;
! 11: static GEN c1,c2,c3,c4,c5,c6,c7,c8,c10,c11,c12,c13,c14,c15,B0,x1,x2,x3,x0;
! 12: static GEN halpha,eps3,gdeg,A,MatNE,roo,MatFU,Delta,Lambda,delta,lambda;
! 13: static GEN Vect2,SOL,uftot;
! 14:
! 15: GEN bnfisintnorm(GEN, GEN);
! 16:
! 17: /* Check whether tnf is a valid structure */
! 18: static int
! 19: checktnf(GEN tnf)
! 20: {
! 21: if (typ(tnf)!=t_VEC || (lg(tnf)!=8 && lg(tnf)!=3)) return 0;
! 22: if (typ(tnf[1])!=t_POL) return 0;
! 23: if (lg(tnf) != 8) return 1; /* s=0 */
! 24:
! 25: deg=lgef(tnf[1])-3;
! 26: if (deg<=2) err(talker,"invalid polynomial in thue (need deg>2)");
! 27: s=sturm((GEN)tnf[1]); t=(deg-s)>>1; r=s+t-1;
! 28: (void)checkbnf((GEN)tnf[2]);
! 29: if (typ(tnf[3]) != t_COL || lg(tnf[3]) != deg+1) return 0;
! 30: if (typ(tnf[4]) != t_COL || lg(tnf[4]) != r+1) return 0;
! 31: if (typ(tnf[5]) != t_MAT || lg(tnf[5]) != r+1
! 32: || lg(gmael(tnf,5,1)) != deg+1) return 0;
! 33: if (typ(tnf[6]) != t_MAT || lg(tnf[6])!=r+1
! 34: || lg(gmael(tnf,6,1)) != r+1) return 0;
! 35: if (typ(tnf[7]) != t_VEC || lg(tnf[7]) != 7) return 0;
! 36: return 1;
! 37: }
! 38:
! 39: static GEN distoZ(GEN z)
! 40: {
! 41: GEN p1=gfrac(z);
! 42: return gmin(p1, gsub(gun,p1));
! 43: }
! 44:
! 45: /* Check whether a solution has already been found */
! 46: static int
! 47: _thue_new(GEN zz)
! 48: {
! 49: int i;
! 50: for (i=1; i<lg(SOL); i++)
! 51: if (gegal(zz,(GEN)SOL[i])) return 0;
! 52: return 1;
! 53: }
! 54:
! 55: /* Compensates rounding errors for computation/display of the constants */
! 56: static GEN
! 57: myround(GEN Cst, GEN upd)
! 58: {
! 59: return gmul(Cst, gadd(gun, gmul(upd,gpuigs(stoi(10),-10))));
! 60: }
! 61:
! 62: /* Returns the index of the largest element in a vector */
! 63: static int
! 64: Vecmax(GEN Vec, int size)
! 65: {
! 66: int k, tno = 1;
! 67: GEN tmax = (GEN)Vec[1];
! 68: for (k=2; k<=size; k++)
! 69: if (gcmp((GEN)Vec[k],tmax)==1) { tmax=(GEN)Vec[k]; tno=k; }
! 70: return tno;
! 71: }
! 72:
! 73: /* Performs basic computations concerning the equation: buchinitfu, c1, c2 */
! 74: static void
! 75: inithue(GEN poly, long flag)
! 76: {
! 77: GEN roo2, tmp, gpmin, de;
! 78: int k,j;
! 79:
! 80: x0=gzero; x1=gzero; deg=lgef(poly)-3; gdeg=stoi(deg);
! 81:
! 82: if (!uftot)
! 83: {
! 84: uftot=bnfinit0(poly,1,NULL,Prec);
! 85: if (flag) certifybuchall(uftot);
! 86: s=itos(gmael3(uftot,7,2,1));
! 87: t=itos(gmael3(uftot,7,2,2));
! 88: }
! 89: /* Switch the roots to get the usual order */
! 90: roo=roots(poly, Prec); roo2=cgetg(deg+1,t_COL);
! 91: for (k=1; k<=s; k++) roo2[k]=roo[k];
! 92: for (k=1; k<=t; k++)
! 93: {
! 94: roo2[k+s]=roo[2*k-1+s];
! 95: roo2[k+s+t]=lconj((GEN)roo2[k+s]);
! 96: }
! 97: roo=roo2;
! 98:
! 99: r=s+t-1; halpha=gun;
! 100: for (k=1; k<=deg; k++)
! 101: halpha = gmul(halpha,gmax(gun,gabs((GEN)roo[k],Prec)));
! 102: halpha=gdiv(glog(halpha,Prec),gdeg);
! 103:
! 104: de=derivpol(poly); c1=gabs(poleval(de,(GEN)roo[1]),Prec);
! 105: for (k=2; k<=s; k++)
! 106: {
! 107: tmp=gabs(poleval(de,(GEN)roo[k]),Prec);
! 108: if (gcmp(tmp,c1)==-1) c1=tmp;
! 109: }
! 110:
! 111: c1=gdiv(gpui(gdeux,gsub(gdeg,gun),Prec),c1); c1=myround(c1,gun);
! 112: c2=gabs(gsub((GEN)roo[1],(GEN)roo[2]),Prec);
! 113:
! 114: for (k=1; k<=deg; k++)
! 115: for (j=k+1; j<=deg; j++)
! 116: {
! 117: tmp=gabs(gsub((GEN)roo[j],(GEN)roo[k]),Prec);
! 118: if (gcmp(c2,tmp)==1) c2=tmp;
! 119: }
! 120:
! 121: c2=myround(c2,stoi(-1));
! 122: if (t==0) x0=gun;
! 123: else
! 124: {
! 125: gpmin=gabs(poleval(de,(GEN)roo[s+1]),Prec);
! 126: for (k=2; k<=t; k++)
! 127: {
! 128: tmp=gabs(poleval(de,(GEN)roo[s+k]),Prec);
! 129: if (gcmp(tmp,gpmin)==-1) gpmin=tmp;
! 130: }
! 131:
! 132: /* Compute x0. See paper, Prop. 2.2.1 */
! 133: x0=gpui(gdiv(gpui(gdeux,gsub(gdeg,gun),Prec),
! 134: gmul(gpmin,
! 135: gabs((GEN)gimag(roo)[Vecmax(gabs(gimag(roo),Prec),deg)],Prec))),
! 136: ginv(gdeg),Prec);
! 137: }
! 138:
! 139: if (DEBUGLEVEL >=2) fprintferr("c1 = %Z\nc2 = %Z\n", c1, c2);
! 140:
! 141: }
! 142:
! 143: /* Computation of M, its inverse A and check of the precision (see paper) */
! 144: static void
! 145: T_A_Matrices()
! 146: {
! 147: GEN mask, eps1, eps2, nia, m1, IntM;
! 148: int i,j;
! 149:
! 150: m1=glog(gabs(MatFU,Prec),Prec); mask=gsub(gpui(gdeux,stoi(r),Prec),gun);
! 151: m1=matextract(m1,mask,mask);
! 152:
! 153: A=invmat(m1); IntM=gsub(gmul(A,m1),idmat(r));
! 154:
! 155: eps2=gzero;
! 156: for (i=1; i<=r; i++)
! 157: for (j=1; j<=r; j++)
! 158: if (gcmp(eps2,gabs(gcoeff(IntM,i,j),20)) == -1)
! 159: eps2=gabs(gcoeff(IntM,i,j),20);
! 160:
! 161: eps1=gpui(gdeux,stoi((Prec-2)*32),Prec); eps2=gadd(eps2,ginv(eps1));
! 162:
! 163: nia=gzero;
! 164: for (i=1; i<=r; i++)
! 165: for (j=1; j<=r; j++)
! 166: if (gcmp(nia,gabs(gcoeff(A,i,j),20)) == -1)
! 167: nia = gabs(gcoeff(A,i,j),20);
! 168:
! 169: /* Check for the precision in matrix inversion. See paper, Lemma 2.4.2. */
! 170: if (gcmp(gmul(gadd(gmul(stoi(r),gmul(nia,eps1)),eps2),
! 171: gmul(gdeux,stoi(r))),gun) == -1)
! 172: err(talker,"not enough precision in thue");
! 173:
! 174: eps3=gmul(gdeux,gmul(gmul(gsqr(stoi(r)),nia),
! 175: gadd(gmul(stoi(r),gdiv(nia,eps1)),eps2)));
! 176: myround(eps3,gun);
! 177:
! 178: if (DEBUGLEVEL>=2) fprintferr("epsilon_3 -> %Z\n",eps3);
! 179: }
! 180:
! 181: /* Computation of the constants c5, c7, c10, c12, c15 */
! 182: static void
! 183: ComputeConstants()
! 184: {
! 185: int k;
! 186:
! 187: GEN Vect;
! 188:
! 189: Vect=cgetg(r+1,t_COL); for (k=1; k<=r; k++) Vect[k]=un;
! 190: if (numroot <= r) Vect[numroot]=lsub(gun,gdeg);
! 191:
! 192: Delta=gmul(A,Vect);
! 193:
! 194: c5=(GEN)(gabs(Delta,Prec)[Vecmax(gabs(Delta,Prec),r)]);
! 195: c5=myround(c5,gun); c7=mulsr(r,c5);
! 196: c10=divsr(deg,c7); c13=divsr(deg,c5);
! 197:
! 198:
! 199: if (DEBUGLEVEL>=2)
! 200: {
! 201: fprintferr("c5 = %Z\n",c5);
! 202: fprintferr("c7 = %Z\n",c7);
! 203: fprintferr("c10 = %Z\n",c10);
! 204: fprintferr("c13 = %Z\n",c13);
! 205: }
! 206: }
! 207:
! 208: /* Computation of the constants c6, c8, c9 */
! 209: static void
! 210: ComputeConstants2(GEN poly, GEN rhs)
! 211: {
! 212: GEN Vect1, tmp;
! 213: int k;
! 214:
! 215: Vect1=cgetg(r+1,t_COL);
! 216: for (k=1; k<=r; k++) Vect1[k]=un;
! 217: Vect1=gmul(gabs(A,ConstPrec),Vect1);
! 218:
! 219:
! 220: Vect2=cgetg(r+1,t_COL);
! 221: for (k=1; k<=r; k++)
! 222: { if (k!=numroot)
! 223: { Vect2[k]=llog(gabs(gdiv(gsub((GEN)roo[numroot],(GEN)roo[k]),
! 224: gcoeff(MatNE,k,curne)),Prec),Prec); }
! 225: else { Vect2[k]=llog(gabs(gdiv(rhs,gmul(poleval(derivpol(poly)
! 226: ,(GEN)roo[numroot]),
! 227: gcoeff(MatNE,k,curne))),Prec),Prec);
! 228: }
! 229: }
! 230: Lambda=gmul(A,Vect2);
! 231:
! 232: tmp=(GEN)Vect1[Vecmax(Vect1,r)];
! 233: x2=gmax(x1,gpui(mulsr(10,mulrr(c4,tmp)),ginv(gdeg),ConstPrec));
! 234: c14=mulrr(c4,tmp);
! 235:
! 236: c6=gabs((GEN)Lambda[Vecmax(gabs(Lambda,ConstPrec),r)],ConstPrec);
! 237: c6=addrr(c6,dbltor(0.1)); c6=myround(c6,gun);
! 238:
! 239: c8=addrr(dbltor(1.23),mulsr(r,c6));
! 240: c11=mulrr(mulsr(2,c3),gexp(divrr(mulsr(deg,c8),c7),ConstPrec));
! 241:
! 242: tmp=gexp(divrr(mulsr(deg,c6),c5),ConstPrec);
! 243: c12=mulrr(mulsr(2,c3),tmp);
! 244: c15=mulsr(2,mulrr(c14,tmp));
! 245:
! 246: if (DEBUGLEVEL>=2)
! 247: {
! 248: fprintferr("c6 = %Z\n",c6);
! 249: fprintferr("c8 = %Z\n",c8);
! 250: fprintferr("c11 = %Z\n",c11);
! 251: fprintferr("c12 = %Z\n",c12);
! 252: fprintferr("c14 = %Z\n",c14);
! 253: fprintferr("c15 = %Z\n",c15);
! 254: }
! 255: }
! 256:
! 257: /* Computation of the logarithmic heights of the units */
! 258: static GEN
! 259: Logarithmic_Height(int s)
! 260: {
! 261: int i;
! 262: GEN LH=gun,mat;
! 263:
! 264: mat=gabs(MatFU,Prec);
! 265: for (i=1; i<=deg; i++)
! 266: LH = gmul(LH,gmax(gun,gabs(gcoeff(mat,i,s),Prec)));
! 267: return gmul(gdeux,gdiv(glog(LH,Prec),gdeg));
! 268: }
! 269:
! 270: /* Computation of the matrix ((\sigma_i(\eta_j)) used for M_1 and
! 271: the computation of logarithmic heights */
! 272: static void
! 273: Compute_Fund_Units(GEN uf)
! 274: {
! 275: int i,j;
! 276: MatFU=cgetg(r+1,t_MAT);
! 277:
! 278: for (i=1; i<=r; i++)
! 279: MatFU[i]=lgetg(deg+1,t_COL);
! 280: for (i=1; i<=r; i++)
! 281: {
! 282: if (typ(uf[i])!=t_POL) err(talker,"incorrect system of units");
! 283: for (j=1; j<=deg; j++)
! 284: coeff(MatFU,j,i)=(long)poleval((GEN)uf[i],(GEN)roo[j]);
! 285: }
! 286: }
! 287:
! 288: /* Computation of the conjugates of the solutions to the norm equation */
! 289: static void
! 290: Conj_Norm_Eq(GEN ne, GEN *Hmu)
! 291: {
! 292: int p,q,nesol,x;
! 293:
! 294: nesol=lg(ne); MatNE=(GEN)cgetg(nesol,t_MAT); (*Hmu)=cgetg(nesol,t_COL);
! 295:
! 296: for (p=1; p<nesol; p++) { MatNE[p]=lgetg(deg+1,t_COL); (*Hmu)[p]=un; }
! 297: for (q=1; q<nesol; q++)
! 298: {
! 299: x=typ(ne[q]);
! 300: if (x!=t_INT && x!=t_POL)
! 301: err(talker,"incorrect solutions of norm equation");
! 302: for (p=1; p<=deg; p++)
! 303: {
! 304: coeff(MatNE,p,q)=(long)poleval((GEN)ne[q],(GEN)roo[p]);
! 305: /* Logarithmic height of the solutions of the norm equation */
! 306: (*Hmu)[q]=lmul((GEN)(*Hmu)[q],gmax(gun,gabs(gcoeff(MatNE,p,q),Prec)));
! 307: }
! 308: }
! 309: for (q=1; q<nesol; q++)
! 310: (*Hmu)[q]=ldiv(glog((GEN)(*Hmu)[q],Prec),gdeg);
! 311: }
! 312:
! 313: /* Compute Baker's bound c11, and B_0, the bound for the b_i's .*/
! 314: static void
! 315: Baker(GEN ALH, GEN Hmu)
! 316: {
! 317: GEN c9=gun, gbak, hb0=gzero;
! 318: int k,i1,i2;
! 319:
! 320: gbak = gmul(gmul(gdeg,gsub(gdeg,gun)),gsub(gdeg,gdeux));
! 321:
! 322: switch (numroot) {
! 323: case 1: i1=2; i2=3; break;
! 324: case 2: i1=1; i2=3; break;
! 325: case 3: i1=1; i2=2; break;
! 326: default: i1=1; i2=2; break;
! 327: }
! 328:
! 329: /* For the symbols used for the computation of c11, see paper, Thm 2.3.1 */
! 330: /* Compute h_1....h_r */
! 331: for (k=1; k<=r; k++)
! 332: {
! 333: c9=gmul(c9,gmax((GEN)ALH[k],
! 334: gmax(ginv(gbak),
! 335: gdiv(gabs(glog(gdiv(gcoeff(MatFU,i1,k),
! 336: gcoeff(MatFU,i2,k)),
! 337: Prec),Prec),gbak))));
! 338: }
! 339:
! 340: /* Compute a bound for the h_0 */
! 341: hb0=gadd(gmul(stoi(4),halpha),gadd(gmul(gdeux,(GEN)Hmu[curne]),
! 342: gmul(gdeux,glog(gdeux,Prec))));
! 343: hb0=gmax(hb0,gmax(ginv(gbak),
! 344: gdiv(gabs(glog(gdiv(gmul(gsub((GEN)roo[numroot],
! 345: (GEN)roo[i2]),
! 346: gcoeff(MatNE,i1,curne)),
! 347: gmul(gsub((GEN)roo[numroot],
! 348: (GEN)roo[i1]),
! 349: gcoeff(MatNE,i2,curne))),
! 350: Prec),Prec),gbak)));
! 351: c9=gmul(c9,hb0);
! 352: /* Multiply c9 by the "constant" factor */
! 353: c9=gmul(c9,gmul(gmul(gmul(stoi(18),mppi(Prec)),gpui(stoi(32),stoi(4+r),Prec)),
! 354: gmul(gmul(mpfact(r+3), gpowgs(gmul(gbak,stoi(r+2)), r+3)),
! 355: glog(gmul(gdeux,gmul(gbak,stoi(r+2))),Prec))));
! 356: c9=myround(c9,gun);
! 357: /* Compute B0 according to Lemma 2.3.3 */
! 358: B0=gmax(gexp(gun,Prec),
! 359: mulsr(2,divrr(addrr(mulrr(c9,glog(divrr(c9,c10),ConstPrec)),
! 360: glog(c11,ConstPrec)),c10)));
! 361:
! 362: if (DEBUGLEVEL>=2) fprintferr("Baker -> %Z\nB0 -> %Z\n",c9,B0);
! 363: }
! 364:
! 365: /* Compute delta and lambda */
! 366: static void
! 367: Create_CF_Values(int i1, int i2, GEN *errdelta)
! 368: {
! 369: GEN eps5;
! 370:
! 371: if (r>1)
! 372: {
! 373: delta=divrr((GEN)Delta[i2],(GEN)Delta[i1]);
! 374: eps5=mulrs(eps3,r);
! 375: *errdelta=mulrr(addsr(1,delta),
! 376: divrr(eps5,subrr(gabs((GEN)Delta[i1],ConstPrec),eps5)));
! 377:
! 378: lambda=gdiv(gsub(gmul((GEN)Delta[i2],(GEN)Lambda[i1]),
! 379: gmul((GEN)Delta[i1],(GEN)Lambda[i2])),
! 380: (GEN)Delta[i1]);
! 381: }
! 382: else
! 383: {
! 384: GEN Pi2 = gmul2n(mppi(Prec),1);
! 385: delta=gdiv(gcoeff(MatFU,2,1),gcoeff(MatFU,3,1));
! 386: delta=gdiv(garg(delta,Prec),Pi2);
! 387: *errdelta=gdiv(gpui(gdeux,stoi(-(Prec-2)*32+1),Prec),
! 388: gabs(gcoeff(MatFU,2,1),Prec));
! 389: lambda=gmul(gdiv(gsub((GEN)roo[numroot],(GEN)roo[2]),
! 390: gsub((GEN)roo[numroot],(GEN)roo[3])),
! 391: gdiv(gcoeff(MatNE,3,curne),gcoeff(MatNE,2,curne)));
! 392: lambda=gdiv(garg(lambda,Prec),Pi2);
! 393: }
! 394: if (DEBUGLEVEL>=2) outerr(*errdelta);
! 395: }
! 396:
! 397: /* Try to reduce the bound through continued fractions; see paper. */
! 398: static int
! 399: CF_First_Pass(GEN kappa, GEN errdelta)
! 400: {
! 401: GEN q,ql,qd,l0;
! 402:
! 403: if (gcmp(gmul(dbltor(0.1),gsqr(mulri(B0,kappa))),ginv(errdelta))==1)
! 404: {
! 405: return -1;
! 406: }
! 407:
! 408: q=denom(bestappr(delta, mulir(kappa, B0))); ql=mulir(q,lambda);
! 409: qd=gmul(q,delta); ql=gabs(subri(ql, ground(ql)),Prec);
! 410: qd=gabs(mulrr(subri(qd,ground(qd)),B0),Prec);
! 411: l0=subrr(ql,addrr(qd,divri(dbltor(0.1),kappa)));
! 412: if (signe(l0) <= 0)
! 413: {
! 414: if (DEBUGLEVEL>=2)
! 415: fprintferr("CF_First_Pass failed. Trying again with larger kappa\n");
! 416: return 0;
! 417: }
! 418:
! 419: if (r>1)
! 420: B0=divrr(glog(divrr(mulir(q,c15),l0),ConstPrec),c13);
! 421: else
! 422: B0=divrr(glog(divrr(mulir(q,c11),mulrr(l0,gmul2n(mppi(ConstPrec),1))),ConstPrec),c10);
! 423:
! 424: if (DEBUGLEVEL>=2)
! 425: fprintferr("CF_First_Pass successful !!\nB0 -> %Z\n",B0);
! 426: return 1;
! 427: }
! 428:
! 429: /* Check whether a "potential" solution is truly a solution. */
! 430: static void
! 431: Check_Solutions(GEN xmay1, GEN xmay2, GEN poly, GEN rhs)
! 432: {
! 433: GEN xx1, xx2, yy1, yy2, zz, u;
! 434:
! 435: yy1=ground(greal(gdiv(gsub(xmay2,xmay1), gsub((GEN)roo[1],(GEN)roo[2]))));
! 436: yy2=gneg(yy1);
! 437:
! 438: xx1=greal(gadd(xmay1,gmul((GEN)roo[1],yy1)));
! 439: xx2=gneg(xx1);
! 440:
! 441: if (gcmp(distoZ(xx1),dbltor(0.0001))==-1)
! 442: {
! 443: xx1=ground(xx1);
! 444: if (!gcmp0(yy1))
! 445: {
! 446: if (gegal(gmul(poleval(poly,gdiv(xx1,yy1)),
! 447: gpui(yy1,gdeg,Prec)),(GEN)rhs))
! 448: {
! 449: zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC);
! 450: u[1]=(long)xx1; u[2]=(long)yy1; zz[1]=(long)u;
! 451: if (_thue_new(u)) SOL=concatsp(SOL,zz);
! 452: }
! 453: }
! 454: else if (gegal(gpui(xx1,gdeg,Prec),(GEN)rhs))
! 455: {
! 456: zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC);
! 457: u[1]=(long)xx1; u[2]=(long)gzero; zz[1]=(long)u;
! 458: if (_thue_new(u)) SOL=concatsp(SOL,zz);
! 459: }
! 460:
! 461: xx2=ground(xx2);
! 462: if (!gcmp0(yy2))
! 463: {
! 464: if (gegal(gmul(poleval(poly,gdiv(xx2,yy2)),
! 465: gpui(yy2,gdeg,Prec)),(GEN)rhs))
! 466: {
! 467: zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC);
! 468: u[1]=(long)xx2; u[2]=(long)yy2; zz[1]=(long)u;
! 469: if (_thue_new(u)) SOL=concatsp(SOL,zz);
! 470: }
! 471: }
! 472: else if (gegal(gpui(xx2,gdeg,Prec),(GEN)rhs))
! 473: {
! 474: zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC);
! 475: u[1]=(long)xx2; u[2]=(long)gzero; zz[1]=(long)u;
! 476: if (_thue_new(u)) SOL=concatsp(SOL,zz);
! 477: }
! 478: }
! 479: }
! 480:
! 481: static GEN
! 482: GuessQi(GEN *q1, GEN *q2, GEN *q3)
! 483: {
! 484: GEN C, Lat, eps;
! 485:
! 486: C=gpui(stoi(10),stoi(10),Prec);
! 487: Lat=idmat(3); mael(Lat,1,3)=(long)C; mael(Lat,2,3)=lround(gmul(C,delta));
! 488: mael(Lat,3,3)=lround(gmul(C,lambda));
! 489:
! 490: Lat=lllint(Lat);
! 491: *q1=gmael(Lat,1,1); *q2=gmael(Lat,1,2); *q3=gmael(Lat,1,3);
! 492:
! 493: eps=gabs(gadd(gadd(*q1,gmul(*q2,delta)),gmul(*q3,lambda)),Prec);
! 494: return(eps);
! 495: }
! 496:
! 497: static void
! 498: TotRat()
! 499: {
! 500: err(bugparier,"thue (totally rational case)");
! 501: }
! 502:
! 503: /* Check for solutions under a small bound (see paper) */
! 504: static void
! 505: Check_Small(int bound, GEN poly, GEN rhs)
! 506: {
! 507: GEN interm, xx, zz, u, maxr, tmp, ypot, xxn, xxnm1, yy;
! 508: long av = avma, lim = stack_lim(av,1);
! 509: int x, j, bsupy, y;
! 510: double bndyx;
! 511:
! 512: maxr=gabs((GEN)roo[1],Prec); for(j=1; j<=deg; j++)
! 513: { if(gcmp(tmp=gabs((GEN)roo[j],Prec),maxr)==1) maxr=tmp; }
! 514:
! 515: bndyx=gtodouble(gadd(gpui(gabs(rhs,Prec),ginv(gdeg),Prec),maxr));
! 516:
! 517: for (x=-bound; x<=bound; x++)
! 518: {
! 519: if (low_stack(lim,stack_lim(av,1)))
! 520: {
! 521: if(DEBUGMEM>1) err(warnmem,"Check_small");
! 522: SOL = gerepileupto(av, gcopy(SOL));
! 523: }
! 524: if (x==0)
! 525: {
! 526: ypot=gmul(stoi(gsigne(rhs)),ground(gpui(gabs(rhs,0),ginv(gdeg),Prec)));
! 527: if (gegal(gpui(ypot,gdeg,0),rhs))
! 528: {
! 529: zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC);
! 530: u[1]=(long)ypot; u[2]=(long)gzero; zz[1]=(long)u;
! 531: if (_thue_new(u)) SOL=concatsp(SOL,zz);
! 532: }
! 533: if (gegal(gpui(gneg(ypot),gdeg,0),rhs))
! 534: {
! 535: zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC);
! 536: u[1]=(long)gneg(ypot); u[2]=(long)gzero; zz[1]=(long)u;
! 537: if (_thue_new(u)) SOL=concatsp(SOL,zz);
! 538: }
! 539: }
! 540: else
! 541: {
! 542: bsupy=(int)(x>0?bndyx*x:-bndyx*x);
! 543:
! 544: xx=stoi(x); xxn=gpui(xx,gdeg,Prec);
! 545: interm=gsub((GEN)rhs,gmul(xxn,(GEN)poly[2]));
! 546:
! 547: /* Verifier ... */
! 548: xxnm1=xxn; j=2;
! 549: while(gegal(interm,gzero))
! 550: {
! 551: xxnm1=gdiv(xxnm1,xx);
! 552: interm=gmul((GEN)poly[++j],xxnm1);
! 553: }
! 554:
! 555: for(y=-bsupy; y<=bsupy; y++)
! 556: {
! 557: yy=stoi(y);
! 558: if(y==0) {
! 559: if (gegal(gmul((GEN)poly[2],xxn),rhs))
! 560: {
! 561: zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC);
! 562: u[1]=(long)gzero; u[2]=(long)xx; zz[1]=(long)u;
! 563: if (_thue_new(u)) SOL=concatsp(SOL,zz);
! 564: }
! 565: }
! 566: else if(gegal(gmod(interm,yy),gzero))
! 567: if(gegal(poleval(poly,gdiv(yy,xx)),gdiv(rhs,xxn)))
! 568: /* Remplacer par un eval *homogene* */
! 569: {
! 570: zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC);
! 571: u[1]=(long)yy; u[2]=(long)xx; zz[1]=(long)u;
! 572: if (_thue_new(u)) SOL=concatsp(SOL,zz);
! 573: }
! 574: }
! 575: }
! 576: }
! 577: }
! 578:
! 579: /* Computes [x]! */
! 580: static double
! 581: fact(double x)
! 582: {
! 583: double ft=1.0;
! 584: x=(int)x; while (x>1) { ft*=x; x--; }
! 585: return ft ;
! 586: }
! 587:
! 588: /* From a polynomial and optionally a system of fundamental units for the
! 589: * field defined by poly, computes all the relevant constants needed to solve
! 590: * the equation P(x,y)=a whenever the solutions of N_{ K/Q }(x)=a. Returns a
! 591: * "tnf" structure containing
! 592: * 1) the polynomial
! 593: * 2) the bnf (used to solve the norm equation)
! 594: * 3) roots, with presumably enough precision
! 595: * 4) The logarithmic heights of units
! 596: * 5) The matrix of conjugates of units
! 597: * 6) its inverse
! 598: * 7) a few technical constants
! 599: */
! 600: GEN
! 601: thueinit(GEN poly, long flag, long prec)
! 602: {
! 603: GEN thueres,ALH,csts,c0;
! 604: long av,tetpil,k,st;
! 605: double d,dr;
! 606:
! 607: av=avma;
! 608:
! 609: uftot=0;
! 610: if (checktnf(poly)) { uftot=(GEN)poly[2]; poly=(GEN)poly[1]; }
! 611: else
! 612: if (typ(poly)!=t_POL) err(notpoler,"thueinit");
! 613:
! 614: if (!gisirreducible(poly)) err(redpoler,"thueinit");
! 615: st=sturm(poly);
! 616: if (st)
! 617: {
! 618: dr=(double)((st+lgef(poly)-5)>>1);
! 619: d=(double)lgef(poly)-3; d=d*(d-1)*(d-2);
! 620: /* Try to guess the precision by approximating Baker's bound.
! 621: * Note that the guess is most of the time pretty generous,
! 622: * ie 10 to 30 decimal digits above what is *really* necessary.
! 623: * Note that the limiting step is the reduction. See paper.
! 624: */
! 625: Prec=3 + (long)((5.83 + (dr+4)*5 + log(fact(dr+3)) + (dr+3)*log(dr+2) +
! 626: (dr+3)*log(d) + log(log(2*d*(dr+2))) + (dr+1)) / 10.);
! 627: ConstPrec=4;
! 628: if (Prec<prec) Prec = prec;
! 629: if (!checktnf(poly)) inithue(poly,flag);
! 630:
! 631: thueres=cgetg(8,t_VEC);
! 632: thueres[1]=(long)poly;
! 633: thueres[2]=(long)uftot;
! 634: thueres[3]=(long)roo;
! 635: Compute_Fund_Units(gmael(uftot,8,5));
! 636: ALH=cgetg(r+1,t_COL);
! 637: for (k=1; k<=r; k++) ALH[k]=(long)Logarithmic_Height(k);
! 638: thueres[4]=(long)ALH;
! 639: thueres[5]=(long)MatFU;
! 640: T_A_Matrices();
! 641: thueres[6]=(long)A;
! 642:
! 643: csts=cgetg(7,t_VEC);
! 644: csts[1]=(long)c1; csts[2]=(long)c2; csts[3]=(long)halpha;
! 645: csts[4]=(long)x0; csts[5]=(long)eps3;
! 646: csts[6]=(long)stoi(Prec);
! 647:
! 648: thueres[7]=(long)csts; tetpil=avma;
! 649: return gerepile(av,tetpil,gcopy(thueres));
! 650: }
! 651:
! 652: thueres=cgetg(3,t_VEC); c0=gun; Prec=4;
! 653: roo=roots(poly,Prec);
! 654: for (k=1; k<lg(roo); k++)
! 655: c0=gmul(c0, gimag((GEN)roo[k]));
! 656: c0=ginv(gabs(c0,Prec));
! 657: thueres[1]=(long)poly; thueres[2]=(long)c0;
! 658: tetpil=avma; return gerepile(av,tetpil,gcopy(thueres));
! 659: }
! 660:
! 661: /* Given a tnf structure as returned by thueinit, and a right-hand-side and
! 662: * optionally the solutions to the norm equation, returns the solutions to
! 663: * the Thue equation F(x,y)=a
! 664: */
! 665: GEN
! 666: thue(GEN thueres, GEN rhs, GEN ne)
! 667: {
! 668: GEN Kstart,Old_B0,ALH,errdelta,Hmu,c0,poly,csts,bd;
! 669: GEN xmay1,xmay2,b,zp1,tmp,q1,q2,q3,ep;
! 670: long Nb_It=0,upb,bi1,av,tetpil,i1,i2,i, flag,cf,fs;
! 671:
! 672: if (!checktnf(thueres)) err(talker,"not a tnf in thue");
! 673:
! 674: av=avma; SOL=cgetg(1,t_VEC);
! 675:
! 676: if (lg(thueres)==8)
! 677: {
! 678: poly=(GEN)thueres[1]; deg=lgef(poly)-3; gdeg=stoi(deg);
! 679: uftot=(GEN)thueres[2];
! 680: roo=gcopy((GEN)thueres[3]);
! 681: ALH=(GEN)thueres[4];
! 682: MatFU=gcopy((GEN)thueres[5]);
! 683: A=gcopy((GEN)thueres[6]);
! 684: csts=(GEN)thueres[7];
! 685:
! 686: if (!ne) ne = bnfisintnorm(uftot, rhs);
! 687: if (lg(ne)==1) { avma=av; return cgetg(1,t_VEC); }
! 688:
! 689: c1=gmul(gabs(rhs,Prec), (GEN)csts[1]); c2=(GEN)csts[2];
! 690: halpha=(GEN)csts[3];
! 691: if (t)
! 692: x0 = gmul((GEN)csts[4],gpui(gabs(rhs,Prec), ginv(gdeg), Prec));
! 693: eps3=(GEN)csts[5];
! 694: Prec=gtolong((GEN)csts[6]);
! 695: b=cgetg(r+1,t_COL);
! 696: tmp=divrr(c1,c2);
! 697: x1=gmax(x0,gpui(mulsr(2,tmp),ginv(gdeg),ConstPrec));
! 698: if(DEBUGLEVEL >=2) fprintferr("x1 -> %Z\n",x1);
! 699:
! 700: c3=mulrr(dbltor(1.39),tmp);
! 701: c4=mulsr(deg-1,c3);
! 702:
! 703: for (numroot=1; numroot<=s; numroot++)
! 704: {
! 705: ComputeConstants();
! 706: Conj_Norm_Eq(ne,&Hmu);
! 707: for (curne=1; curne<lg(ne); curne++)
! 708: {
! 709: ComputeConstants2(poly,rhs);
! 710: Baker(ALH,Hmu);
! 711:
! 712: i1=Vecmax(gabs(Delta,Prec),r);
! 713: if (i1!=1) i2=1; else i2=2;
! 714: do
! 715: {
! 716: fs=0;
! 717: Create_CF_Values(i1,i2,&errdelta);
! 718: if (DEBUGLEVEL>=2) fprintferr("Entering CF\n");
! 719: Old_B0=gmul(B0,gdeux);
! 720:
! 721: /* Try to reduce B0 while
! 722: * 1) there was less than 10 reductions
! 723: * 2) the previous reduction improved the bound of more than 0.1.
! 724: */
! 725: while (Nb_It<10 && gcmp(Old_B0,gadd(B0,dbltor(0.1))) == 1 && fs<2)
! 726: {
! 727: cf=0; Old_B0=B0; Nb_It++; Kstart=stoi(10);
! 728: while (!fs && CF_First_Pass(Kstart,errdelta) == 0 && cf < 8 )
! 729: {
! 730: cf++;
! 731: Kstart=mulis(Kstart,10);
! 732: }
! 733: if ( CF_First_Pass(Kstart,errdelta) == -1 )
! 734: { ne = gerepileupto(av, gcopy(ne)); Prec+=10;
! 735: if(DEBUGLEVEL>=2) fprintferr("Increasing precision\n");
! 736: thueres=thueinit(thueres,0,Prec);
! 737: return(thue(thueres,rhs,ne)); }
! 738:
! 739: if (cf==8 || fs) /* Semirational or totally rational case */
! 740: {
! 741: if (!fs)
! 742: { ep=GuessQi(&q1,&q2,&q3); }
! 743: bd=gmul(denom(bestappr(delta,gadd(B0,gabs(q2,Prec))))
! 744: ,delta);
! 745: bd=gabs(gsub(bd,ground(bd)),Prec);
! 746: if(gcmp(bd,ep)==1 && !gegal(q3, gzero))
! 747: {
! 748: fs=1;
! 749: B0=gdiv(glog(gdiv(gmul(q3,c15),gsub(bd,ep)), Prec),c13);
! 750: if (DEBUGLEVEL>=2)
! 751: fprintferr("Semirat. reduction ok. B0 -> %Z\n",B0);
! 752: }
! 753: else fs=2;
! 754: }
! 755: else fs=0;
! 756: Nb_It=0; B0=gmin(Old_B0,B0); upb=gtolong(gceil(B0));
! 757: }
! 758: i2++; if (i2==i1) i2++;
! 759: }
! 760: while (fs == 2 && i2 <= r);
! 761:
! 762: if (fs == 2) TotRat();
! 763:
! 764: if (DEBUGLEVEL >=2) fprintferr("x2 -> %Z\n",x2);
! 765:
! 766: /* For each possible value of b_i1, compute the b_i's
! 767: * and 2 conjugates of x-\alpha y. Then check.
! 768: */
! 769: zp1=dbltor(0.01);
! 770: x3=gmax(x2,gpui(mulsr(2,divrr(c14,zp1)),ginv(gdeg),ConstPrec));
! 771:
! 772: for (bi1=-upb; bi1<=upb; bi1++)
! 773: {
! 774: flag=1;
! 775: xmay1=gun; xmay2=gun;
! 776: for (i=1; i<=r; i++)
! 777: {
! 778: b[i]=(long)gdiv(gsub(gmul((GEN)Delta[i],stoi(bi1)),
! 779: gsub(gmul((GEN)Delta[i],(GEN)Lambda[i1]),
! 780: gmul((GEN)Delta[i1],(GEN)Lambda[i]))),
! 781: (GEN)Delta[i1]);
! 782: if (gcmp(distoZ((GEN)b[i]),zp1)==1) { flag=0; break; }
! 783: }
! 784:
! 785: if(flag)
! 786: {
! 787: for(i=1; i<=r; i++)
! 788: {
! 789: b[i]=lround((GEN)b[i]);
! 790: xmay1=gmul(xmay1,gpui(gcoeff(MatFU,1,i),(GEN)b[i],Prec));
! 791: xmay2=gmul(xmay2,gpui(gcoeff(MatFU,2,i),(GEN)b[i],Prec));
! 792: }
! 793: xmay1=gmul(xmay1,gcoeff(MatNE,1,curne));
! 794: xmay2=gmul(xmay2,gcoeff(MatNE,2,curne));
! 795: Check_Solutions(xmay1,xmay2,poly,rhs);
! 796: }
! 797: }
! 798: }
! 799: }
! 800: if (DEBUGLEVEL>=2) fprintferr("Checking for small solutions\n");
! 801: Check_Small((int)(gtodouble(x3)),poly,rhs);
! 802: tetpil=avma; return gerepile(av,tetpil,gcopy(SOL));
! 803: }
! 804:
! 805: /* Case s=0. All the solutions are "small". */
! 806: Prec=DEFAULTPREC; poly=(GEN)thueres[1]; deg=lgef(poly)-3;
! 807: gdeg=stoi(deg); c0=(GEN)thueres[2];
! 808: roo=roots(poly,Prec);
! 809: Check_Small(gtolong(ground(gpui(gmul((GEN)poly[2],gdiv(gabs(rhs,Prec),c0)),
! 810: ginv(gdeg),Prec) )), poly, rhs);
! 811: tetpil=avma; return gerepile(av,tetpil,gcopy(SOL));
! 812: }
! 813:
! 814: static GEN *Relations; /* primes above a, expressed on generators of Cl(K) */
! 815: static GEN *Partial; /* list of vvectors, Partial[i] = Relations[1..i] * u[1..i] */
! 816: static GEN *gen_ord; /* orders of generators of Cl(K) given in bnf */
! 817:
! 818: static long *f; /* f[i] = f(Primes[i]/p), inertial degree */
! 819: static long *n; /* a = prod p^{ n_p }. n[i]=n_p if Primes[i] divides p */
! 820: static long *inext; /* index of first P above next p, 0 if p is last */
! 821: static long *S; /* S[i] = n[i] - sum_{ 1<=k<=i } f[k].u[k] */
! 822: static long *u; /* We want principal ideals I = prod Primes[i]^u[i] */
! 823: static long **normsol; /* lists of copies of the u[] which are solutions */
! 824:
! 825: static long Nprimes; /* length(Relations) = #{max ideal above divisors of a} */
! 826: static long sindex, smax; /* current index in normsol; max. index */
! 827:
! 828: /* u[1..i] has been filled. Norm(u) is correct.
! 829: * Check relations in class group then save it.
! 830: */
! 831: static void
! 832: test_sol(long i)
! 833: {
! 834: long k,*sol;
! 835:
! 836: if (Partial)
! 837: {
! 838: long av=avma;
! 839: for (k=1; k<lg(Partial[1]); k++)
! 840: if ( signe(modii( (GEN)Partial[i][k], gen_ord[k] )) )
! 841: { avma=av; return; }
! 842: avma=av;
! 843: }
! 844: if (sindex == smax)
! 845: {
! 846: long new_smax = smax << 1;
! 847: long **new_normsol = (long **) new_chunk(new_smax+1);
! 848:
! 849: for (k=1; k<=smax; k++) new_normsol[k] = normsol[k];
! 850: normsol = new_normsol; smax = new_smax;
! 851: }
! 852: sol = cgetg(Nprimes+1,t_VECSMALL);
! 853: normsol[++sindex] = sol;
! 854:
! 855: for (k=1; k<=i; k++) sol[k]=u[k];
! 856: for ( ; k<=Nprimes; k++) sol[k]=0;
! 857: if (DEBUGLEVEL > 2)
! 858: {
! 859: fprintferr("sol = %Z\n",sol);
! 860: if (Partial) fprintferr("Partial = %Z\n",Partial);
! 861: flusherr();
! 862: }
! 863: }
! 864: static void
! 865: fix_Partial(long i)
! 866: {
! 867: long k, av = avma;
! 868: for (k=1; k<lg(Partial[1]); k++)
! 869: addiiz(
! 870: (GEN) Partial[i-1][k],
! 871: mulis((GEN) Relations[i][k], u[i]),
! 872: (GEN) Partial[i][k]
! 873: );
! 874: avma=av;
! 875: }
! 876:
! 877: /* Recursive loop. Suppose u[1..i] has been filled
! 878: * Find possible solutions u such that, Norm(prod Prime[i]^u[i]) = a, taking
! 879: * into account:
! 880: * 1) the relations in the class group if need be.
! 881: * 2) the factorization of a.
! 882: */
! 883: static void
! 884: isintnorm_loop(long i)
! 885: {
! 886: if (S[i] == 0) /* sum u[i].f[i] = n[i], do another prime */
! 887: {
! 888: int k;
! 889: if (inext[i] == 0) { test_sol(i); return; }
! 890:
! 891: /* there are some primes left */
! 892: if (Partial) gaffect(Partial[i], Partial[inext[i]-1]);
! 893: for (k=i+1; k < inext[i]; k++) u[k]=0;
! 894: i=inext[i]-1;
! 895: }
! 896: else if (i == inext[i]-2 || i == Nprimes-1)
! 897: {
! 898: /* only one Prime left above prime; change prime, fix u[i+1] */
! 899: if (S[i] % f[i+1]) return;
! 900: i++; u[i] = S[i-1] / f[i];
! 901: if (Partial) fix_Partial(i);
! 902: if (inext[i]==0) { test_sol(i); return; }
! 903: }
! 904:
! 905: i++; u[i]=0;
! 906: if (Partial) gaffect(Partial[i-1], Partial[i]);
! 907: if (i == inext[i-1])
! 908: { /* change prime */
! 909: if (inext[i] == i+1 || i == Nprimes) /* only one Prime above p */
! 910: {
! 911: S[i]=0; u[i] = n[i] / f[i]; /* we already know this is exact */
! 912: if (Partial) fix_Partial(i);
! 913: }
! 914: else S[i] = n[i];
! 915: }
! 916: else S[i] = S[i-1]; /* same prime, different Prime */
! 917: for(;;)
! 918: {
! 919: isintnorm_loop(i); S[i]-=f[i]; if (S[i]<0) break;
! 920: if (Partial)
! 921: gaddz(Partial[i], Relations[i], Partial[i]);
! 922: u[i]++;
! 923: }
! 924: }
! 925:
! 926: static void
! 927: get_sol_abs(GEN bnf, GEN a, GEN **ptPrimes)
! 928: {
! 929: GEN dec, fact, primes, *Primes, *Fact;
! 930: long *gcdlist, gcd,nprimes,Ngen,i,j;
! 931:
! 932: if (gcmp1(a))
! 933: {
! 934: long *sol = new_chunk(Nprimes+1);
! 935: sindex = 1; normsol = (long**) new_chunk(2);
! 936: normsol[1] = sol; for (i=1; i<=Nprimes; i++) sol[i]=0;
! 937: return;
! 938: }
! 939:
! 940: fact=factor(a); primes=(GEN)fact[1];
! 941: nprimes=lg(primes)-1; sindex = 0;
! 942: gen_ord = (GEN *) mael3(bnf,8,1,2); Ngen = lg(gen_ord)-1;
! 943:
! 944: Fact = (GEN*) new_chunk(1+nprimes);
! 945: gcdlist = new_chunk(1+nprimes);
! 946:
! 947: Nprimes=0;
! 948: for (i=1; i<=nprimes; i++)
! 949: {
! 950: long ldec;
! 951:
! 952: dec = primedec(bnf,(GEN)primes[i]); ldec = lg(dec)-1;
! 953: gcd = itos(gmael(dec,1,4));
! 954:
! 955: /* check that gcd_{P|p} f_P | n_p */
! 956: for (j=2; gcd>1 && j<=ldec; j++)
! 957: gcd = cgcd(gcd,itos(gmael(dec,j,4)));
! 958:
! 959: gcdlist[i]=gcd;
! 960:
! 961: if (gcd != 1 && smodis(gmael(fact,2,i),gcd))
! 962: {
! 963: if (DEBUGLEVEL>2)
! 964: { fprintferr("gcd f_P does not divide n_p\n"); flusherr(); }
! 965: return;
! 966: }
! 967: Fact[i] = dec; Nprimes += ldec;
! 968: }
! 969:
! 970: f = new_chunk(1+Nprimes); u = new_chunk(1+Nprimes);
! 971: n = new_chunk(1+Nprimes); S = new_chunk(1+Nprimes);
! 972: inext = new_chunk(1+Nprimes);
! 973: Primes = (GEN*) new_chunk(1+Nprimes);
! 974: *ptPrimes = Primes;
! 975:
! 976: if (Ngen)
! 977: {
! 978: Partial = (GEN*) new_chunk(1+Nprimes);
! 979: Relations = (GEN*) new_chunk(1+Nprimes);
! 980: }
! 981: else /* trivial class group, no relations to check */
! 982: Relations = Partial = NULL;
! 983:
! 984: j=0;
! 985: for (i=1; i<=nprimes; i++)
! 986: {
! 987: long k,lim,v, vn=itos(gmael(fact,2,i));
! 988:
! 989: gcd = gcdlist[i];
! 990: dec = Fact[i]; lim = lg(dec);
! 991: v = (i==nprimes)? 0: j + lim;
! 992: for (k=1; k < lim; k++)
! 993: {
! 994: j++; Primes[j] = (GEN)dec[k];
! 995: f[j] = itos(gmael(dec,k,4)) / gcd;
! 996: n[j] = vn / gcd; inext[j] = v;
! 997: if (Partial)
! 998: Relations[j] = isprincipal(bnf,Primes[j]);
! 999: }
! 1000: }
! 1001: if (Partial)
! 1002: {
! 1003: for (i=1; i <= Nprimes; i++)
! 1004: if (!gcmp0(Relations[i])) break;
! 1005: if (i > Nprimes) Partial = NULL; /* all ideals dividing a are principal */
! 1006: }
! 1007: if (Partial)
! 1008: for (i=0; i<=Nprimes; i++) /* Partial[0] needs to be initialized */
! 1009: {
! 1010: Partial[i]=cgetg(Ngen+1,t_COL);
! 1011: for (j=1; j<=Ngen; j++)
! 1012: {
! 1013: Partial[i][j]=lgeti(4);
! 1014: gaffect(gzero,(GEN) Partial[i][j]);
! 1015: }
! 1016: }
! 1017: smax=511; normsol = (long**) new_chunk(smax+1);
! 1018: S[0]=n[1]; inext[0]=1; isintnorm_loop(0);
! 1019: }
! 1020:
! 1021: static long
! 1022: get_unit_1(GEN bnf, GEN pol, GEN *unit)
! 1023: {
! 1024: GEN fu;
! 1025: long j;
! 1026:
! 1027: if (DEBUGLEVEL > 2)
! 1028: fprintferr("looking for a fundamental unit of norm -1\n");
! 1029:
! 1030: *unit = gmael3(bnf,8,4,2); /* torsion unit */
! 1031: if (signe( gnorm(gmodulcp(*unit,pol)) ) < 0) return 1;
! 1032:
! 1033: fu = gmael(bnf,8,5); /* fundamental units */
! 1034: for (j=1; j<lg(fu); j++)
! 1035: {
! 1036: *unit = (GEN)fu[j];
! 1037: if (signe( gnorm(gmodulcp(*unit,pol)) ) < 0) return 1;
! 1038: }
! 1039: return 0;
! 1040: }
! 1041:
! 1042: GEN
! 1043: bnfisintnorm(GEN bnf, GEN a)
! 1044: {
! 1045: GEN nf,pol,res,unit,x,id, *Primes;
! 1046: long av = avma, tetpil,sa,i,j,norm_1;
! 1047:
! 1048: bnf = checkbnf(bnf); nf = (GEN)bnf[7]; pol = (GEN)nf[1];
! 1049: if (typ(a)!=t_INT)
! 1050: err(talker,"expected an integer in bnfisintnorm");
! 1051: sa = signe(a);
! 1052: if (sa == 0) { res=cgetg(2,t_VEC); res[1]=zero; return res; }
! 1053: if (gcmp1(a)) { res=cgetg(2,t_VEC); res[1]=un; return res; }
! 1054:
! 1055: get_sol_abs(bnf, absi(a), &Primes);
! 1056:
! 1057: res = cgetg(1,t_VEC); unit = NULL;
! 1058: for (i=1; i<=sindex; i++)
! 1059: {
! 1060: id = gun; x = normsol[i];
! 1061: for (j=1; j<=Nprimes; j++) /* compute prod Primes[i]^u[i] */
! 1062: if (x[j])
! 1063: {
! 1064: GEN id2 = Primes[j];
! 1065: if (x[j] != 1) id2 = idealpow(nf,id2, stoi(x[j]));
! 1066: id = idealmul(nf,id,id2);
! 1067: }
! 1068: x = (GEN) isprincipalgen(bnf,id)[2];
! 1069: x = gmul((GEN)nf[7],x); /* x possible solution */
! 1070: if (signe(gnorm(gmodulcp(x,(GEN)nf[1]))) != sa)
! 1071: {
! 1072: if (! unit) norm_1 = get_unit_1(bnf,pol,&unit);
! 1073: if (norm_1) x = gmul(unit,x);
! 1074: else
! 1075: {
! 1076: if (DEBUGLEVEL > 2)
! 1077: fprintferr("%Z eliminated because of sign\n",x);
! 1078: x = NULL;
! 1079: }
! 1080: }
! 1081: if (x) res = concatsp(res, gmod(x,pol));
! 1082: }
! 1083: tetpil=avma; return gerepile(av,tetpil,gcopy(res));
! 1084: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>