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