/* thue.c -- Thue equation solver. In all the forthcoming remarks, "paper" * designs the paper "Thue Equations of High Degree", by Yu. Bilu and * G. Hanrot, J. Number Theory (1996). Note that numbering of the constants * is that of Hanrot's thesis rather than that of the paper. * The last part of the program (bnfisintnorm) was written by K. Belabas. */ /* $Id: thue.c,v 1.1.1.1 1999/09/16 13:48:20 karim Exp $ */ #include "pari.h" static int curne,r,s,t,deg,Prec,ConstPrec,numroot; static GEN c1,c2,c3,c4,c5,c6,c7,c8,c10,c11,c12,c13,c14,c15,B0,x1,x2,x3,x0; static GEN halpha,eps3,gdeg,A,MatNE,roo,MatFU,Delta,Lambda,delta,lambda; static GEN Vect2,SOL,uftot; GEN bnfisintnorm(GEN, GEN); /* Check whether tnf is a valid structure */ static int checktnf(GEN tnf) { if (typ(tnf)!=t_VEC || (lg(tnf)!=8 && lg(tnf)!=3)) return 0; if (typ(tnf[1])!=t_POL) return 0; if (lg(tnf) != 8) return 1; /* s=0 */ deg=lgef(tnf[1])-3; if (deg<=2) err(talker,"invalid polynomial in thue (need deg>2)"); s=sturm((GEN)tnf[1]); t=(deg-s)>>1; r=s+t-1; (void)checkbnf((GEN)tnf[2]); if (typ(tnf[3]) != t_COL || lg(tnf[3]) != deg+1) return 0; if (typ(tnf[4]) != t_COL || lg(tnf[4]) != r+1) return 0; if (typ(tnf[5]) != t_MAT || lg(tnf[5]) != r+1 || lg(gmael(tnf,5,1)) != deg+1) return 0; if (typ(tnf[6]) != t_MAT || lg(tnf[6])!=r+1 || lg(gmael(tnf,6,1)) != r+1) return 0; if (typ(tnf[7]) != t_VEC || lg(tnf[7]) != 7) return 0; return 1; } static GEN distoZ(GEN z) { GEN p1=gfrac(z); return gmin(p1, gsub(gun,p1)); } /* Check whether a solution has already been found */ static int _thue_new(GEN zz) { int i; for (i=1; i=2) fprintferr("c1 = %Z\nc2 = %Z\n", c1, c2); } /* Computation of M, its inverse A and check of the precision (see paper) */ static void T_A_Matrices() { GEN mask, eps1, eps2, nia, m1, IntM; int i,j; m1=glog(gabs(MatFU,Prec),Prec); mask=gsub(gpui(gdeux,stoi(r),Prec),gun); m1=matextract(m1,mask,mask); A=invmat(m1); IntM=gsub(gmul(A,m1),idmat(r)); eps2=gzero; for (i=1; i<=r; i++) for (j=1; j<=r; j++) if (gcmp(eps2,gabs(gcoeff(IntM,i,j),20)) == -1) eps2=gabs(gcoeff(IntM,i,j),20); eps1=gpui(gdeux,stoi((Prec-2)*32),Prec); eps2=gadd(eps2,ginv(eps1)); nia=gzero; for (i=1; i<=r; i++) for (j=1; j<=r; j++) if (gcmp(nia,gabs(gcoeff(A,i,j),20)) == -1) nia = gabs(gcoeff(A,i,j),20); /* Check for the precision in matrix inversion. See paper, Lemma 2.4.2. */ if (gcmp(gmul(gadd(gmul(stoi(r),gmul(nia,eps1)),eps2), gmul(gdeux,stoi(r))),gun) == -1) err(talker,"not enough precision in thue"); eps3=gmul(gdeux,gmul(gmul(gsqr(stoi(r)),nia), gadd(gmul(stoi(r),gdiv(nia,eps1)),eps2))); myround(eps3,gun); if (DEBUGLEVEL>=2) fprintferr("epsilon_3 -> %Z\n",eps3); } /* Computation of the constants c5, c7, c10, c12, c15 */ static void ComputeConstants() { int k; GEN Vect; Vect=cgetg(r+1,t_COL); for (k=1; k<=r; k++) Vect[k]=un; if (numroot <= r) Vect[numroot]=lsub(gun,gdeg); Delta=gmul(A,Vect); c5=(GEN)(gabs(Delta,Prec)[Vecmax(gabs(Delta,Prec),r)]); c5=myround(c5,gun); c7=mulsr(r,c5); c10=divsr(deg,c7); c13=divsr(deg,c5); if (DEBUGLEVEL>=2) { fprintferr("c5 = %Z\n",c5); fprintferr("c7 = %Z\n",c7); fprintferr("c10 = %Z\n",c10); fprintferr("c13 = %Z\n",c13); } } /* Computation of the constants c6, c8, c9 */ static void ComputeConstants2(GEN poly, GEN rhs) { GEN Vect1, tmp; int k; Vect1=cgetg(r+1,t_COL); for (k=1; k<=r; k++) Vect1[k]=un; Vect1=gmul(gabs(A,ConstPrec),Vect1); Vect2=cgetg(r+1,t_COL); for (k=1; k<=r; k++) { if (k!=numroot) { Vect2[k]=llog(gabs(gdiv(gsub((GEN)roo[numroot],(GEN)roo[k]), gcoeff(MatNE,k,curne)),Prec),Prec); } else { Vect2[k]=llog(gabs(gdiv(rhs,gmul(poleval(derivpol(poly) ,(GEN)roo[numroot]), gcoeff(MatNE,k,curne))),Prec),Prec); } } Lambda=gmul(A,Vect2); tmp=(GEN)Vect1[Vecmax(Vect1,r)]; x2=gmax(x1,gpui(mulsr(10,mulrr(c4,tmp)),ginv(gdeg),ConstPrec)); c14=mulrr(c4,tmp); c6=gabs((GEN)Lambda[Vecmax(gabs(Lambda,ConstPrec),r)],ConstPrec); c6=addrr(c6,dbltor(0.1)); c6=myround(c6,gun); c8=addrr(dbltor(1.23),mulsr(r,c6)); c11=mulrr(mulsr(2,c3),gexp(divrr(mulsr(deg,c8),c7),ConstPrec)); tmp=gexp(divrr(mulsr(deg,c6),c5),ConstPrec); c12=mulrr(mulsr(2,c3),tmp); c15=mulsr(2,mulrr(c14,tmp)); if (DEBUGLEVEL>=2) { fprintferr("c6 = %Z\n",c6); fprintferr("c8 = %Z\n",c8); fprintferr("c11 = %Z\n",c11); fprintferr("c12 = %Z\n",c12); fprintferr("c14 = %Z\n",c14); fprintferr("c15 = %Z\n",c15); } } /* Computation of the logarithmic heights of the units */ static GEN Logarithmic_Height(int s) { int i; GEN LH=gun,mat; mat=gabs(MatFU,Prec); for (i=1; i<=deg; i++) LH = gmul(LH,gmax(gun,gabs(gcoeff(mat,i,s),Prec))); return gmul(gdeux,gdiv(glog(LH,Prec),gdeg)); } /* Computation of the matrix ((\sigma_i(\eta_j)) used for M_1 and the computation of logarithmic heights */ static void Compute_Fund_Units(GEN uf) { int i,j; MatFU=cgetg(r+1,t_MAT); for (i=1; i<=r; i++) MatFU[i]=lgetg(deg+1,t_COL); for (i=1; i<=r; i++) { if (typ(uf[i])!=t_POL) err(talker,"incorrect system of units"); for (j=1; j<=deg; j++) coeff(MatFU,j,i)=(long)poleval((GEN)uf[i],(GEN)roo[j]); } } /* Computation of the conjugates of the solutions to the norm equation */ static void Conj_Norm_Eq(GEN ne, GEN *Hmu) { int p,q,nesol,x; nesol=lg(ne); MatNE=(GEN)cgetg(nesol,t_MAT); (*Hmu)=cgetg(nesol,t_COL); for (p=1; p=2) fprintferr("Baker -> %Z\nB0 -> %Z\n",c9,B0); } /* Compute delta and lambda */ static void Create_CF_Values(int i1, int i2, GEN *errdelta) { GEN eps5; if (r>1) { delta=divrr((GEN)Delta[i2],(GEN)Delta[i1]); eps5=mulrs(eps3,r); *errdelta=mulrr(addsr(1,delta), divrr(eps5,subrr(gabs((GEN)Delta[i1],ConstPrec),eps5))); lambda=gdiv(gsub(gmul((GEN)Delta[i2],(GEN)Lambda[i1]), gmul((GEN)Delta[i1],(GEN)Lambda[i2])), (GEN)Delta[i1]); } else { GEN Pi2 = gmul2n(mppi(Prec),1); delta=gdiv(gcoeff(MatFU,2,1),gcoeff(MatFU,3,1)); delta=gdiv(garg(delta,Prec),Pi2); *errdelta=gdiv(gpui(gdeux,stoi(-(Prec-2)*32+1),Prec), gabs(gcoeff(MatFU,2,1),Prec)); lambda=gmul(gdiv(gsub((GEN)roo[numroot],(GEN)roo[2]), gsub((GEN)roo[numroot],(GEN)roo[3])), gdiv(gcoeff(MatNE,3,curne),gcoeff(MatNE,2,curne))); lambda=gdiv(garg(lambda,Prec),Pi2); } if (DEBUGLEVEL>=2) outerr(*errdelta); } /* Try to reduce the bound through continued fractions; see paper. */ static int CF_First_Pass(GEN kappa, GEN errdelta) { GEN q,ql,qd,l0; if (gcmp(gmul(dbltor(0.1),gsqr(mulri(B0,kappa))),ginv(errdelta))==1) { return -1; } q=denom(bestappr(delta, mulir(kappa, B0))); ql=mulir(q,lambda); qd=gmul(q,delta); ql=gabs(subri(ql, ground(ql)),Prec); qd=gabs(mulrr(subri(qd,ground(qd)),B0),Prec); l0=subrr(ql,addrr(qd,divri(dbltor(0.1),kappa))); if (signe(l0) <= 0) { if (DEBUGLEVEL>=2) fprintferr("CF_First_Pass failed. Trying again with larger kappa\n"); return 0; } if (r>1) B0=divrr(glog(divrr(mulir(q,c15),l0),ConstPrec),c13); else B0=divrr(glog(divrr(mulir(q,c11),mulrr(l0,gmul2n(mppi(ConstPrec),1))),ConstPrec),c10); if (DEBUGLEVEL>=2) fprintferr("CF_First_Pass successful !!\nB0 -> %Z\n",B0); return 1; } /* Check whether a "potential" solution is truly a solution. */ static void Check_Solutions(GEN xmay1, GEN xmay2, GEN poly, GEN rhs) { GEN xx1, xx2, yy1, yy2, zz, u; yy1=ground(greal(gdiv(gsub(xmay2,xmay1), gsub((GEN)roo[1],(GEN)roo[2])))); yy2=gneg(yy1); xx1=greal(gadd(xmay1,gmul((GEN)roo[1],yy1))); xx2=gneg(xx1); if (gcmp(distoZ(xx1),dbltor(0.0001))==-1) { xx1=ground(xx1); if (!gcmp0(yy1)) { if (gegal(gmul(poleval(poly,gdiv(xx1,yy1)), gpui(yy1,gdeg,Prec)),(GEN)rhs)) { zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC); u[1]=(long)xx1; u[2]=(long)yy1; zz[1]=(long)u; if (_thue_new(u)) SOL=concatsp(SOL,zz); } } else if (gegal(gpui(xx1,gdeg,Prec),(GEN)rhs)) { zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC); u[1]=(long)xx1; u[2]=(long)gzero; zz[1]=(long)u; if (_thue_new(u)) SOL=concatsp(SOL,zz); } xx2=ground(xx2); if (!gcmp0(yy2)) { if (gegal(gmul(poleval(poly,gdiv(xx2,yy2)), gpui(yy2,gdeg,Prec)),(GEN)rhs)) { zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC); u[1]=(long)xx2; u[2]=(long)yy2; zz[1]=(long)u; if (_thue_new(u)) SOL=concatsp(SOL,zz); } } else if (gegal(gpui(xx2,gdeg,Prec),(GEN)rhs)) { zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC); u[1]=(long)xx2; u[2]=(long)gzero; zz[1]=(long)u; if (_thue_new(u)) SOL=concatsp(SOL,zz); } } } static GEN GuessQi(GEN *q1, GEN *q2, GEN *q3) { GEN C, Lat, eps; C=gpui(stoi(10),stoi(10),Prec); Lat=idmat(3); mael(Lat,1,3)=(long)C; mael(Lat,2,3)=lround(gmul(C,delta)); mael(Lat,3,3)=lround(gmul(C,lambda)); Lat=lllint(Lat); *q1=gmael(Lat,1,1); *q2=gmael(Lat,1,2); *q3=gmael(Lat,1,3); eps=gabs(gadd(gadd(*q1,gmul(*q2,delta)),gmul(*q3,lambda)),Prec); return(eps); } static void TotRat() { err(bugparier,"thue (totally rational case)"); } /* Check for solutions under a small bound (see paper) */ static void Check_Small(int bound, GEN poly, GEN rhs) { GEN interm, xx, zz, u, maxr, tmp, ypot, xxn, xxnm1, yy; long av = avma, lim = stack_lim(av,1); int x, j, bsupy, y; double bndyx; maxr=gabs((GEN)roo[1],Prec); for(j=1; j<=deg; j++) { if(gcmp(tmp=gabs((GEN)roo[j],Prec),maxr)==1) maxr=tmp; } bndyx=gtodouble(gadd(gpui(gabs(rhs,Prec),ginv(gdeg),Prec),maxr)); for (x=-bound; x<=bound; x++) { if (low_stack(lim,stack_lim(av,1))) { if(DEBUGMEM>1) err(warnmem,"Check_small"); SOL = gerepileupto(av, gcopy(SOL)); } if (x==0) { ypot=gmul(stoi(gsigne(rhs)),ground(gpui(gabs(rhs,0),ginv(gdeg),Prec))); if (gegal(gpui(ypot,gdeg,0),rhs)) { zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC); u[1]=(long)ypot; u[2]=(long)gzero; zz[1]=(long)u; if (_thue_new(u)) SOL=concatsp(SOL,zz); } if (gegal(gpui(gneg(ypot),gdeg,0),rhs)) { zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC); u[1]=(long)gneg(ypot); u[2]=(long)gzero; zz[1]=(long)u; if (_thue_new(u)) SOL=concatsp(SOL,zz); } } else { bsupy=(int)(x>0?bndyx*x:-bndyx*x); xx=stoi(x); xxn=gpui(xx,gdeg,Prec); interm=gsub((GEN)rhs,gmul(xxn,(GEN)poly[2])); /* Verifier ... */ xxnm1=xxn; j=2; while(gegal(interm,gzero)) { xxnm1=gdiv(xxnm1,xx); interm=gmul((GEN)poly[++j],xxnm1); } for(y=-bsupy; y<=bsupy; y++) { yy=stoi(y); if(y==0) { if (gegal(gmul((GEN)poly[2],xxn),rhs)) { zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC); u[1]=(long)gzero; u[2]=(long)xx; zz[1]=(long)u; if (_thue_new(u)) SOL=concatsp(SOL,zz); } } else if(gegal(gmod(interm,yy),gzero)) if(gegal(poleval(poly,gdiv(yy,xx)),gdiv(rhs,xxn))) /* Remplacer par un eval *homogene* */ { zz=cgetg(2,t_VEC); u=cgetg(3,t_VEC); u[1]=(long)yy; u[2]=(long)xx; zz[1]=(long)u; if (_thue_new(u)) SOL=concatsp(SOL,zz); } } } } } /* Computes [x]! */ static double fact(double x) { double ft=1.0; x=(int)x; while (x>1) { ft*=x; x--; } return ft ; } /* From a polynomial and optionally a system of fundamental units for the * field defined by poly, computes all the relevant constants needed to solve * the equation P(x,y)=a whenever the solutions of N_{ K/Q }(x)=a. Returns a * "tnf" structure containing * 1) the polynomial * 2) the bnf (used to solve the norm equation) * 3) roots, with presumably enough precision * 4) The logarithmic heights of units * 5) The matrix of conjugates of units * 6) its inverse * 7) a few technical constants */ GEN thueinit(GEN poly, long flag, long prec) { GEN thueres,ALH,csts,c0; long av,tetpil,k,st; double d,dr; av=avma; uftot=0; if (checktnf(poly)) { uftot=(GEN)poly[2]; poly=(GEN)poly[1]; } else if (typ(poly)!=t_POL) err(notpoler,"thueinit"); if (!gisirreducible(poly)) err(redpoler,"thueinit"); st=sturm(poly); if (st) { dr=(double)((st+lgef(poly)-5)>>1); d=(double)lgef(poly)-3; d=d*(d-1)*(d-2); /* Try to guess the precision by approximating Baker's bound. * Note that the guess is most of the time pretty generous, * ie 10 to 30 decimal digits above what is *really* necessary. * Note that the limiting step is the reduction. See paper. */ Prec=3 + (long)((5.83 + (dr+4)*5 + log(fact(dr+3)) + (dr+3)*log(dr+2) + (dr+3)*log(d) + log(log(2*d*(dr+2))) + (dr+1)) / 10.); ConstPrec=4; if (Prec=2) fprintferr("x1 -> %Z\n",x1); c3=mulrr(dbltor(1.39),tmp); c4=mulsr(deg-1,c3); for (numroot=1; numroot<=s; numroot++) { ComputeConstants(); Conj_Norm_Eq(ne,&Hmu); for (curne=1; curne=2) fprintferr("Entering CF\n"); Old_B0=gmul(B0,gdeux); /* Try to reduce B0 while * 1) there was less than 10 reductions * 2) the previous reduction improved the bound of more than 0.1. */ while (Nb_It<10 && gcmp(Old_B0,gadd(B0,dbltor(0.1))) == 1 && fs<2) { cf=0; Old_B0=B0; Nb_It++; Kstart=stoi(10); while (!fs && CF_First_Pass(Kstart,errdelta) == 0 && cf < 8 ) { cf++; Kstart=mulis(Kstart,10); } if ( CF_First_Pass(Kstart,errdelta) == -1 ) { ne = gerepileupto(av, gcopy(ne)); Prec+=10; if(DEBUGLEVEL>=2) fprintferr("Increasing precision\n"); thueres=thueinit(thueres,0,Prec); return(thue(thueres,rhs,ne)); } if (cf==8 || fs) /* Semirational or totally rational case */ { if (!fs) { ep=GuessQi(&q1,&q2,&q3); } bd=gmul(denom(bestappr(delta,gadd(B0,gabs(q2,Prec)))) ,delta); bd=gabs(gsub(bd,ground(bd)),Prec); if(gcmp(bd,ep)==1 && !gegal(q3, gzero)) { fs=1; B0=gdiv(glog(gdiv(gmul(q3,c15),gsub(bd,ep)), Prec),c13); if (DEBUGLEVEL>=2) fprintferr("Semirat. reduction ok. B0 -> %Z\n",B0); } else fs=2; } else fs=0; Nb_It=0; B0=gmin(Old_B0,B0); upb=gtolong(gceil(B0)); } i2++; if (i2==i1) i2++; } while (fs == 2 && i2 <= r); if (fs == 2) TotRat(); if (DEBUGLEVEL >=2) fprintferr("x2 -> %Z\n",x2); /* For each possible value of b_i1, compute the b_i's * and 2 conjugates of x-\alpha y. Then check. */ zp1=dbltor(0.01); x3=gmax(x2,gpui(mulsr(2,divrr(c14,zp1)),ginv(gdeg),ConstPrec)); for (bi1=-upb; bi1<=upb; bi1++) { flag=1; xmay1=gun; xmay2=gun; for (i=1; i<=r; i++) { b[i]=(long)gdiv(gsub(gmul((GEN)Delta[i],stoi(bi1)), gsub(gmul((GEN)Delta[i],(GEN)Lambda[i1]), gmul((GEN)Delta[i1],(GEN)Lambda[i]))), (GEN)Delta[i1]); if (gcmp(distoZ((GEN)b[i]),zp1)==1) { flag=0; break; } } if(flag) { for(i=1; i<=r; i++) { b[i]=lround((GEN)b[i]); xmay1=gmul(xmay1,gpui(gcoeff(MatFU,1,i),(GEN)b[i],Prec)); xmay2=gmul(xmay2,gpui(gcoeff(MatFU,2,i),(GEN)b[i],Prec)); } xmay1=gmul(xmay1,gcoeff(MatNE,1,curne)); xmay2=gmul(xmay2,gcoeff(MatNE,2,curne)); Check_Solutions(xmay1,xmay2,poly,rhs); } } } } if (DEBUGLEVEL>=2) fprintferr("Checking for small solutions\n"); Check_Small((int)(gtodouble(x3)),poly,rhs); tetpil=avma; return gerepile(av,tetpil,gcopy(SOL)); } /* Case s=0. All the solutions are "small". */ Prec=DEFAULTPREC; poly=(GEN)thueres[1]; deg=lgef(poly)-3; gdeg=stoi(deg); c0=(GEN)thueres[2]; roo=roots(poly,Prec); Check_Small(gtolong(ground(gpui(gmul((GEN)poly[2],gdiv(gabs(rhs,Prec),c0)), ginv(gdeg),Prec) )), poly, rhs); tetpil=avma; return gerepile(av,tetpil,gcopy(SOL)); } static GEN *Relations; /* primes above a, expressed on generators of Cl(K) */ static GEN *Partial; /* list of vvectors, Partial[i] = Relations[1..i] * u[1..i] */ static GEN *gen_ord; /* orders of generators of Cl(K) given in bnf */ static long *f; /* f[i] = f(Primes[i]/p), inertial degree */ static long *n; /* a = prod p^{ n_p }. n[i]=n_p if Primes[i] divides p */ static long *inext; /* index of first P above next p, 0 if p is last */ static long *S; /* S[i] = n[i] - sum_{ 1<=k<=i } f[k].u[k] */ static long *u; /* We want principal ideals I = prod Primes[i]^u[i] */ static long **normsol; /* lists of copies of the u[] which are solutions */ static long Nprimes; /* length(Relations) = #{max ideal above divisors of a} */ static long sindex, smax; /* current index in normsol; max. index */ /* u[1..i] has been filled. Norm(u) is correct. * Check relations in class group then save it. */ static void test_sol(long i) { long k,*sol; if (Partial) { long av=avma; for (k=1; k 2) { fprintferr("sol = %Z\n",sol); if (Partial) fprintferr("Partial = %Z\n",Partial); flusherr(); } } static void fix_Partial(long i) { long k, av = avma; for (k=1; k1 && j<=ldec; j++) gcd = cgcd(gcd,itos(gmael(dec,j,4))); gcdlist[i]=gcd; if (gcd != 1 && smodis(gmael(fact,2,i),gcd)) { if (DEBUGLEVEL>2) { fprintferr("gcd f_P does not divide n_p\n"); flusherr(); } return; } Fact[i] = dec; Nprimes += ldec; } f = new_chunk(1+Nprimes); u = new_chunk(1+Nprimes); n = new_chunk(1+Nprimes); S = new_chunk(1+Nprimes); inext = new_chunk(1+Nprimes); Primes = (GEN*) new_chunk(1+Nprimes); *ptPrimes = Primes; if (Ngen) { Partial = (GEN*) new_chunk(1+Nprimes); Relations = (GEN*) new_chunk(1+Nprimes); } else /* trivial class group, no relations to check */ Relations = Partial = NULL; j=0; for (i=1; i<=nprimes; i++) { long k,lim,v, vn=itos(gmael(fact,2,i)); gcd = gcdlist[i]; dec = Fact[i]; lim = lg(dec); v = (i==nprimes)? 0: j + lim; for (k=1; k < lim; k++) { j++; Primes[j] = (GEN)dec[k]; f[j] = itos(gmael(dec,k,4)) / gcd; n[j] = vn / gcd; inext[j] = v; if (Partial) Relations[j] = isprincipal(bnf,Primes[j]); } } if (Partial) { for (i=1; i <= Nprimes; i++) if (!gcmp0(Relations[i])) break; if (i > Nprimes) Partial = NULL; /* all ideals dividing a are principal */ } if (Partial) for (i=0; i<=Nprimes; i++) /* Partial[0] needs to be initialized */ { Partial[i]=cgetg(Ngen+1,t_COL); for (j=1; j<=Ngen; j++) { Partial[i][j]=lgeti(4); gaffect(gzero,(GEN) Partial[i][j]); } } smax=511; normsol = (long**) new_chunk(smax+1); S[0]=n[1]; inext[0]=1; isintnorm_loop(0); } static long get_unit_1(GEN bnf, GEN pol, GEN *unit) { GEN fu; long j; if (DEBUGLEVEL > 2) fprintferr("looking for a fundamental unit of norm -1\n"); *unit = gmael3(bnf,8,4,2); /* torsion unit */ if (signe( gnorm(gmodulcp(*unit,pol)) ) < 0) return 1; fu = gmael(bnf,8,5); /* fundamental units */ for (j=1; j 2) fprintferr("%Z eliminated because of sign\n",x); x = NULL; } } if (x) res = concatsp(res, gmod(x,pol)); } tetpil=avma; return gerepile(av,tetpil,gcopy(res)); }