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

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>