[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

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>