[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.2

1.2     ! noro        1: /* $Id: thue.c,v 1.19 2002/07/17 20:23:16 karim Exp $
1.1       noro        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:
1.2     ! noro       16: #include "pari.h"
        !            17:
1.1       noro       18: /* Thue equation solver. In all the forthcoming remarks, "paper"
                     19:  * designs the paper "Thue Equations of High Degree", by Yu. Bilu and
                     20:  * G. Hanrot, J. Number Theory (1996). Note that numbering of the constants
                     21:  * is that of Hanrot's thesis rather than that of the paper.
1.2     ! noro       22:  * The last part of the program (bnfisintnorm) was written by K. Belabas. */
1.1       noro       23:
                     24: /* Check whether tnf is a valid structure */
                     25: static int
                     26: checktnf(GEN tnf)
                     27: {
1.2     ! noro       28:   int n, R, S, T;
1.1       noro       29:   if (typ(tnf)!=t_VEC || (lg(tnf)!=8 && lg(tnf)!=3)) return 0;
1.2     ! noro       30:   if (typ(tnf[1]) != t_POL) return 0;
        !            31:   if (lg(tnf) != 8) return 1; /* S=0 */
1.1       noro       32:
1.2     ! noro       33:   n = degpol(tnf[1]);
        !            34:   if (n <= 2) err(talker,"invalid polynomial in thue (need n>2)");
        !            35:   S = sturm((GEN)tnf[1]); T = (n-S)>>1; R = S+T-1;
1.1       noro       36:   (void)checkbnf((GEN)tnf[2]);
1.2     ! noro       37:   if (typ(tnf[3]) != t_COL || lg(tnf[3]) != n+1) return 0;
        !            38:   if (typ(tnf[4]) != t_COL || lg(tnf[4]) != R+1) return 0;
        !            39:   if (typ(tnf[5]) != t_MAT || lg(tnf[5])!=R+1 || lg(gmael(tnf,5,1)) != n+1) return 0;
        !            40:   if (typ(tnf[6]) != t_MAT || lg(tnf[6])!=R+1 || lg(gmael(tnf,6,1)) != R+1) return 0;
1.1       noro       41:   if (typ(tnf[7]) != t_VEC || lg(tnf[7]) != 7) return 0;
                     42:   return 1;
                     43: }
                     44:
1.2     ! noro       45: static GEN
        !            46: distoZ(GEN z)
1.1       noro       47: {
1.2     ! noro       48:   GEN p1 = gfrac(z);
1.1       noro       49:   return gmin(p1, gsub(gun,p1));
                     50: }
                     51:
1.2     ! noro       52: /* Compensates rounding errors for computation/display of the constants.
        !            53:  * Round up if dir > 0, down otherwise */
1.1       noro       54: static GEN
1.2     ! noro       55: myround(GEN x, long dir)
1.1       noro       56: {
1.2     ! noro       57:   GEN eps = gpowgs(stoi(dir > 0? 10: -10), -10);
        !            58:   return gmul(x, gadd(gun, eps));
1.1       noro       59: }
                     60:
                     61: /* Returns the index of the largest element in a vector */
1.2     ! noro       62: static GEN
        !            63: _Vecmax(GEN Vec, int *ind)
1.1       noro       64: {
1.2     ! noro       65:   int k, tno = 1, l = lg(Vec);
1.1       noro       66:   GEN tmax = (GEN)Vec[1];
1.2     ! noro       67:   for (k = 2; k < l; k++)
        !            68:     if (gcmp((GEN)Vec[k],tmax) > 0) { tmax = (GEN)Vec[k]; tno = k; }
        !            69:   if (ind) *ind = tno;
        !            70:   return tmax;
1.1       noro       71: }
                     72:
1.2     ! noro       73: static GEN
        !            74: Vecmax(GEN v) { return _Vecmax(v, NULL); }
1.1       noro       75:
1.2     ! noro       76: static int
        !            77: Vecmaxind(GEN v) { int i; (void)_Vecmax(v, &i); return i; }
1.1       noro       78:
1.2     ! noro       79: static GEN
        !            80: tnf_get_roots(GEN poly, long prec, int S, int T)
        !            81: {
        !            82:   GEN R0 = roots(poly, prec), R = cgetg(lg(R0), t_COL);
        !            83:   int k;
1.1       noro       84:
1.2     ! noro       85:   for (k=1; k<=S; k++) R[k] = lreal((GEN)R0[k]);
        !            86:   /* swap roots to get the usual order */
        !            87:   for (k=1; k<=T; k++)
1.1       noro       88:   {
1.2     ! noro       89:     R[k+S]  = R0[2*k+S-1];
        !            90:     R[k+S+T]= R0[2*k+S];
1.1       noro       91:   }
1.2     ! noro       92:   return R;
        !            93: }
1.1       noro       94:
1.2     ! noro       95: /* Computation of the logarithmic height of x (given by embeddings) */
        !            96: static GEN
        !            97: LogHeight(GEN x, long prec)
        !            98: {
        !            99:   int i, n = lg(x)-1;
        !           100:   GEN LH = gun;
        !           101:   for (i=1; i<=n; i++) LH = gmul(LH, gmax(gun, gabs((GEN)x[i], prec)));
        !           102:   return gdivgs(glog(LH,prec), n);
        !           103: }
1.1       noro      104:
1.2     ! noro      105: /* x^(1/n) */
        !           106: static GEN
        !           107: mpsqrtn(GEN x, long n)
        !           108: {
        !           109:   if (typ(x) != t_REAL) err(typeer,"mpsqrtn");
        !           110:   return mpexp(divrs(mplog(x), n));
        !           111: }
1.1       noro      112:
1.2     ! noro      113: /* |x|^(1/n), x t_INT */
        !           114: static GEN
        !           115: absisqrtn(GEN x, long n, long prec) {
        !           116:   GEN r = itor(x,prec);
        !           117:   if (signe(r) < 0) r = negr(r);
        !           118:   return mpsqrtn(r, n);
1.1       noro      119: }
                    120:
1.2     ! noro      121: static GEN
        !           122: get_emb(GEN x, GEN r)
1.1       noro      123: {
1.2     ! noro      124:   int l = lg(r), i, tx;
        !           125:   GEN e, y = cgetg(l, t_COL);
1.1       noro      126:
1.2     ! noro      127:   tx = typ(x);
        !           128:   if (tx != t_INT && tx != t_POL) err(typeer,"get_emb");
        !           129:   for (i=1; i<l; i++)
        !           130:   {
        !           131:     e = poleval(x, (GEN)r[i]);
        !           132:     if (gcmp0(e)) return NULL;
        !           133:     y[i] = (long)e;
        !           134:   }
        !           135:   return y;
1.1       noro      136: }
                    137:
1.2     ! noro      138: /* Computation of the conjugates (sigma_i(v_j)), and log. heights, of elts of v */
        !           139: static GEN
        !           140: Conj_LH(GEN v, GEN *H, GEN r, long prec)
1.1       noro      141: {
1.2     ! noro      142:   int j, l = lg(v);
        !           143:   GEN e, M = (GEN)cgetg(l,t_MAT);
1.1       noro      144:
1.2     ! noro      145:   (*H) = cgetg(l,t_COL);
        !           146:   for (j = 1; j < l; j++)
1.1       noro      147:   {
1.2     ! noro      148:     if (! (e = get_emb((GEN)v[j], r)) ) return NULL; /* FAIL */
        !           149:     M[j] = (long)e;
        !           150:     (*H)[j]= (long)LogHeight(e, prec);
1.1       noro      151:   }
1.2     ! noro      152:   return M;
1.1       noro      153: }
                    154:
1.2     ! noro      155: static GEN abslog(GEN x, long prec) { return gabs(glog(x,prec), prec); }
        !           156: static GEN logabs(GEN x, long prec) { return glog(gabs(x,prec), prec); }
        !           157:
        !           158: /* Computation of M, its inverse A and precision check (see paper) */
        !           159: static GEN
        !           160: T_A_Matrices(GEN MatFU, int r, GEN *eps5, long prec)
1.1       noro      161: {
1.2     ! noro      162:   GEN A, p1, m1, IntM, nia, eps3, eps2, eps1 = shifti(gun, bit_accuracy(prec));
1.1       noro      163:
1.2     ! noro      164:   m1 = rowextract_i(vecextract_i(MatFU, 1,r), 1,r); /* minor order r */
        !           165:   m1 = logabs(m1,prec);
1.1       noro      166:
1.2     ! noro      167:   A = invmat(m1);
        !           168:   IntM = gsub(gmul(A,m1), idmat(r));
1.1       noro      169:
1.2     ! noro      170:   eps2 = gadd(vecmax(gabs(IntM,prec)), ginv(eps1));
        !           171:   nia = vecmax(gabs(A,prec));
1.1       noro      172:
1.2     ! noro      173:   /* Check for the precision in matrix inversion. See paper, Lemma 2.4.2. */
        !           174:   p1 = gadd(gmulsg(r, gmul(nia,eps1)), eps2);
        !           175:   if (gcmp(gmulgs(p1, 2*r), gun) < 0) err(precer,"thue");
1.1       noro      176:
1.2     ! noro      177:   p1 = gadd(gmulsg(r, gdiv(nia,eps1)), eps2);
        !           178:   eps3 = gmul(gmulsg(2*r*r,nia), p1);
        !           179:   eps3 = myround(eps3, 1);
1.1       noro      180:
1.2     ! noro      181:   if (DEBUGLEVEL>1) fprintferr("epsilon_3 -> %Z\n",eps3);
        !           182:   *eps5 = mulsr(r, eps3); return A;
1.1       noro      183: }
                    184:
1.2     ! noro      185: /* Performs basic computations concerning the equation.
        !           186:  * Returns a "tnf" structure containing
        !           187:  *  1) the polynomial
        !           188:  *  2) the bnf (used to solve the norm equation)
        !           189:  *  3) roots, with presumably enough precision
        !           190:  *  4) The logarithmic heights of units
        !           191:  *  5) The matrix of conjugates of units
        !           192:  *  6) its inverse
        !           193:  *  7) a few technical constants */
1.1       noro      194: static GEN
1.2     ! noro      195: inithue(GEN P, GEN bnf, long flag, long prec)
1.1       noro      196: {
1.2     ! noro      197:   GEN MatFU, x0, tnf, tmp, gpmin, dP, csts, ALH, eps5, ro, c1, c2;
        !           198:   int k,j, s,t, n = degpol(P);
1.1       noro      199:
1.2     ! noro      200:   if (!bnf)
        !           201:   {
        !           202:     bnf = bnfinit0(P,1,NULL,prec);
        !           203:     if (bnf != checkbnf_discard(bnf)) err(talker,"non-monic polynomial in thue");
        !           204:     if (flag) (void)certifybuchall(bnf);
        !           205:   }
        !           206:   nf_get_sign(checknf(bnf), (long*)&s, (long*)&t);
        !           207:   ro = tnf_get_roots(P, prec, s, t);
        !           208:   MatFU = Conj_LH(gmael(bnf,8,5), &ALH, ro, prec);
        !           209:   if (!MatFU) return NULL; /* FAIL */
1.1       noro      210:
1.2     ! noro      211:   dP = derivpol(P);
        !           212:   c1 = NULL; /* min |P'(r_i)|, i <= s */
        !           213:   for (k=1; k<=s; k++)
1.1       noro      214:   {
1.2     ! noro      215:     tmp = gabs(poleval(dP,(GEN)ro[k]),prec);
        !           216:     if (!c1 || gcmp(tmp,c1) < 0) c1 = tmp;
1.1       noro      217:   }
1.2     ! noro      218:   c1 = gdiv(shifti(gun,n-1), c1);
        !           219:   c1 = gprec_w(myround(c1, 1), DEFAULTPREC);
1.1       noro      220:
1.2     ! noro      221:   c2 = NULL; /* max |r_i - r_j|, i!=j */
        !           222:   for (k=1; k<=n; k++)
        !           223:     for (j=k+1; j<=n; j++)
        !           224:     {
        !           225:       tmp = gabs(gsub((GEN)ro[j],(GEN)ro[k]), prec);
        !           226:       if (!c2 || gcmp(c2,tmp) > 0) c2 = tmp;
        !           227:     }
        !           228:   c2 = gprec_w(myround(c2, -1), DEFAULTPREC);
1.1       noro      229:
1.2     ! noro      230:   if (t==0) x0 = gun;
        !           231:   else
1.1       noro      232:   {
1.2     ! noro      233:     gpmin = NULL; /* min |P'(r_i)|, i > s */
        !           234:     for (k=1; k<=t; k++)
1.1       noro      235:     {
1.2     ! noro      236:       tmp = gabs(poleval(dP,(GEN)ro[s+k]), prec);
        !           237:       if (!gpmin || gcmp(tmp,gpmin) < 0) gpmin = tmp;
1.1       noro      238:     }
1.2     ! noro      239:     gpmin = gprec_w(gpmin, DEFAULTPREC);
        !           240:
        !           241:     /* Compute x0. See paper, Prop. 2.2.1 */
        !           242:     x0 = gmul(gpmin, Vecmax(gabs(gimag(ro), prec)));
        !           243:     x0 = mpsqrtn(gdiv(shifti(gun,n-1), x0), n);
1.1       noro      244:   }
1.2     ! noro      245:   if (DEBUGLEVEL>1) fprintferr("c1 = %Z\nc2 = %Z\n", c1, c2);
        !           246:
        !           247:   ALH = gmul2n(ALH, 1);
        !           248:   tnf = cgetg(8,t_VEC); csts = cgetg(7,t_VEC);
        !           249:   tnf[1] = (long)P;
        !           250:   tnf[2] = (long)bnf;
        !           251:   tnf[3] = (long)ro;
        !           252:   tnf[4] = (long)ALH;
        !           253:   tnf[5] = (long)MatFU;
        !           254:   tnf[6] = (long)T_A_Matrices(MatFU, s+t-1, &eps5, prec);
        !           255:   tnf[7] = (long)csts;
        !           256:   csts[1] = (long)c1; csts[2] = (long)c2;   csts[3] = (long)LogHeight(ro, prec);
        !           257:   csts[4] = (long)x0; csts[5] = (long)eps5; csts[6] = (long)stoi(prec);
        !           258:   return tnf;
        !           259: }
        !           260:
        !           261: typedef struct {
        !           262:   GEN c10, c11, c13, c15, bak, NE, ALH, hal, MatFU, ro, Hmu;
        !           263:   GEN delta, lambda, errdelta;
        !           264:   int r, iroot;
        !           265: } baker_s;
1.1       noro      266:
1.2     ! noro      267: /* Compute Baker's bound c9 and B_0, the bound for the b_i's. See Thm 2.3.1 */
        !           268: static GEN
        !           269: Baker(baker_s *BS)
1.1       noro      270: {
1.2     ! noro      271:   const long prec = DEFAULTPREC;
        !           272:   GEN tmp, B0, hb0, c9 = gun, ro = BS->ro, ro0 = (GEN)ro[BS->iroot];
        !           273:   int k, i1, i2, r = BS->r;
        !           274:
        !           275:   switch (BS->iroot) {
        !           276:     case 1: i1=2; i2=3; break;
        !           277:     case 2: i1=1; i2=3; break;
        !           278:    default: i1=1; i2=2; break;
1.1       noro      279:   }
                    280:
                    281:   /* Compute h_1....h_r */
                    282:   for (k=1; k<=r; k++)
                    283:   {
1.2     ! noro      284:     tmp = gdiv(gcoeff(BS->MatFU,i1,k), gcoeff(BS->MatFU,i2,k));
        !           285:     tmp = gmax(gun, abslog(tmp,prec));
        !           286:     c9 = gmul(c9, gmax((GEN)BS->ALH[k], gdiv(tmp, BS->bak)));
1.1       noro      287:   }
                    288:
                    289:   /* Compute a bound for the h_0 */
1.2     ! noro      290:   hb0 = gadd(gmul2n(BS->hal,2), gmul(gdeux, gadd(BS->Hmu,mplog2(prec))));
        !           291:   tmp = gdiv(gmul(gsub(ro0, (GEN)ro[i2]), (GEN)BS->NE[i1]),
        !           292:              gmul(gsub(ro0, (GEN)ro[i1]), (GEN)BS->NE[i2]));
        !           293:   tmp = gmax(gun, abslog(tmp, prec));
        !           294:   hb0 = gmax(hb0, gdiv(tmp, BS->bak));
        !           295:   c9 = gmul(c9,hb0);
1.1       noro      296:   /* Multiply c9 by the "constant" factor */
1.2     ! noro      297:   c9 = gmul(c9, gmul(mulri(mulsr(18,mppi(prec)), gpowgs(stoi(32),4+r)),
        !           298:                      gmul(gmul(mpfact(r+3), gpowgs(mulis(BS->bak,r+2), r+3)),
        !           299:                           glog(mulis(BS->bak,2*(r+2)),prec))));
        !           300:   c9 = gprec_w(myround(c9, 1), DEFAULTPREC);
1.1       noro      301:   /* Compute B0 according to Lemma 2.3.3 */
1.2     ! noro      302:   B0 = mulsr(2, divrr(addrr(mulrr(c9,mplog(divrr(c9,BS->c10))), mplog(BS->c11)),
        !           303:                       BS->c10));
        !           304:   B0 = gmax(B0, dbltor(2.71828183));
1.1       noro      305:
1.2     ! noro      306:   if (DEBUGLEVEL>1) {
        !           307:     fprintferr("  B0  = %Z\n",B0);
        !           308:     fprintferr("  Baker = %Z\n",c9);
        !           309:   }
        !           310:   return B0;
1.1       noro      311: }
                    312:
1.2     ! noro      313: /* || x d ||, x t_REAL, d t_INT */
        !           314: static GEN
        !           315: errnum(GEN x, GEN d)
1.1       noro      316: {
1.2     ! noro      317:   GEN dx = mulir(d, x);
        !           318:   return mpabs(subri(dx, ground(dx)));
1.1       noro      319: }
                    320:
                    321: /* Try to reduce the bound through continued fractions; see paper. */
                    322: static int
1.2     ! noro      323: CF_1stPass(GEN *B0, GEN kappa, baker_s *BS)
1.1       noro      324: {
1.2     ! noro      325:   GEN q, ql, qd, l0, denbound = mulri(*B0, kappa);
        !           326:
        !           327:   if (gcmp(gmul(dbltor(0.1),gsqr(denbound)), ginv(BS->errdelta)) > 0) return -1;
1.1       noro      328:
1.2     ! noro      329:   q = denom( bestappr(BS->delta, denbound) );
        !           330:   qd = errnum(BS->delta, q);
        !           331:   ql = errnum(BS->lambda,q);
        !           332:
        !           333:   l0 = subrr(ql, addrr(mulrr(qd, *B0), divri(dbltor(0.1),kappa)));
        !           334:   if (signe(l0) <= 0) return 0;
1.1       noro      335:
1.2     ! noro      336:   if (BS->r > 1)
        !           337:     *B0 = divrr(mplog(divrr(mulir(q,BS->c15), l0)), BS->c13);
        !           338:   else
1.1       noro      339:   {
1.2     ! noro      340:     l0 = mulrr(l0,Pi2n(1, DEFAULTPREC));
        !           341:     *B0 = divrr(mplog(divrr(mulir(q,BS->c11), l0)), BS->c10);
1.1       noro      342:   }
1.2     ! noro      343:   if (DEBUGLEVEL>1) fprintferr("    B0 -> %Z\n",*B0);
        !           344:   return 1;
        !           345: }
1.1       noro      346:
1.2     ! noro      347: /* Check whether a solution has already been found */
        !           348: static int
        !           349: new_sol(GEN z, GEN S)
        !           350: {
        !           351:   int i, l = lg(S);
        !           352:   for (i=1; i<l; i++)
        !           353:     if (gegal(z,(GEN)S[i])) return 0;
        !           354:   return 1;
        !           355: }
1.1       noro      356:
1.2     ! noro      357: static void
        !           358: add_sol(GEN *pS, GEN x, GEN y)
        !           359: {
        !           360:   GEN u = cgetg(3,t_VEC); u[1] = (long)x; u[2] = (long)y;
        !           361:   if (new_sol(u, *pS)) *pS = concatsp(*pS, _vec(u));
        !           362: }
1.1       noro      363:
                    364: static void
1.2     ! noro      365: check_sol(GEN x, GEN y, GEN P, GEN rhs, GEN *pS)
1.1       noro      366: {
1.2     ! noro      367:   if (gcmp0(y))
        !           368:   { if (gegal(gpowgs(x,degpol(P)), rhs)) add_sol(pS, x, gzero); }
        !           369:   else
        !           370:   { if (gegal(poleval(rescale_pol(P,y),x), rhs)) add_sol(pS, x, y); }
        !           371: }
1.1       noro      372:
1.2     ! noro      373: /* Check whether a potential solution is a true solution. Return 0 if
        !           374:  * truncation error (increase precision) */
        !           375: static int
        !           376: CheckSol(GEN *pS, GEN z1, GEN z2, GEN P, GEN rhs, GEN ro)
        !           377: {
        !           378:   GEN x, y, ro1 = (GEN)ro[1], ro2 = (GEN)ro[2];
        !           379:   long e;
1.1       noro      380:
1.2     ! noro      381:   y = grndtoi(greal(gdiv(gsub(z2,z1), gsub(ro1,ro2))), &e);
        !           382:   if (e > 0) return 0;
        !           383:   x = gadd(z1, gmul(ro1, y));
        !           384:   x = grndtoi(greal(x), &e);
        !           385:   if (e > 0) return 0;
        !           386:   if (e <= -13)
1.1       noro      387:   {
1.2     ! noro      388:     check_sol(     x ,      y,  P,rhs,pS);
        !           389:     check_sol(gneg(x), gneg(y), P,rhs,pS);
1.1       noro      390:   }
1.2     ! noro      391:   return 1;
1.1       noro      392: }
                    393:
1.2     ! noro      394: /* find q1,q2,q3 st q1 + b q2 + c q3 ~ 0 */
1.1       noro      395: static GEN
1.2     ! noro      396: GuessQi(GEN b, GEN c, GEN *eps)
1.1       noro      397: {
1.2     ! noro      398:   GEN Q, Lat, C = gpowgs(stoi(10), 10);
1.1       noro      399:
1.2     ! noro      400:   Lat = idmat(3);
        !           401:   mael(Lat,1,3) = (long)C;
        !           402:   mael(Lat,2,3) = lround(gmul(C,b));
        !           403:   mael(Lat,3,3) = lround(gmul(C,c));
1.1       noro      404:
1.2     ! noro      405:   Q = (GEN)lllint(Lat)[1];
        !           406:   if (gcmp0((GEN)Q[3])) return NULL; /* FAIL */
1.1       noro      407:
1.2     ! noro      408:   *eps = gadd(gadd((GEN)Q[1], gmul((GEN)Q[2],b)), gmul((GEN)Q[3],c));
        !           409:   *eps = mpabs(*eps); return Q;
1.1       noro      410: }
                    411:
                    412: /* Check for solutions under a small bound (see paper) */
1.2     ! noro      413: static GEN
        !           414: SmallSols(GEN S, int Bx, GEN poly, GEN rhs, GEN ro)
1.1       noro      415: {
1.2     ! noro      416:   gpmem_t av = avma, lim = stack_lim(av, 1);
        !           417:   const long prec = DEFAULTPREC;
        !           418:   GEN Hpoly, interm, X, Xn, Xnm1, Y, sqrtnRHS;
        !           419:   int x, y, j, By, n = degpol(poly);
1.1       noro      420:   double bndyx;
                    421:
1.2     ! noro      422:   if (DEBUGLEVEL>1) fprintferr("* Checking for small solutions\n");
        !           423:
        !           424:   sqrtnRHS = absisqrtn(rhs, n, prec);
        !           425:   bndyx = gtodouble(gadd(sqrtnRHS, Vecmax(gabs(ro,prec))));
        !           426:
        !           427:   /* x = 0 first */
        !           428:   Y = ground(sqrtnRHS);
        !           429:   if (gegal(gpowgs(Y,n), rhs)) add_sol(&S, Y, gzero);
        !           430:   Y = negi(Y);
        !           431:   if (gegal(gpowgs(Y,n), rhs)) add_sol(&S, Y, gzero);
        !           432:   /* x != 0 */
        !           433:   for (x = -Bx; x <= Bx; x++)
        !           434:   {
        !           435:     if (!x) continue;
        !           436:
        !           437:     X = stoi(x); Xn = gpowgs(X,n);
        !           438:     interm = subii(rhs, mulii(Xn, (GEN)poly[2]));
        !           439:     Xnm1 = Xn; j = 2;
        !           440:     while (gcmp0(interm))
        !           441:     {
        !           442:       Xnm1 = divis(Xnm1, x);
        !           443:       interm = mulii((GEN)poly[++j], Xnm1);
        !           444:     }
        !           445:     /* y | interm */
1.1       noro      446:
1.2     ! noro      447:     Hpoly = rescale_pol(poly,X); /* homogenize */
        !           448:     By = (int)(x>0? bndyx*x: -bndyx*x);
        !           449:     if (gegal(gmul((GEN)poly[2],Xn),rhs)) add_sol(&S, gzero, X); /* y = 0 */
        !           450:     for(y = -By; y <= By; y++)
        !           451:     {
        !           452:       if (!y || smodis(interm, y)) continue;
        !           453:       Y = stoi(y);
        !           454:       if (gegal(poleval(Hpoly, Y), rhs)) add_sol(&S, Y, X);
        !           455:     }
1.1       noro      456:
                    457:     if (low_stack(lim,stack_lim(av,1)))
                    458:     {
                    459:       if(DEBUGMEM>1) err(warnmem,"Check_small");
1.2     ! noro      460:       S = gerepilecopy(av, S);
1.1       noro      461:     }
                    462:   }
1.2     ! noro      463:   return S;
1.1       noro      464: }
                    465:
                    466: /* Computes [x]! */
                    467: static double
                    468: fact(double x)
                    469: {
1.2     ! noro      470:   double ft = 1.0;
        !           471:   x = (int)x; while (x>1) { ft *= x; x--; }
1.1       noro      472:   return ft ;
                    473: }
                    474:
                    475: /* From a polynomial and optionally a system of fundamental units for the
1.2     ! noro      476:  * field defined by poly, computes all relevant constants needed to solve
        !           477:  * the equation P(x,y)=a given the solutions of N_{K/Q}(x)=a (see inithue). */
1.1       noro      478: GEN
                    479: thueinit(GEN poly, long flag, long prec)
                    480: {
1.2     ! noro      481:   GEN tnf, bnf = NULL;
        !           482:   gpmem_t av = avma;
        !           483:   long k, s;
        !           484:
        !           485:   if (checktnf(poly)) { bnf = checkbnf((GEN)poly[2]); poly = (GEN)poly[1]; }
        !           486:   if (typ(poly)!=t_POL) err(notpoler,"thueinit");
        !           487:   if (degpol(poly) <= 2) err(talker,"invalid polynomial in thue (need deg>2)");
        !           488:
        !           489:   if (!gisirreducible(poly)) err(redpoler,"thueinit");
        !           490:   s = sturm(poly);
        !           491:   if (s)
        !           492:   {
        !           493:     long PREC, n = degpol(poly);
        !           494:     double d, dr, dn = (double)n;
1.1       noro      495:
1.2     ! noro      496:     dr = (double)((s+n-2)>>1); /* s+t-1 */
        !           497:     d = dn*(dn-1)*(dn-2);
        !           498:     /* Guess precision by approximating Baker's bound. The guess is most of
        !           499:      * the time not sharp, ie 10 to 30 decimal digits above what is _really_
        !           500:      * necessary. Note that the limiting step is the reduction. See paper. */
        !           501:     PREC = 3 + (long)((5.83 + (dr+4)*5 + log(fact(dr+3)) + (dr+3)*log(dr+2) +
        !           502:                     (dr+3)*log(d) + log(log(2*d*(dr+2))) + (dr+1)) / 10.);
        !           503:     if (PREC < prec) PREC = prec;
        !           504:     for (;;)
        !           505:     {
        !           506:       if (( tnf = inithue(poly, bnf, flag, PREC) )) break;
        !           507:       PREC = (PREC<<1)-2;
        !           508:       if (DEBUGLEVEL>1) err(warnprec,"thueinit",PREC);
        !           509:       bnf = NULL; avma = av;
        !           510:     }
        !           511:   }
1.1       noro      512:   else
1.2     ! noro      513:   {
        !           514:     GEN c0 = gun, ro = roots(poly, DEFAULTPREC);
        !           515:     for (k=1; k<lg(ro); k++) c0 = gmul(c0, gimag((GEN)ro[k]));
        !           516:     c0 = ginv( mpabs(c0) );
        !           517:     tnf = cgetg(3,t_VEC);
        !           518:     tnf[1] = (long)poly;
        !           519:     tnf[2] = (long)c0;
        !           520:   }
        !           521:   return gerepilecopy(av,tnf);
        !           522: }
1.1       noro      523:
1.2     ! noro      524: static GEN
        !           525: get_B0(int i1, GEN Delta, GEN Lambda, GEN eps5, long prec, baker_s *BS)
        !           526: {
        !           527:   GEN delta, lambda, errdelta, B0 = Baker(BS);
        !           528:   int i2, r = BS->r;
        !           529:
        !           530:   i2 = (i1 == 1)? 2: 1;
        !           531:   for(;;) /* i2 from 1 to r unless r = 1 [then i2 = 2] */
1.1       noro      532:   {
1.2     ! noro      533:     if (r > 1)
        !           534:     {
        !           535:       delta = divrr((GEN)Delta[i2],(GEN)Delta[i1]);
        !           536:       lambda = gdiv(gsub(gmul((GEN)Delta[i2],(GEN)Lambda[i1]),
        !           537:                          gmul((GEN)Delta[i1],(GEN)Lambda[i2])),
        !           538:                     (GEN)Delta[i1]);
        !           539:       errdelta = mulrr(addsr(1,delta),
        !           540:                        divrr(eps5, subrr(mpabs((GEN)Delta[i1]),eps5)));
        !           541:     }
        !           542:     else
        !           543:     { /* r == 1, single fundamental unit (i1 = s = t = 1) */
        !           544:       GEN p1, Pi2 = Pi2n(1, prec);
        !           545:       GEN fu = (GEN)BS->MatFU[1], ro = BS->ro;
        !           546:
        !           547:       p1 = gdiv((GEN)fu[2], (GEN)fu[3]);
        !           548:       delta = divrr(garg(p1,prec), Pi2);
        !           549:
        !           550:       p1 = gmul(gdiv(gsub((GEN)ro[1], (GEN)ro[2]),
        !           551:                      gsub((GEN)ro[1], (GEN)ro[3])),
        !           552:                 gdiv((GEN)BS->NE[3], (GEN)BS->NE[2]));
        !           553:       lambda = divrr(garg(p1,prec), Pi2);
        !           554:
        !           555:       errdelta = gdiv(gmul2n(gun, 1 - bit_accuracy(prec)),
        !           556:                       gabs((GEN)fu[2],prec));
        !           557:     }
        !           558:     BS->delta = delta;
        !           559:     BS->lambda= lambda; BS->errdelta = errdelta;
        !           560:     if (DEBUGLEVEL>1) fprintferr("  errdelta = %Z\n",errdelta);
        !           561:
        !           562:     if (DEBUGLEVEL>1) fprintferr("  Entering CF...\n");
        !           563:     /* Reduce B0 as long as we make progress: newB0 < oldB0 - 0.1 */
        !           564:     for (;;)
        !           565:     {
        !           566:       GEN oldB0 = B0, kappa = stoi(10);
        !           567:       int cf;
        !           568:
        !           569:       for (cf = 0; cf < 10; cf++, kappa = mulis(kappa,10))
        !           570:       {
        !           571:         int res = CF_1stPass(&B0, kappa, BS);
        !           572:         if (res < 0) return NULL; /* prec problem */
        !           573:         if (res) break;
        !           574:         if (DEBUGLEVEL>1) fprintferr("CF failed. Increasing kappa\n");
        !           575:       }
        !           576:       if (cf == 10)
        !           577:       { /* Semirational or totally rational case */
        !           578:         GEN Q, ep, q, l0, denbound;
        !           579:
        !           580:         if (! (Q = GuessQi(delta, lambda, &ep)) ) break;
        !           581:
        !           582:         denbound = gadd(B0, absi((GEN)Q[2]));
        !           583:         q = denom( bestappr(delta, denbound) );
        !           584:         l0 = subrr(errnum(delta, q), ep);
        !           585:         if (signe(l0) <= 0) break;
        !           586:
        !           587:         B0 = divrr(mplog(divrr(mulir((GEN)Q[3], BS->c15), l0)),  BS->c13);
        !           588:         if (DEBUGLEVEL>1) fprintferr("Semirat. reduction: B0 -> %Z\n",B0);
        !           589:       }
        !           590:       /* if no progress, stop */
        !           591:       if (gcmp(oldB0, gadd(B0,dbltor(0.1))) <= 0) return gmin(oldB0, B0);
        !           592:     }
        !           593:     i2++; if (i2 == i1) i2++;
        !           594:     if (i2 > r) break;
        !           595:   }
        !           596:   err(bugparier,"thue (totally rational case)");
        !           597:   return NULL; /* not reached */
1.1       noro      598: }
                    599:
1.2     ! noro      600: static GEN
        !           601: LargeSols(GEN tnf, GEN rhs, GEN ne, GEN *pro, GEN *pS)
1.1       noro      602: {
1.2     ! noro      603:   GEN Vect, P, ro, bnf, MatFU, A, csts, dP, vecdP;
        !           604:   GEN c1,c2,c3,c4,c10,c11,c13,c14,c15, x0, x1, x2, x3, b, zp1, tmp, eps5;
        !           605:   int iroot, ine, n, i, r,s,t;
        !           606:   long upb, bi1, Prec, prec;
        !           607:   baker_s BS;
        !           608:   gpmem_t av = avma;
        !           609:
        !           610:   bnf  = (GEN)tnf[2];
        !           611:   if (!ne) ne = bnfisintnorm(bnf, rhs);
        !           612:   if (lg(ne)==1) return NULL;
        !           613:   nf_get_sign(checknf(bnf), (long*)&s, (long*)&t);
        !           614:   BS.r = r = s+t-1;
        !           615:   P      = (GEN)tnf[1]; n = degpol(P);
        !           616:   ro     = (GEN)tnf[3];
        !           617:   BS.ALH = (GEN)tnf[4];
        !           618:   MatFU  = (GEN)tnf[5];
        !           619:   A      = (GEN)tnf[6];
        !           620:   csts   = (GEN)tnf[7];
        !           621:   c1     = (GEN)csts[1]; c1 = gmul(absi(rhs), c1);
        !           622:   c2     = (GEN)csts[2];
        !           623:   BS.hal = (GEN)csts[3];
        !           624:   x0     = (GEN)csts[4];
        !           625:   eps5   = (GEN)csts[5];
        !           626:   Prec = gtolong((GEN)csts[6]);
        !           627:   BS.MatFU = MatFU;
        !           628:   BS.bak = mulss(n, (n-1)*(n-2)); /* safe */
        !           629:   *pS = cgetg(1, t_VEC);
        !           630:
        !           631:   if (t) x0 = gmul(x0, absisqrtn(rhs, n, Prec));
        !           632:   tmp = divrr(c1,c2);
        !           633:   c3 = mulrr(dbltor(1.39), tmp);
        !           634:   c4 = mulsr(n-1, c3);
        !           635:   x1 = gmax(x0, mpsqrtn(mulsr(2,tmp),n));
        !           636:
        !           637:   Vect = cgetg(r+1,t_COL); for (i=1; i<=r; i++) Vect[i]=un;
        !           638:   Vect = gmul(gabs(A,DEFAULTPREC), Vect);
        !           639:   c14 = mulrr(c4, Vecmax(Vect));
        !           640:   x2 = gmax(x1, mpsqrtn(mulsr(10,c14), n));
        !           641:   if (DEBUGLEVEL>1) {
        !           642:     fprintferr("x1 -> %Z\n",x1);
        !           643:     fprintferr("x2 -> %Z\n",x2);
        !           644:     fprintferr("c14 = %Z\n",c14);
        !           645:   }
1.1       noro      646:
1.2     ! noro      647:   dP = derivpol(P);
        !           648:   vecdP = cgetg(s+1, t_VEC);
        !           649:   for (i=1; i<=s; i++) vecdP[i] = (long)poleval(dP, (GEN)ro[i]);
        !           650:
        !           651:   zp1 = dbltor(0.01);
        !           652:   x3 = gmax(x2, mpsqrtn(mulsr(2,divrr(c14,zp1)),n));
        !           653:
        !           654:   b = cgetg(r+1,t_COL);
        !           655:   for (iroot=1; iroot<=s; iroot++)
        !           656:   {
        !           657:     GEN Delta, MatNE, Hmu, c5, c7;
        !           658:
        !           659:     Vect = cgetg(r+1,t_COL); for (i=1; i<=r; i++) Vect[i] = un;
        !           660:     if (iroot <= r) Vect[iroot] = lstoi(1-n);
        !           661:     Delta = gmul(A,Vect);
        !           662:
        !           663:     c5 = Vecmax(gabs(Delta,Prec));
        !           664:     c5  = myround(gprec_w(c5,DEFAULTPREC), 1);
        !           665:     c7  = mulsr(r,c5);
        !           666:     c10 = divsr(n,c7); BS.c10 = c10;
        !           667:     c13 = divsr(n,c5); BS.c13 = c13;
        !           668:     if (DEBUGLEVEL>1) {
        !           669:       fprintferr("* real root no %ld/%ld\n", iroot,s);
        !           670:       fprintferr("  c10 = %Z\n",c10);
        !           671:       fprintferr("  c13 = %Z\n",c13);
        !           672:     }
        !           673:
        !           674:     prec = Prec;
        !           675:     for (;;)
        !           676:     {
        !           677:       if (( MatNE = Conj_LH(ne, &Hmu, ro, prec) )) break;
        !           678:       prec = (prec<<1)-2;
        !           679:       if (DEBUGLEVEL>1) err(warnprec,"thue",prec);
        !           680:       ro = tnf_get_roots(P, prec, s, t);
        !           681:     }
        !           682:     BS.ro    = ro;
        !           683:     BS.iroot = iroot;
1.1       noro      684:
1.2     ! noro      685:     for (ine=1; ine<lg(ne); ine++)
1.1       noro      686:     {
1.2     ! noro      687:       GEN Lambda, B0, c6, c8;
        !           688:       GEN NE = (GEN)MatNE[ine], Vect2 = cgetg(r+1,t_COL);
        !           689:       int k, i1;
        !           690:
        !           691:       if (DEBUGLEVEL>1) fprintferr("  - norm sol. no %ld/%ld\n",ine,lg(ne)-1);
        !           692:       for (k=1; k<=r; k++)
1.1       noro      693:       {
1.2     ! noro      694:         if (k == iroot)
        !           695:           tmp = gdiv(rhs, gmul((GEN)vecdP[k], (GEN)NE[k]));
        !           696:         else
        !           697:           tmp = gdiv(gsub((GEN)ro[iroot],(GEN)ro[k]), (GEN)NE[k]);
        !           698:         Vect2[k] = llog(gabs(tmp,prec), prec);
        !           699:       }
        !           700:       Lambda = gmul(A,Vect2);
        !           701:
        !           702:       c6 = addrr(dbltor(0.1), Vecmax(gabs(Lambda,DEFAULTPREC)));
        !           703:       c6 = myround(c6, 1);
        !           704:       c8 = addrr(dbltor(1.23), mulsr(r,c6));
        !           705:       c11= mulrr(mulsr(2,c3) , mpexp(divrr(mulsr(n,c8),c7)));
        !           706:       c15= mulrr(mulsr(2,c14), mpexp(divrr(mulsr(n,c6),c5)));
        !           707:
        !           708:       if (DEBUGLEVEL>1) {
        !           709:         fprintferr("  c6  = %Z\n",c6);
        !           710:         fprintferr("  c8  = %Z\n",c8);
        !           711:         fprintferr("  c11 = %Z\n",c11);
        !           712:         fprintferr("  c15 = %Z\n",c15);
        !           713:       }
        !           714:       BS.c11 = c11;
        !           715:       BS.c15 = c15;
        !           716:       BS.NE = NE;
        !           717:       BS.Hmu = (GEN)Hmu[ine];
        !           718:
        !           719:       i1 = Vecmaxind(gabs(Delta,prec));
        !           720:       if (! (B0 = get_B0(i1, Delta, Lambda, eps5, prec, &BS)) ) goto PRECPB;
        !           721:
        !           722:      /* For each possible value of b_i1, compute the b_i's
        !           723:       * and 2 conjugates of z = x - alpha y. Then check. */
        !           724:       upb = gtolong(gceil(B0));
        !           725:       for (bi1=-upb; bi1<=upb; bi1++)
        !           726:       {
        !           727:         GEN z1, z2;
        !           728:         for (i=1; i<=r; i++)
        !           729:         {
        !           730:           b[i] = ldiv(gsub(gmul((GEN)Delta[i], stoi(bi1)),
        !           731:                            gsub(gmul((GEN)Delta[i],(GEN)Lambda[i1]),
        !           732:                                 gmul((GEN)Delta[i1],(GEN)Lambda[i]))),
        !           733:                       (GEN)Delta[i1]);
        !           734:           if (gcmp(distoZ((GEN)b[i]), zp1) > 0) break;
        !           735:         }
        !           736:         if (i <= r) continue;
        !           737:
        !           738:         z1 = z2 = gun;
        !           739:         for(i=1; i<=r; i++)
        !           740:         {
        !           741:           GEN c = ground((GEN)b[i]);
        !           742:           z1 = gmul(z1, powgi(gcoeff(MatFU,1,i), c));
        !           743:           z2 = gmul(z2, powgi(gcoeff(MatFU,2,i), c));
        !           744:         }
        !           745:         z1 = gmul(z1, (GEN)NE[1]);
        !           746:         z2 = gmul(z2, (GEN)NE[2]);
        !           747:         if (!CheckSol(pS, z1,z2,P,rhs,ro)) goto PRECPB;
1.1       noro      748:       }
                    749:     }
                    750:   }
1.2     ! noro      751:   *pro = ro; return x3;
1.1       noro      752:
1.2     ! noro      753: PRECPB:
        !           754:   ne = gerepilecopy(av, ne);
        !           755:   prec += 5 * (DEFAULTPREC-2);
        !           756:   if (DEBUGLEVEL>1) err(warnprec,"thue",prec);
        !           757:   tnf = inithue(P, bnf, 0, prec);
        !           758:   return LargeSols(tnf, rhs, ne, pro, pS);
        !           759: }
        !           760:
        !           761: /* Given a tnf structure as returned by thueinit, a RHS and
        !           762:  * optionally the solutions to the norm equation, returns the solutions to
        !           763:  * the Thue equation F(x,y)=a
        !           764:  */
        !           765: GEN
        !           766: thue(GEN tnf, GEN rhs, GEN ne)
        !           767: {
        !           768:   gpmem_t av = avma;
        !           769:   GEN P, ro, x3, S;
        !           770:
        !           771:   if (!checktnf(tnf)) err(talker,"not a tnf in thue");
        !           772:   if (typ(rhs) != t_INT) err(typeer,"thue");
        !           773:
        !           774:   P = (GEN)tnf[1];
        !           775:   if (lg(tnf) == 8)
        !           776:   {
        !           777:     x3 = LargeSols(tnf, rhs, ne, &ro, &S);
        !           778:     if (!x3) { avma = av; return cgetg(1,t_VEC); }
        !           779:   }
        !           780:   else
        !           781:   { /* Case s=0. All solutions are "small". */
        !           782:     GEN c0   = (GEN)tnf[2]; /* t_REAL */
        !           783:     S = cgetg(1,t_VEC);
        !           784:     ro = roots(P, DEFAULTPREC);
        !           785:     x3 = mpsqrtn(mulir(constant_term(P), divir(absi(rhs),c0)), degpol(P));
        !           786:   }
        !           787:   return gerepilecopy(av, SmallSols(S, gtolong(x3), P, rhs, ro));
1.1       noro      788: }
                    789:
                    790: static GEN *Relations; /* primes above a, expressed on generators of Cl(K) */
                    791: static GEN *Partial;   /* list of vvectors, Partial[i] = Relations[1..i] * u[1..i] */
                    792: static GEN *gen_ord;   /* orders of generators of Cl(K) given in bnf */
                    793:
                    794: static long *f;        /* f[i] = f(Primes[i]/p), inertial degree */
                    795: static long *n;        /* a = prod p^{ n_p }. n[i]=n_p if Primes[i] divides p */
                    796: static long *inext;    /* index of first P above next p, 0 if p is last */
                    797: static long *S;        /* S[i] = n[i] - sum_{ 1<=k<=i } f[k].u[k] */
                    798: static long *u;        /* We want principal ideals I = prod Primes[i]^u[i] */
                    799: static long **normsol; /* lists of copies of the u[] which are solutions */
                    800:
                    801: static long Nprimes; /* length(Relations) = #{max ideal above divisors of a} */
                    802: static long sindex, smax; /* current index in normsol; max. index */
                    803:
                    804: /* u[1..i] has been filled. Norm(u) is correct.
                    805:  * Check relations in class group then save it.
                    806:  */
                    807: static void
                    808: test_sol(long i)
                    809: {
                    810:   long k,*sol;
                    811:
                    812:   if (Partial)
                    813:   {
1.2     ! noro      814:     gpmem_t av=avma;
1.1       noro      815:     for (k=1; k<lg(Partial[1]); k++)
                    816:       if ( signe(modii( (GEN)Partial[i][k], gen_ord[k] )) )
                    817:         { avma=av; return; }
                    818:     avma=av;
                    819:   }
                    820:   if (sindex == smax)
                    821:   {
                    822:     long new_smax = smax << 1;
                    823:     long **new_normsol = (long **) new_chunk(new_smax+1);
                    824:
                    825:     for (k=1; k<=smax; k++) new_normsol[k] = normsol[k];
                    826:     normsol = new_normsol; smax = new_smax;
                    827:   }
                    828:   sol = cgetg(Nprimes+1,t_VECSMALL);
                    829:   normsol[++sindex] = sol;
                    830:
                    831:   for (k=1; k<=i; k++) sol[k]=u[k];
                    832:   for (   ; k<=Nprimes; k++) sol[k]=0;
1.2     ! noro      833:   if (DEBUGLEVEL>2)
1.1       noro      834:   {
                    835:     fprintferr("sol = %Z\n",sol);
                    836:     if (Partial) fprintferr("Partial = %Z\n",Partial);
                    837:     flusherr();
                    838:   }
                    839: }
                    840: static void
                    841: fix_Partial(long i)
                    842: {
1.2     ! noro      843:   long k;
        !           844:   gpmem_t av = avma;
1.1       noro      845:   for (k=1; k<lg(Partial[1]); k++)
                    846:     addiiz(
                    847:       (GEN) Partial[i-1][k],
                    848:             mulis((GEN) Relations[i][k], u[i]),
                    849:       (GEN) Partial[i][k]
                    850:     );
                    851:   avma=av;
                    852: }
                    853:
                    854: /* Recursive loop. Suppose u[1..i] has been filled
                    855:  * Find possible solutions u such that, Norm(prod Prime[i]^u[i]) = a, taking
                    856:  * into account:
                    857:  *  1) the relations in the class group if need be.
                    858:  *  2) the factorization of a.
                    859:  */
                    860: static void
                    861: isintnorm_loop(long i)
                    862: {
                    863:   if (S[i] == 0) /* sum u[i].f[i] = n[i], do another prime */
                    864:   {
                    865:     int k;
                    866:     if (inext[i] == 0) { test_sol(i); return; }
                    867:
                    868:     /* there are some primes left */
                    869:     if (Partial) gaffect(Partial[i], Partial[inext[i]-1]);
                    870:     for (k=i+1; k < inext[i]; k++) u[k]=0;
                    871:     i=inext[i]-1;
                    872:   }
                    873:   else if (i == inext[i]-2 || i == Nprimes-1)
                    874:   {
                    875:     /* only one Prime left above prime; change prime, fix u[i+1] */
                    876:     if (S[i] % f[i+1]) return;
                    877:     i++; u[i] = S[i-1] / f[i];
                    878:     if (Partial) fix_Partial(i);
                    879:     if (inext[i]==0) { test_sol(i); return; }
                    880:   }
                    881:
                    882:   i++; u[i]=0;
                    883:   if (Partial) gaffect(Partial[i-1], Partial[i]);
                    884:   if (i == inext[i-1])
                    885:   { /* change prime */
                    886:     if (inext[i] == i+1 || i == Nprimes) /* only one Prime above p */
                    887:     {
                    888:       S[i]=0; u[i] = n[i] / f[i]; /* we already know this is exact */
                    889:       if (Partial) fix_Partial(i);
                    890:     }
                    891:     else S[i] = n[i];
                    892:   }
                    893:   else S[i] = S[i-1]; /* same prime, different Prime */
                    894:   for(;;)
                    895:   {
                    896:     isintnorm_loop(i); S[i]-=f[i]; if (S[i]<0) break;
                    897:     if (Partial)
                    898:       gaddz(Partial[i], Relations[i], Partial[i]);
                    899:     u[i]++;
                    900:   }
                    901: }
                    902:
                    903: static void
                    904: get_sol_abs(GEN bnf, GEN a, GEN **ptPrimes)
                    905: {
                    906:   GEN dec, fact, primes, *Primes, *Fact;
                    907:   long *gcdlist, gcd,nprimes,Ngen,i,j;
                    908:
                    909:   if (gcmp1(a))
                    910:   {
                    911:     long *sol = new_chunk(Nprimes+1);
                    912:     sindex = 1; normsol = (long**) new_chunk(2);
                    913:     normsol[1] = sol; for (i=1; i<=Nprimes; i++) sol[i]=0;
                    914:     return;
                    915:   }
                    916:
                    917:   fact=factor(a); primes=(GEN)fact[1];
                    918:   nprimes=lg(primes)-1; sindex = 0;
                    919:   gen_ord = (GEN *) mael3(bnf,8,1,2); Ngen = lg(gen_ord)-1;
                    920:
                    921:   Fact = (GEN*) new_chunk(1+nprimes);
                    922:   gcdlist = new_chunk(1+nprimes);
                    923:
                    924:   Nprimes=0;
                    925:   for (i=1; i<=nprimes; i++)
                    926:   {
                    927:     long ldec;
                    928:
                    929:     dec = primedec(bnf,(GEN)primes[i]); ldec = lg(dec)-1;
                    930:     gcd = itos(gmael(dec,1,4));
                    931:
                    932:     /* check that gcd_{P|p} f_P | n_p */
                    933:     for (j=2; gcd>1 && j<=ldec; j++)
                    934:       gcd = cgcd(gcd,itos(gmael(dec,j,4)));
                    935:
                    936:     gcdlist[i]=gcd;
                    937:
                    938:     if (gcd != 1 && smodis(gmael(fact,2,i),gcd))
                    939:     {
                    940:       if (DEBUGLEVEL>2)
                    941:         { fprintferr("gcd f_P  does not divide n_p\n"); flusherr(); }
                    942:       return;
                    943:     }
                    944:     Fact[i] = dec; Nprimes += ldec;
                    945:   }
                    946:
                    947:   f = new_chunk(1+Nprimes); u = new_chunk(1+Nprimes);
                    948:   n = new_chunk(1+Nprimes); S = new_chunk(1+Nprimes);
                    949:   inext = new_chunk(1+Nprimes);
                    950:   Primes = (GEN*) new_chunk(1+Nprimes);
                    951:   *ptPrimes = Primes;
                    952:
                    953:   if (Ngen)
                    954:   {
                    955:     Partial = (GEN*) new_chunk(1+Nprimes);
                    956:     Relations = (GEN*) new_chunk(1+Nprimes);
                    957:   }
                    958:   else /* trivial class group, no relations to check */
                    959:     Relations = Partial = NULL;
                    960:
                    961:   j=0;
                    962:   for (i=1; i<=nprimes; i++)
                    963:   {
                    964:     long k,lim,v, vn=itos(gmael(fact,2,i));
                    965:
                    966:     gcd = gcdlist[i];
                    967:     dec = Fact[i]; lim = lg(dec);
                    968:     v = (i==nprimes)? 0: j + lim;
                    969:     for (k=1; k < lim; k++)
                    970:     {
                    971:       j++; Primes[j] = (GEN)dec[k];
                    972:       f[j] = itos(gmael(dec,k,4)) / gcd;
                    973:       n[j] = vn / gcd; inext[j] = v;
                    974:       if (Partial)
                    975:        Relations[j] = isprincipal(bnf,Primes[j]);
                    976:     }
                    977:   }
                    978:   if (Partial)
                    979:   {
                    980:     for (i=1; i <= Nprimes; i++)
                    981:       if (!gcmp0(Relations[i])) break;
                    982:     if (i > Nprimes) Partial = NULL; /* all ideals dividing a are principal */
                    983:   }
                    984:   if (Partial)
                    985:     for (i=0; i<=Nprimes; i++) /* Partial[0] needs to be initialized */
                    986:     {
                    987:       Partial[i]=cgetg(Ngen+1,t_COL);
                    988:       for (j=1; j<=Ngen; j++)
                    989:       {
                    990:        Partial[i][j]=lgeti(4);
                    991:        gaffect(gzero,(GEN) Partial[i][j]);
                    992:       }
                    993:     }
                    994:   smax=511; normsol = (long**) new_chunk(smax+1);
                    995:   S[0]=n[1]; inext[0]=1; isintnorm_loop(0);
                    996: }
                    997:
                    998: static long
                    999: get_unit_1(GEN bnf, GEN pol, GEN *unit)
                   1000: {
                   1001:   GEN fu;
                   1002:   long j;
                   1003:
                   1004:   if (DEBUGLEVEL > 2)
                   1005:     fprintferr("looking for a fundamental unit of norm -1\n");
                   1006:
                   1007:   *unit = gmael3(bnf,8,4,2);  /* torsion unit */
                   1008:   if (signe( gnorm(gmodulcp(*unit,pol)) ) < 0) return 1;
                   1009:
                   1010:   fu = gmael(bnf,8,5); /* fundamental units */
                   1011:   for (j=1; j<lg(fu); j++)
                   1012:   {
                   1013:     *unit = (GEN)fu[j];
                   1014:     if (signe( gnorm(gmodulcp(*unit,pol)) ) < 0) return 1;
                   1015:   }
                   1016:   return 0;
                   1017: }
                   1018:
                   1019: GEN
                   1020: bnfisintnorm(GEN bnf, GEN a)
                   1021: {
                   1022:   GEN nf,pol,res,unit,x,id, *Primes;
                   1023:   long sa,i,j,norm_1;
1.2     ! noro     1024:   gpmem_t av = avma;
1.1       noro     1025:
                   1026:   bnf = checkbnf(bnf); nf = (GEN)bnf[7]; pol = (GEN)nf[1];
                   1027:   if (typ(a)!=t_INT)
                   1028:     err(talker,"expected an integer in bnfisintnorm");
                   1029:   sa = signe(a);
1.2     ! noro     1030:   if (sa == 0)  return _vec(gzero);
        !          1031:   if (gcmp1(a)) return _vec(gun);
1.1       noro     1032:
                   1033:   get_sol_abs(bnf, absi(a), &Primes);
                   1034:
                   1035:   res = cgetg(1,t_VEC); unit = NULL;
                   1036:   norm_1 = 0; /* gcc -Wall */
                   1037:   for (i=1; i<=sindex; i++)
                   1038:   {
1.2     ! noro     1039:     x = normsol[i];
        !          1040:     id = idealpow(nf,Primes[1], stoi(x[1]));
        !          1041:     for (j=2; j<=Nprimes; j++) /* compute prod Primes[i]^u[i] */
        !          1042:       id = idealmulpowprime(nf,id, Primes[j], stoi(x[j]));
1.1       noro     1043:     x = (GEN) isprincipalgenforce(bnf,id)[2];
                   1044:     x = gmul((GEN)nf[7],x); /* x possible solution */
                   1045:     if (signe(gnorm(gmodulcp(x,(GEN)nf[1]))) != sa)
                   1046:     {
                   1047:       if (! unit) norm_1 = get_unit_1(bnf,pol,&unit);
                   1048:       if (norm_1) x = gmul(unit,x);
                   1049:       else
                   1050:       {
1.2     ! noro     1051:         if (DEBUGLEVEL > 2) fprintferr("%Z eliminated because of sign\n",x);
1.1       noro     1052:         x = NULL;
                   1053:       }
                   1054:     }
                   1055:     if (x) res = concatsp(res, gmod(x,pol));
                   1056:   }
                   1057:   return gerepilecopy(av,res);
                   1058: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>