[BACK]Return to thue.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari / src / modules

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>