[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

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>