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

Annotation of OpenXM_contrib/pari-2.2/src/basemath/bibli1.c, Revision 1.1

1.1     ! noro        1: /* $Id: bibli1.c,v 1.76 2001/10/01 12:11:29 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: /********************************************************************/
        !            17: /**                                                                **/
        !            18: /**                 LLL Algorithm and close friends                **/
        !            19: /**                                                                **/
        !            20: /********************************************************************/
        !            21: #include "pari.h"
        !            22: #include "parinf.h"
        !            23: extern GEN ZV_lincomb(GEN u, GEN v, GEN X, GEN Y);
        !            24: extern GEN roots_to_pol_r1r2(GEN a, long r1, long v);
        !            25: extern GEN makebasis(GEN nf,GEN pol);
        !            26: extern GEN caractducos(GEN p, GEN x, int v);
        !            27:
        !            28: /* scalar product x.x */
        !            29: GEN
        !            30: sqscal(GEN x)
        !            31: {
        !            32:   long i,av,lx;
        !            33:   GEN z;
        !            34:   lx = lg(x);
        !            35:   if (lx == 1) return gzero;
        !            36:   av = avma;
        !            37:   z = gsqr((GEN)x[1]);
        !            38:   for (i=2; i<lx; i++)
        !            39:     z = gadd(z, gsqr((GEN)x[i]));
        !            40:   return gerepileupto(av,z);
        !            41: }
        !            42:
        !            43: /* scalar product x.y */
        !            44: GEN
        !            45: gscal(GEN x,GEN y)
        !            46: {
        !            47:   long i,av,lx;
        !            48:   GEN z;
        !            49:   if (x == y) return sqscal(x);
        !            50:   lx = lg(x);
        !            51:   if (lx == 1) return gzero;
        !            52:   av = avma;
        !            53:   z = gmul((GEN)x[1],(GEN)y[1]);
        !            54:   for (i=2; i<lx; i++)
        !            55:     z = gadd(z, gmul((GEN)x[i],(GEN)y[i]));
        !            56:   return gerepileupto(av,z);
        !            57: }
        !            58:
        !            59: static GEN
        !            60: sqscali(GEN x)
        !            61: {
        !            62:   long i,av,lx;
        !            63:   GEN z;
        !            64:   lx = lg(x);
        !            65:   if (lx == 1) return gzero;
        !            66:   av = avma;
        !            67:   z = sqri((GEN)x[1]);
        !            68:   for (i=2; i<lx; i++)
        !            69:     z = addii(z, sqri((GEN)x[i]));
        !            70:   return gerepileuptoint(av,z);
        !            71: }
        !            72:
        !            73: static GEN
        !            74: gscali(GEN x,GEN y)
        !            75: {
        !            76:   long i,av,lx;
        !            77:   GEN z;
        !            78:   if (x == y) return sqscali(x);
        !            79:   lx = lg(x);
        !            80:   if (lx == 1) return gzero;
        !            81:   av = avma;
        !            82:   z = mulii((GEN)x[1],(GEN)y[1]);
        !            83:   for (i=2; i<lx; i++)
        !            84:     z = addii(z, mulii((GEN)x[i],(GEN)y[i]));
        !            85:   return gerepileuptoint(av,z);
        !            86: }
        !            87:
        !            88: static GEN
        !            89: lllall_trivial(GEN x, long n, long flag)
        !            90: {
        !            91:   GEN y;
        !            92:   if (!n)
        !            93:   {
        !            94:     if (flag != lll_ALL) return cgetg(1,t_MAT);
        !            95:     y=cgetg(3,t_VEC);
        !            96:     y[1]=lgetg(1,t_MAT);
        !            97:     y[2]=lgetg(1,t_MAT); return y;
        !            98:   }
        !            99:   /* here n = 1 */
        !           100:   if (gcmp0((GEN)x[1]))
        !           101:   {
        !           102:     switch(flag ^ lll_GRAM)
        !           103:     {
        !           104:       case lll_KER: return idmat(1);
        !           105:       case lll_IM : return cgetg(1,t_MAT);
        !           106:       default: y=cgetg(3,t_VEC);
        !           107:         y[1]=(long)idmat(1);
        !           108:         y[2]=lgetg(1,t_MAT); return y;
        !           109:     }
        !           110:   }
        !           111:   if (flag & lll_GRAM) flag ^= lll_GRAM; else x = NULL;
        !           112:   switch (flag)
        !           113:   {
        !           114:     case lll_KER: return cgetg(1,t_MAT);
        !           115:     case lll_IM : return idmat(1);
        !           116:     default: y=cgetg(3,t_VEC);
        !           117:       y[1]=lgetg(1,t_MAT);
        !           118:       y[2]=x? lcopy(x): (long)idmat(1); return y;
        !           119:   }
        !           120: }
        !           121:
        !           122: static GEN
        !           123: lllgramall_finish(GEN h,GEN fl,long flag,long n)
        !           124: {
        !           125:   long k;
        !           126:   GEN y;
        !           127:
        !           128:   k=1; while (k<=n && !fl[k]) k++;
        !           129:   switch(flag)
        !           130:   {
        !           131:     case lll_KER: setlg(h,k);
        !           132:       y = gcopy(h); break;
        !           133:
        !           134:     case lll_IM: h += k-1; h[0] = evaltyp(t_MAT)| evallg(n-k+2);
        !           135:       y = gcopy(h); break;
        !           136:
        !           137:     default: setlg(h,k); y=cgetg(3,t_VEC);
        !           138:       y[1] = lcopy(h);
        !           139:       h += k-1; h[0] = evaltyp(t_MAT)| evallg(n-k+2);
        !           140:       y[2] = lcopy(h);
        !           141:       break;
        !           142:   }
        !           143:   return y;
        !           144: }
        !           145:
        !           146: /********************************************************************/
        !           147: /**                                                                **/
        !           148: /**                          LLL with content                      **/
        !           149: /**                                                                **/
        !           150: /********************************************************************/
        !           151:
        !           152: /* real Gram matrix has coeffs X[i,j] = x[i,j]*veccon[i]*veccon[j] */
        !           153: static GEN
        !           154: lllgramintwithcontent(GEN x, GEN veccon, long flag)
        !           155: {
        !           156:   long av0=avma,av,tetpil,lx=lg(x),i,j,k,l,n,lim,kmax;
        !           157:   GEN u,u2,B,lam,q,r,h,la,bb,p1,p2,p3,p4,fl,corr,corr2,newcon;
        !           158:   GEN *gptr[8];
        !           159:
        !           160:   if (typ(x) != t_MAT) err(typeer,"lllgramintwithcontent");
        !           161:   n=lx-1; if (n<=1) return lllall_trivial(x,n,flag);
        !           162:   if (lg((GEN)x[1])!=lx) err(mattype1,"lllgramintwithcontent");
        !           163:   fl = new_chunk(lx);
        !           164:
        !           165:   av=avma; lim=stack_lim(av,1);
        !           166:   x=dummycopy(x); veccon=dummycopy(veccon);
        !           167:   B=cgetg(lx+1,t_COL); B[1]=un;
        !           168:   /* B[i+1]=B_i; le vrai B_i est B_i*prod(1,j=1,i,veccon[j]^2) */
        !           169:
        !           170:   for (i=1; i<lx; i++) { B[i+1]=zero; fl[i]=0; }
        !           171:   lam=cgetg(lx,t_MAT);
        !           172:   for (j=1; j<lx; j++)
        !           173:   { p2=cgetg(lx,t_COL); lam[j]=(long)p2; for (i=1; i<lx; i++) p2[i]=zero; }
        !           174: /* le vrai lam[i,j] est
        !           175:    lam[i,j]*veccon[i]*veccon[j]*prod(1,l=1,j-1,veccon[l]^2) */
        !           176:   k=2; h=idmat(n); kmax=1;
        !           177:   u=gcoeff(x,1,1); if (typ(u)!=t_INT) err(lllger4);
        !           178:   if (signe(u)) { B[2]=(long)u; coeff(lam,1,1)=un; fl[1]=1; }
        !           179:   else { B[2]=un; fl[1]=0; }
        !           180:   if (DEBUGLEVEL>5) { fprintferr("k = %ld",k); flusherr(); }
        !           181:   for(;;)
        !           182:   {
        !           183:     if (k>kmax)
        !           184:     {
        !           185:       kmax=k;
        !           186:       for (j=1; j<=k; j++)
        !           187:       {
        !           188:        if (j==k || fl[j])
        !           189:        {
        !           190:          u=gcoeff(x,k,j); if (typ(u)!=t_INT) err(lllger4);
        !           191:          for (i=1; i<j; i++)
        !           192:            if (fl[i])
        !           193:              u=divii(subii(mulii((GEN)B[i+1],u),mulii(gcoeff(lam,k,i),gcoeff(lam,j,i))),(GEN)B[i]);
        !           194:          if (j<k) coeff(lam,k,j)=(long)u;
        !           195:          else
        !           196:          {
        !           197:            if (signe(u)) { B[k+1]=(long)u; coeff(lam,k,k)=un; fl[k]=1; }
        !           198:            else { B[k+1]=B[k]; fl[k]=0; }
        !           199:          }
        !           200:        }
        !           201:       }
        !           202:       if (low_stack(lim, stack_lim(av,1)))
        !           203:       {
        !           204:        if(DEBUGMEM>1) err(warnmem,"[1]: lllgramintwithcontent");
        !           205:        gptr[0]=&B; gptr[1]=&lam; gptr[2]=&h;
        !           206:        gptr[3]=&x; gptr[4]=&veccon; gerepilemany(av,gptr,5);
        !           207:       }
        !           208:     }
        !           209:     u=shifti(mulii(gcoeff(lam,k,k-1),(GEN)veccon[k]),1);
        !           210:     u2=mulii((GEN)B[k],(GEN)veccon[k-1]);
        !           211:     if (cmpii(absi(u),u2)>0)
        !           212:     {
        !           213:       q=dvmdii(addii(u,u2),shifti(u2,1),&r);
        !           214:       if (signe(r)<0) q=addsi(-1,q);
        !           215:       h[k]=lsub((GEN)h[k],gmul(q,(GEN)h[k-1]));
        !           216:       newcon=mppgcd((GEN)veccon[k],(GEN)veccon[k-1]);
        !           217:       corr=divii((GEN)veccon[k],newcon); veccon[k]=(long)newcon;
        !           218:       if(!gcmp1(corr))
        !           219:       {
        !           220:        corr2=sqri(corr);
        !           221:        for (j=1; j<=n; j++)
        !           222:          coeff(x,j,k)=coeff(x,k,j)=lmulii(corr,gcoeff(x,k,j));
        !           223:        coeff(x,k,k)=lmulii(corr,gcoeff(x,k,k));
        !           224:        for (j=k; j<=kmax; j++) B[j+1]=lmulii(corr2,(GEN)B[j+1]);
        !           225:        for (i=1; i<k; i++) coeff(lam,k,i)=lmulii(corr,gcoeff(lam,k,i));
        !           226:        for (i=k+1; i<=kmax; i++)
        !           227:        {
        !           228:          coeff(lam,i,k)=lmulii(corr,gcoeff(lam,i,k));
        !           229:          for (j=k+1; j<i; j++)
        !           230:            coeff(lam,i,j)=lmulii(corr2,gcoeff(lam,i,j));
        !           231:        }
        !           232:       }
        !           233:       r=negi(mulii(q,divii((GEN)veccon[k-1],(GEN)veccon[k])));
        !           234:       p1=gcoeff(x,k,k-1);
        !           235:       for (j=1; j<=n; j++)
        !           236:        coeff(x,j,k)=coeff(x,k,j)=laddii(gcoeff(x,j,k),mulii(r,(j==k)?p1:gcoeff(x,j,k-1)));
        !           237:       coeff(x,k,k)=laddii(gcoeff(x,k,k),mulii(r,gcoeff(x,k-1,k)));
        !           238:       coeff(lam,k,k-1)=laddii(gcoeff(lam,k,k-1),mulii(r,(GEN)B[k]));
        !           239:       for (i=1; i<k-1; i++)
        !           240:        coeff(lam,k,i)=laddii(gcoeff(lam,k,i),mulii(r,gcoeff(lam,k-1,i)));
        !           241:     }
        !           242:     if (low_stack(lim, stack_lim(av,1)))
        !           243:     {
        !           244:       if(DEBUGMEM>1) err(warnmem,"[2]: lllgramintwithcontent");
        !           245:       gptr[0]=&B; gptr[1]=&lam; gptr[2]=&h;
        !           246:       gptr[3]=&x; gptr[4]=&veccon; gerepilemany(av,gptr,5);
        !           247:     }
        !           248:     p3=mulii((GEN)B[k-1],(GEN)B[k+1]);la=gcoeff(lam,k,k-1);p4=mulii(la,la);
        !           249:     p2=mulsi(100,mulii(mulii((GEN)veccon[k],(GEN)veccon[k]),addii(p3,p4)));
        !           250:     p1=mulii((GEN)veccon[k-1],(GEN)B[k]);p1=mulsi(99,mulii(p1,p1));
        !           251:     if (fl[k-1] && (cmpii(p1,p2)>0 || !fl[k]))
        !           252:     {
        !           253:       if (DEBUGLEVEL>=4 && k==n)
        !           254:        { fprintferr(" (%ld)", expi(p1)-expi(p2)); flusherr(); }
        !           255:       p1=(GEN)h[k-1]; h[k-1]=h[k]; h[k]=(long)p1;
        !           256:       p1=(GEN)x[k-1]; x[k-1]=x[k]; x[k]=(long)p1;
        !           257:       for (j=1; j<=n; j++)
        !           258:       { p1=gcoeff(x,k-1,j); coeff(x,k-1,j)=coeff(x,k,j); coeff(x,k,j)=(long)p1; }
        !           259:       p1=(GEN)veccon[k-1]; veccon[k-1]=veccon[k]; veccon[k]=(long)p1;
        !           260:       for (j=1; j<=k-2; j++)
        !           261:       { p1=gcoeff(lam,k-1,j); coeff(lam,k-1,j)=coeff(lam,k,j); coeff(lam,k,j)=(long)p1; }
        !           262:       if (fl[k])
        !           263:       {
        !           264:        for (i=k+1; i<=kmax; i++)
        !           265:        {
        !           266:          bb=gcoeff(lam,i,k);
        !           267:          coeff(lam,i,k)=ldivii(subii(mulii((GEN)B[k+1],gcoeff(lam,i,k-1)),mulii(la,bb)),(GEN)B[k]);
        !           268:          coeff(lam,i,k-1)=ldivii(addii(mulii(la,gcoeff(lam,i,k-1)),mulii((GEN)B[k-1],bb)),(GEN)B[k]);
        !           269:           if (low_stack(lim, stack_lim(av,1)))
        !           270:          {
        !           271:            if(DEBUGMEM>1) err(warnmem,"[3]: lllgramintwithcontent");
        !           272:            gptr[0]=&B; gptr[1]=&lam; gptr[2]=&h;
        !           273:            gptr[3]=&x; gptr[4]=&la; gptr[5]=&veccon; gptr[6]=&p3;
        !           274:            gptr[7]=&p4; gerepilemany(av,gptr,8);
        !           275:          }
        !           276:        }
        !           277:        B[k]=ldivii(addii(p3,p4),(GEN)B[k]);
        !           278:       }
        !           279:       else
        !           280:       {
        !           281:        if (signe(la))
        !           282:        {
        !           283:          p2=(GEN)B[k]; p1=divii(p4,p2);
        !           284:          for (i=k+1; i<=kmax; i++)
        !           285:            coeff(lam,i,k-1)=ldivii(mulii(la,gcoeff(lam,i,k-1)),p2);
        !           286:          for (j=k+1; j<kmax; j++)
        !           287:          {
        !           288:            for (i=j+1; i<=kmax; i++)
        !           289:              coeff(lam,i,j)=ldivii(mulii(p1,gcoeff(lam,i,j)),p2);
        !           290:             if (low_stack(lim, stack_lim(av,1)))
        !           291:            {
        !           292:              if(DEBUGMEM>1) err(warnmem,"[4]: lllgramintwithcontent");
        !           293:              gptr[0]=&B; gptr[1]=&lam; gptr[2]=&h;
        !           294:              gptr[3]=&x; gptr[4]=&la; gptr[5]=&veccon; gptr[6]=&p1;
        !           295:              gptr[7]=&p2; gerepilemany(av,gptr,8);
        !           296:            }
        !           297:          }
        !           298:          B[k+1]=B[k]=(long)p1;
        !           299:          for (i=k+2; i<=lx; i++)
        !           300:            B[i]=ldivii(mulii(p1,(GEN)B[i]),p2);
        !           301:        }
        !           302:        else
        !           303:        {
        !           304:          coeff(lam,k,k-1)=zero;
        !           305:          for (i=k+1; i<=kmax; i++)
        !           306:          {
        !           307:            coeff(lam,i,k)=coeff(lam,i,k-1);
        !           308:            coeff(lam,i,k-1)=zero;
        !           309:          }
        !           310:          B[k]=B[k-1]; fl[k]=1; fl[k-1]=0;
        !           311:        }
        !           312:
        !           313:         if (low_stack(lim, stack_lim(av,1)))
        !           314:        {
        !           315:          if(DEBUGMEM>1) err(warnmem,"[5]: lllgramintwithcontent");
        !           316:          gptr[0]=&B; gptr[1]=&lam; gptr[2]=&h;
        !           317:          gptr[3]=&x; gptr[4]=&veccon;
        !           318:          gerepilemany(av,gptr,5);
        !           319:        }
        !           320:       }
        !           321:       if (k>2) k--;
        !           322:       if (DEBUGLEVEL>5) { fprintferr(" %ld",k); flusherr(); }
        !           323:     }
        !           324:     else
        !           325:     {
        !           326:       for (l=k-2; l>=1; l--)
        !           327:       {
        !           328:        u=shifti(mulii(gcoeff(lam,k,l),(GEN)veccon[k]),1);
        !           329:        u2=mulii((GEN)B[l+1],(GEN)veccon[l]);
        !           330:        if (cmpii(absi(u),u2)>0)
        !           331:        {
        !           332:          q=dvmdii(addii(u,u2),shifti(u2,1),&r);
        !           333:          if (signe(r)<0) q=addsi(-1,q);
        !           334:          h[k]=lsub((GEN)h[k],gmul(q,(GEN)h[l]));
        !           335:          newcon=mppgcd((GEN)veccon[k],(GEN)veccon[l]);
        !           336:          corr=divii((GEN)veccon[k],newcon); veccon[k]=(long)newcon;
        !           337:          if(!gcmp1(corr))
        !           338:          {
        !           339:            corr2=sqri(corr);
        !           340:            for (j=1; j<=n; j++)
        !           341:              coeff(x,j,k)=coeff(x,k,j)=lmulii(corr,gcoeff(x,k,j));
        !           342:            coeff(x,k,k)=lmulii(corr,gcoeff(x,k,k));
        !           343:            for (j=k; j<=kmax; j++) B[j+1]=lmulii(corr2,(GEN)B[j+1]);
        !           344:            for (i=1; i<k; i++) coeff(lam,k,i)=lmulii(corr,gcoeff(lam,k,i));
        !           345:            for (i=k+1; i<=kmax; i++)
        !           346:            {
        !           347:              coeff(lam,i,k)=lmulii(corr,gcoeff(lam,i,k));
        !           348:              for (j=k+1; j<i; j++)
        !           349:                coeff(lam,i,j)=lmulii(corr2,gcoeff(lam,i,j));
        !           350:            }
        !           351:          }
        !           352:          r=negi(mulii(q,divii((GEN)veccon[l],(GEN)veccon[k])));
        !           353:          p1=gcoeff(x,k,l);
        !           354:          for (j=1; j<=n; j++)
        !           355:            coeff(x,j,k)=coeff(x,k,j)=laddii(gcoeff(x,j,k),mulii(r,(j==k)?p1:gcoeff(x,j,l)));
        !           356:          coeff(x,k,k)=laddii(gcoeff(x,k,k),mulii(r,gcoeff(x,l,k)));
        !           357:          coeff(lam,k,l)=laddii(gcoeff(lam,k,l),mulii(r,(GEN)B[l+1]));
        !           358:          for (i=1; i<l; i++)
        !           359:            coeff(lam,k,i)=laddii(gcoeff(lam,k,i),mulii(r,gcoeff(lam,l,i)));
        !           360:        }
        !           361:         if (low_stack(lim, stack_lim(av,1)))
        !           362:        {
        !           363:          if(DEBUGMEM>1) err(warnmem,"[6]: lllgramintwithcontent");
        !           364:          gptr[0]=&B; gptr[1]=&lam; gptr[2]=&h;
        !           365:          gptr[3]=&x; gptr[4]=&veccon; gerepilemany(av,gptr,5);
        !           366:        }
        !           367:       }
        !           368:       k++; if (DEBUGLEVEL>5) { fprintferr(" %ld",k); flusherr(); }
        !           369:       if (k>n)
        !           370:       {
        !           371:         if (DEBUGLEVEL>5) { fprintferr("\n"); flusherr(); }
        !           372:        tetpil=avma;
        !           373:        return gerepile(av0,tetpil,lllgramall_finish(h,fl,flag,n));
        !           374:       }
        !           375:     }
        !           376:     if (low_stack(lim, stack_lim(av,1)))
        !           377:     {
        !           378:       if(DEBUGMEM>1) err(warnmem,"[7]: lllgramintwithcontent");
        !           379:       gptr[0]=&B; gptr[1]=&lam; gptr[2]=&h;
        !           380:       gptr[3]=&x; gptr[4]=&veccon; gerepilemany(av,gptr,5);
        !           381:     }
        !           382:   }
        !           383: }
        !           384:
        !           385: static GEN
        !           386: lllintwithcontent(GEN x)
        !           387: {
        !           388:   long lx=lg(x),i,j,av,tetpil;
        !           389:   GEN veccon,con,xred,g;
        !           390:
        !           391:   if (typ(x) != t_MAT) err(typeer,"lllintwithcontent");
        !           392:   if (lx==1) return cgetg(1,t_MAT);
        !           393:   av=avma; veccon=cgetg(lx,t_VEC); g=cgetg(lx,t_MAT); xred=cgetg(lx,t_MAT);
        !           394:   for (j=1; j<lx; j++)
        !           395:   {
        !           396:     g[j]=lgetg(lx,t_COL); con=content((GEN)x[j]);
        !           397:     xred[j]=ldiv((GEN)x[j],con); veccon[j]=(long)con;
        !           398:   }
        !           399:   for (i=1; i<lx; i++)
        !           400:     for (j=1; j<=i; j++)
        !           401:       coeff(g,i,j)=coeff(g,j,i)=(long)gscal((GEN)xred[i],(GEN)xred[j]);
        !           402:   tetpil=avma;
        !           403:   return gerepile(av,tetpil,lllgramintwithcontent(g,veccon,2));
        !           404: }
        !           405:
        !           406: /********************************************************************/
        !           407: /**                                                                **/
        !           408: /**                          LLL ALGORITHM                         **/
        !           409: /**                                                                **/
        !           410: /********************************************************************/
        !           411: #define swap(x,y) { long _t=x; x=y; y=_t; }
        !           412: #define gswap(x,y) { GEN _t=x; x=y; y=_t; }
        !           413:
        !           414: static void
        !           415: REDI(GEN x, GEN h, GEN L, GEN B, long K, long k, long l)
        !           416: {
        !           417:   long i,lx;
        !           418:   GEN q = truedvmdii(addii(B,shifti(gcoeff(L,k,l),1)), shifti(B,1), NULL);
        !           419:   GEN *hk,*hl,xk,xl;
        !           420:   if (!signe(q)) return;
        !           421:   q = negi(q); lx = lg(x);
        !           422:   xl = (GEN)x[l]; hl = (GEN*)h[l];
        !           423:   xk = (GEN)x[k]; hk = (GEN*)h[k];
        !           424:   if (is_pm1(q))
        !           425:   {
        !           426:     if (signe(q) > 0)
        !           427:     {
        !           428:       for (i=1;i<=K;i++) hk[i]=addii(hk[i],hl[i]);
        !           429:       xk[k] = laddii((GEN)xk[k], (GEN)xl[k]);
        !           430:       for (i=1;i<lx;i++) coeff(x,k,i)=xk[i]=laddii((GEN)xk[i], (GEN)xl[i]);
        !           431:       for (i=1;i<l; i++) coeff(L,k,i)=laddii(gcoeff(L,k,i),gcoeff(L,l,i));
        !           432:       q = B;
        !           433:     } else {
        !           434:       for (i=1;i<=K;i++) hk[i]=subii(hk[i],hl[i]);
        !           435:       xk[k] = lsubii((GEN)xk[k], (GEN)xl[k]);
        !           436:       for (i=1;i<lx;i++) coeff(x,k,i)=xk[i]=lsubii((GEN)xk[i], (GEN)xl[i]);
        !           437:       for (i=1;i<l; i++) coeff(L,k,i)=lsubii(gcoeff(L,k,i),gcoeff(L,l,i));
        !           438:       q = negi(B);
        !           439:     }
        !           440:   } else {
        !           441:     for(i=1;i<=K;i++) hk[i]=addii(hk[i],mulii(q,hl[i]));
        !           442:     xk[k] = laddii((GEN)xk[k], mulii(q,(GEN)xl[k]));
        !           443:     for(i=1;i<lx;i++) coeff(x,k,i)=xk[i]=laddii((GEN)xk[i],mulii(q,(GEN)xl[i]));
        !           444:     for(i=1;i<l;i++)  coeff(L,k,i)=laddii(gcoeff(L,k,i),mulii(q,gcoeff(L,l,i)));
        !           445:     q = mulii(q,B);
        !           446:   }
        !           447:   coeff(L,k,l) = laddii(gcoeff(L,k,l), q);
        !           448: }
        !           449:
        !           450: /* b[k] <-- b[k] - round(L[k,l]) b[l], only b[1] ... b[K] modified so far
        !           451:  * assume l < k and update x = Gram(b), L = Gram Schmidt coeffs. */
        !           452: static void
        !           453: RED(GEN x, GEN h, GEN L, long K, long k, long l)
        !           454: {
        !           455:   long e,i,lx;
        !           456:   GEN q = grndtoi(gcoeff(L,k,l),&e);
        !           457:   GEN *hk,*hl,xk,xl;
        !           458:   if (DEBUGLEVEL>8)
        !           459:     fprintferr("error bits when rounding in lllgram: %ld\n",e);
        !           460:   if (!signe(q)) return;
        !           461:   q = negi(q); lx = lg(x);
        !           462:   xl = (GEN)x[l]; hl = (GEN*)h[l];
        !           463:   xk = (GEN)x[k]; hk = (GEN*)h[k];
        !           464:   if (is_pm1(q))
        !           465:   {
        !           466:     if (signe(q) > 0)
        !           467:     {
        !           468:       for (i=1;i<=K;i++) hk[i]=addii(hk[i],hl[i]);
        !           469:       xk[k] = ladd((GEN)xk[k], (GEN)xl[k]);
        !           470:       for (i=1;i<lx;i++) coeff(x,k,i)=xk[i]=ladd((GEN)xk[i], (GEN)xl[i]);
        !           471:       for (i=1;i<l; i++) coeff(L,k,i)=ladd(gcoeff(L,k,i),gcoeff(L,l,i));
        !           472:     } else {
        !           473:       for (i=1;i<=K;i++) hk[i]=subii(hk[i],hl[i]);
        !           474:       xk[k] = lsub((GEN)xk[k], (GEN)xl[k]);
        !           475:       for (i=1;i<lx;i++) coeff(x,k,i)=xk[i]=lsub((GEN)xk[i], (GEN)xl[i]);
        !           476:       for (i=1;i<l; i++) coeff(L,k,i)=lsub(gcoeff(L,k,i),gcoeff(L,l,i));
        !           477:     }
        !           478:   } else {
        !           479:     for (i=1;i<=K;i++) hk[i]=addii(hk[i],mulii(q,hl[i]));
        !           480:     xk[k] = ladd((GEN)xk[k], gmul(q,(GEN)xl[k]));
        !           481:     for (i=1;i<lx;i++) coeff(x,k,i)=xk[i]=ladd((GEN)xk[i], gmul(q,(GEN)xl[i]));
        !           482:     for (i=1;i<l; i++) coeff(L,k,i)=ladd(gcoeff(L,k,i),gmul(q,gcoeff(L,l,i)));
        !           483:   }
        !           484:   coeff(L,k,l) = ladd(gcoeff(L,k,l),q);
        !           485: }
        !           486:
        !           487: static int
        !           488: do_SWAPI(GEN x, GEN h, GEN L, GEN B, long kmax, long k, long alpha, GEN fl)
        !           489: {
        !           490:   GEN la,la2,p1,p2,Bk;
        !           491:   long av,i,j,lx;
        !           492:
        !           493:   if (!fl[k-1]) return 0;
        !           494:   lx = lg(x); av = avma;
        !           495:   la = gcoeff(L,k,k-1); la2 = sqri(la);
        !           496:   p2 = addii(la2, mulii((GEN)B[k-1],(GEN)B[k+1]));
        !           497:   Bk = (GEN)B[k];
        !           498:   if (fl[k] && cmpii(mulsi(alpha-1,sqri(Bk)), mulsi(alpha,p2)) <= 0)
        !           499:     { avma = av; return 0; }
        !           500:
        !           501:   /* SWAPI(k-1,k) */
        !           502:   if (DEBUGLEVEL>3 && k==kmax) {
        !           503:     fprintferr(" (%ld)", expi(mulsi(alpha-1,sqri(Bk)))
        !           504:                        - expi(mulsi(alpha,p2))); flusherr();
        !           505:   }
        !           506:   swap(h[k-1], h[k]);
        !           507:   swap(x[k-1], x[k]);
        !           508:   for (j=1; j< lx; j++) swap(coeff(x,k-1,j), coeff(x,k,j));
        !           509:   for (j=1; j<k-1; j++) swap(coeff(L,k-1,j), coeff(L,k,j))
        !           510:   if (fl[k])
        !           511:   {
        !           512:     av = avma;
        !           513:     for (i=k+1; i<=kmax; i++)
        !           514:     {
        !           515:       GEN t = gcoeff(L,i,k);
        !           516:       p1 = subii(mulii((GEN)B[k+1],gcoeff(L,i,k-1)), mulii(la,t));
        !           517:       p1 = divii(p1, Bk);
        !           518:       av = avma = coeff(L,i,k) = (long)icopy_av(p1,(GEN)av);
        !           519:
        !           520:       p1 = addii(mulii(la,gcoeff(L,i,k-1)), mulii((GEN)B[k-1],t));
        !           521:       p1 = divii(p1, Bk);
        !           522:       av = avma = coeff(L,i,k-1) = (long)icopy_av(p1,(GEN)av);
        !           523:     }
        !           524:     B[k] = ldivii(p2,Bk);
        !           525:   }
        !           526:   else
        !           527:   {
        !           528:     if (signe(la))
        !           529:     {
        !           530:       p1 = divii(la2, Bk);
        !           531:       B[k+1] = B[k] = (long)p1;
        !           532:       for (i=k+2; i<=lx; i++) B[i] = ldivii(mulii(p1,(GEN)B[i]), Bk);
        !           533:       for (i=k+1; i<=kmax; i++)
        !           534:         coeff(L,i,k-1) = ldivii(mulii(la,gcoeff(L,i,k-1)), Bk);
        !           535:       for (j=k+1; j<kmax; j++)
        !           536:         for (i=j+1; i<=kmax; i++)
        !           537:           coeff(L,i,j) = ldivii(mulii(p1,gcoeff(L,i,j)), Bk);
        !           538:     }
        !           539:     else
        !           540:     {
        !           541:       for (i=k+1; i<=kmax; i++)
        !           542:       {
        !           543:         coeff(L,i,k) = coeff(L,i,k-1);
        !           544:         coeff(L,i,k-1) = zero;
        !           545:       }
        !           546:       B[k] = B[k-1]; fl[k] = 1; fl[k-1] = 0;
        !           547:     }
        !           548:   }
        !           549:   return 1;
        !           550: }
        !           551:
        !           552: static int
        !           553: do_SWAP(GEN x, GEN h, GEN L, GEN B, long kmax, long k, GEN QR)
        !           554: {
        !           555:   GEN la,la2, BK,BB,q;
        !           556:   long av,i,j,lx;
        !           557:
        !           558:   lx = lg(x); av = avma;
        !           559:   la = gcoeff(L,k,k-1); la2 = gsqr(la);
        !           560:   q = gmul((GEN)B[k-1], gsub(QR,la2));
        !           561:   if (gcmp(q, (GEN)B[k]) <= 0) { avma = av; return 0; }
        !           562:
        !           563:   /* SWAP(k-1,k) */
        !           564:   if (DEBUGLEVEL>3 && k==kmax) {
        !           565:     fprintferr(" (%ld)", gexpo(q) - gexpo((GEN)B[k])); flusherr();
        !           566:   }
        !           567:   BB = gadd((GEN)B[k], gmul((GEN)B[k-1],la2));
        !           568:   if (gcmp0(BB)) { B[k] = 0; return 1; } /* precision pb */
        !           569:
        !           570:   coeff(L,k,k-1) = ldiv(gmul(la,(GEN)B[k-1]), BB);
        !           571:   BK = gdiv((GEN)B[k], BB);
        !           572:   B[k] = lmul((GEN)B[k-1], BK);
        !           573:   B[k-1] = (long)BB;
        !           574:
        !           575:   swap(h[k-1],h[k]);
        !           576:   swap(x[k-1],x[k]);
        !           577:   for (j=1; j<lx ; j++) swap(coeff(x,k-1,j), coeff(x,k,j));
        !           578:   for (j=1; j<k-1; j++) swap(coeff(L,k-1,j), coeff(L,k,j))
        !           579:   for (i=k+1; i<=kmax; i++)
        !           580:   {
        !           581:     GEN t = gcoeff(L,i,k);
        !           582:     coeff(L,i,k) = lsub(gcoeff(L,i,k-1), gmul(la,t));
        !           583:     coeff(L,i,k-1) = ladd(gmul(gcoeff(L,k,k-1),gcoeff(L,i,k-1)), gmul(BK,t));
        !           584:    /*              = ladd(t, gmul(gcoeff(L,k,k-1), gcoeff(L,i,k)));
        !           585:     * would save one multiplication, but loses precision faster... */
        !           586:   }
        !           587:   return 1;
        !           588: }
        !           589:
        !           590: /* x integer matrix */
        !           591: GEN
        !           592: lllgramall(GEN x, long alpha, long flag)
        !           593: {
        !           594:   long av0=avma,av,tetpil,lim,lx=lg(x),i,j,k,l,n,s,kmax;
        !           595:   GEN u,B,L,h,fl, *gptr[4];
        !           596:
        !           597:   if (typ(x) != t_MAT) err(typeer,"lllgramall");
        !           598:   n=lx-1; if (n<=1) return lllall_trivial(x,n,flag);
        !           599:   if (lg((GEN)x[1])!=lx) err(mattype1,"lllgramall");
        !           600:   fl = cgetg(lx,t_VECSMALL);
        !           601:
        !           602:   av=avma; lim=stack_lim(av,1); x=dummycopy(x);
        !           603:   B=gscalcol(gun, lx);
        !           604:   L=cgetg(lx,t_MAT);
        !           605:   for (j=1; j<lx; j++)
        !           606:   {
        !           607:     for (i=1; i<lx; i++)
        !           608:       if (typ(gcoeff(x,i,j))!=t_INT) err(lllger4);
        !           609:     fl[j] = 0; L[j] = (long)zerocol(n);
        !           610:   }
        !           611:   k=2; h=idmat(n); kmax=1;
        !           612:   u=gcoeff(x,1,1); s= signe(u);
        !           613:   if (s == 0) B[2]=un;
        !           614:   else
        !           615:   {
        !           616:     if (s < 0) err(lllger3);
        !           617:     B[2]=(long)u; coeff(L,1,1)=un; fl[1]=1;
        !           618:   }
        !           619:   if (DEBUGLEVEL>5) fprintferr("k =");
        !           620:   for(;;)
        !           621:   {
        !           622:     if (k > kmax)
        !           623:     {
        !           624:       if (DEBUGLEVEL>3) {fprintferr(" K%ld",k);flusherr();}
        !           625:       kmax = k;
        !           626:       for (j=1; j<=k; j++)
        !           627:        if (j==k || fl[j])
        !           628:        {
        !           629:           long av1 = avma;
        !           630:          u = gcoeff(x,k,j);
        !           631:          for (i=1; i<j; i++) if (fl[i])
        !           632:             u = divii(subii(mulii((GEN)B[i+1],u),
        !           633:                             mulii(gcoeff(L,k,i),gcoeff(L,j,i))),
        !           634:                       (GEN)B[i]);
        !           635:           u = gerepileuptoint(av1, u);
        !           636:          if (j<k) coeff(L,k,j)=(long)u;
        !           637:          else
        !           638:          {
        !           639:             s = signe(u);
        !           640:             if (s < 0) err(lllger3);
        !           641:            if (s)
        !           642:               { B[k+1]=(long)u; coeff(L,k,k)=un; fl[k]=1; }
        !           643:            else
        !           644:               { B[k+1]=B[k]; fl[k]=0; }
        !           645:          }
        !           646:        }
        !           647:     } else if (DEBUGLEVEL>5) {fprintferr(" %ld",k); flusherr();}
        !           648:     REDI(x,h,L,(GEN)B[k],kmax,k,k-1);
        !           649:     if (do_SWAPI(x,h,L,B,kmax,k,alpha,fl))
        !           650:     {
        !           651:       if (k>2) k--;
        !           652:     }
        !           653:     else
        !           654:     {
        !           655:       for (l=k-2; l; l--)
        !           656:       {
        !           657:         REDI(x,h,L,(GEN)B[l+1],kmax,k,l);
        !           658:         if (low_stack(lim, stack_lim(av,1)))
        !           659:         {
        !           660:           if(DEBUGMEM>1) err(warnmem,"lllgramall[1]");
        !           661:           gptr[0]=&B; gptr[1]=&L; gptr[2]=&h; gptr[3]=&x;
        !           662:           gerepilemany(av,gptr,4);
        !           663:         }
        !           664:       }
        !           665:       if (++k > n) break;
        !           666:     }
        !           667:     if (low_stack(lim, stack_lim(av,1)))
        !           668:     {
        !           669:       if(DEBUGMEM>1) err(warnmem,"lllgramall[2]");
        !           670:       gptr[0]=&B; gptr[1]=&L; gptr[2]=&h; gptr[3]=&x;
        !           671:       gerepilemany(av,gptr,4);
        !           672:     }
        !           673:   }
        !           674:   if (DEBUGLEVEL>3) fprintferr("\n");
        !           675:   tetpil=avma; return gerepile(av0,tetpil,lllgramall_finish(h,fl,flag,n));
        !           676: }
        !           677:
        !           678: static GEN
        !           679: lllgramall0(GEN x, long flag) { return lllgramall(x,100,flag); }
        !           680:
        !           681: static int
        !           682: pslg(GEN x)
        !           683: {
        !           684:   long tx;
        !           685:   if (gcmp0(x)) return 2;
        !           686:   tx=typ(x); return is_scalar_t(tx)? 3: lgef(x);
        !           687: }
        !           688:
        !           689: static GEN
        !           690: lllgramallgen(GEN x, long flag)
        !           691: {
        !           692:   long av0=avma,av,tetpil,lx=lg(x),tu,i,j,k,l,n,lim;
        !           693:   GEN u,B,lam,q,cq,h,la,bb,p1,p2,p3,p4,fl;
        !           694:   int ps1,ps2,flc;
        !           695:
        !           696:   if (typ(x) != t_MAT) err(typeer,"lllgramallgen");
        !           697:   n=lx-1; if (n<=1) return lllall_trivial(x,n,flag);
        !           698:   if (lg((GEN)x[1])!=lx) err(mattype1,"lllgramallgen");
        !           699:
        !           700:   fl = new_chunk(lx);
        !           701:
        !           702:   av=avma; lim=stack_lim(av,1);
        !           703:   B=cgetg(lx+1,t_COL);
        !           704:   B[1]=un; lam=cgetg(lx,t_MAT);
        !           705:   for (j=1; j<lx; j++) lam[j]=lgetg(lx,t_COL);
        !           706:   for (i=1; i<lx; i++)
        !           707:     for (j=1; j<=i; j++)
        !           708:     {
        !           709:       if (j<i && !fl[j]) coeff(lam,i,j)=coeff(lam,j,i)=zero;
        !           710:       else
        !           711:       {
        !           712:        u=gcoeff(x,i,j); tu=typ(u);
        !           713:        if (! is_scalar_t(tu) && tu != t_POL) err(lllger4);
        !           714:        for (k=1; k<j; k++)
        !           715:          if (fl[k])
        !           716:            u=gdiv(gsub( gmul((GEN)B[k+1],u),
        !           717:                          gmul(gcoeff(lam,i,k),gcoeff(lam,j,k)) ),
        !           718:                   (GEN)B[k]);
        !           719:        if (j<i) { coeff(lam,i,j)=(long)u; coeff(lam,j,i)=zero; }
        !           720:        else
        !           721:        {
        !           722:          if (!gcmp0(u)) { B[i+1]=(long)u; coeff(lam,i,i)=un; fl[i]=1; }
        !           723:          else { B[i+1]=B[i]; coeff(lam,i,i)=zero; fl[i]=0; }
        !           724:        }
        !           725:       }
        !           726:     }
        !           727:   k=2; h=idmat(n); flc=0;
        !           728:   for(;;)
        !           729:   {
        !           730:     u=gcoeff(lam,k,k-1);
        !           731:     if (pslg(u) >= pslg((GEN)B[k]))
        !           732:     {
        !           733:       q=gdeuc(u,(GEN)B[k]); cq=gdivsg(1,content(q)); q=gmul(q,cq); flc=1;
        !           734:       h[k]=lsub(gmul(cq,(GEN)h[k]),gmul(q,(GEN)h[k-1]));
        !           735:       coeff(lam,k,k-1)=lsub(gmul(cq,gcoeff(lam,k,k-1)),gmul(q,(GEN)B[k]));
        !           736:       for (i=1; i<k-1; i++)
        !           737:        coeff(lam,k,i)=lsub(gmul(cq,gcoeff(lam,k,i)),gmul(q,gcoeff(lam,k-1,i)));
        !           738:     }
        !           739:     ps1 = pslg(gsqr((GEN)B[k]));
        !           740:     p3 = gmul((GEN)B[k-1],(GEN)B[k+1]);
        !           741:     la=gcoeff(lam,k,k-1); p4 = gmul(la,gcoeff(lam,k,k-1));
        !           742:     ps2=pslg(gadd(p3,p4));
        !           743:     if (fl[k-1] && (ps1>ps2 || (ps1==ps2 && flc) || !fl[k]))
        !           744:     {
        !           745:       flc = (ps1!=ps2);
        !           746:       swap(h[k-1],h[k]);
        !           747:       for (j=1; j<=k-2; j++) swap(coeff(lam,k-1,j), coeff(lam,k,j));
        !           748:       if (fl[k])
        !           749:       {
        !           750:        for (i=k+1; i<=n; i++)
        !           751:        {
        !           752:          bb=gcoeff(lam,i,k);
        !           753:          coeff(lam,i,k)=ldiv(gsub(gmul((GEN)B[k+1],gcoeff(lam,i,k-1)),gmul(la,bb)),(GEN)B[k]);
        !           754:          coeff(lam,i,k-1)=ldiv(gadd(gmul(la,gcoeff(lam,i,k-1)),gmul((GEN)B[k-1],bb)),(GEN)B[k]);
        !           755:         }
        !           756:        B[k]=ldiv(gadd(p3,p4),(GEN)B[k]);
        !           757:       }
        !           758:       else
        !           759:       {
        !           760:        if (!gcmp0(la))
        !           761:        {
        !           762:          p2=(GEN)B[k]; p1=gdiv(p4,p2);
        !           763:          for (i=k+1; i<lx; i++)
        !           764:            coeff(lam,i,k-1)=ldiv(gmul(la,gcoeff(lam,i,k-1)),p2);
        !           765:          for (j=k+1; j<lx-1; j++)
        !           766:            for (i=j+1; i<lx; i++)
        !           767:              coeff(lam,i,j)=ldiv(gmul(p1,gcoeff(lam,i,j)),p2);
        !           768:          B[k+1]=B[k]=(long)p1;
        !           769:          for (i=k+2; i<=lx; i++)
        !           770:            B[i]=ldiv(gmul(p1,(GEN)B[i]),p2);
        !           771:         }
        !           772:        else
        !           773:        {
        !           774:          coeff(lam,k,k-1)=zero;
        !           775:          for (i=k+1; i<lx; i++)
        !           776:          { coeff(lam,i,k)=coeff(lam,i,k-1); coeff(lam,i,k-1)=zero; }
        !           777:          B[k]=B[k-1]; fl[k]=1; fl[k-1]=0;
        !           778:         }
        !           779:       }
        !           780:       if (k>2) k--;
        !           781:     }
        !           782:     else
        !           783:     {
        !           784:       for (l=k-2; l>=1; l--)
        !           785:       {
        !           786:        u=gcoeff(lam,k,l);
        !           787:        if (pslg(u)>=pslg((GEN)B[l+1]))
        !           788:        {
        !           789:          q=gdeuc(u,(GEN)B[l+1]); cq=gdivsg(1,content(q));
        !           790:           q=gmul(q,cq); flc=1;
        !           791:          h[k]=lsub(gmul(cq,(GEN)h[k]),gmul(q,(GEN)h[l]));
        !           792:          coeff(lam,k,l)=lsub(gmul(cq,gcoeff(lam,k,l)),gmul(q,(GEN)B[l+1]));
        !           793:          for (i=1; i<l; i++)
        !           794:             coeff(lam,k,i)=lsub(gmul(cq,gcoeff(lam,k,i)),gmul(q,gcoeff(lam,l,i)));
        !           795:        }
        !           796:       }
        !           797:       if (++k > n) break;
        !           798:     }
        !           799:     if (low_stack(lim, stack_lim(av,1)))
        !           800:     {
        !           801:       GEN *gptr[4];
        !           802:       if(DEBUGMEM>1) err(warnmem,"lllgramallgen");
        !           803:       gptr[0]=&B; gptr[1]=&lam; gptr[2]=&h;
        !           804:       gerepilemany(av,gptr,3);
        !           805:     }
        !           806:   }
        !           807:   tetpil=avma;
        !           808:   return gerepile(av0,tetpil,lllgramall_finish(h,fl,flag,n));
        !           809: }
        !           810:
        !           811: /* compute B[k], update mu(k,1..k-1) */
        !           812: static int
        !           813: get_Gram_Schmidt(GEN x, GEN mu, GEN B, long k)
        !           814: {
        !           815:   GEN s,A = cgetg(k+1, t_COL); /* scratch space */
        !           816:   long av,i,j;
        !           817:   A[1] = coeff(x,k,1);
        !           818:   for(j=1;j<k;)
        !           819:   {
        !           820:     coeff(mu,k,j) = ldiv((GEN)A[j],(GEN)B[j]);
        !           821:     j++; av = avma;
        !           822:     /* A[j] <-- x[k,j] - sum_{i<j} mu[j,i] A[i] */
        !           823:     s = gmul(gcoeff(mu,j,1),(GEN)A[1]);
        !           824:     for (i=2; i<j; i++) s = gadd(s, gmul(gcoeff(mu,j,i),(GEN)A[i]));
        !           825:     s = gneg(s); A[j] = lpileupto(av, gadd(gcoeff(x,k,j),s));
        !           826:   }
        !           827:   B[k] = A[k]; return (gsigne((GEN)B[k]) > 0);
        !           828: }
        !           829:
        !           830: /* x = Gram(b_i). If precision problems return NULL if flag=1, error otherwise.
        !           831:  * Quality ratio = Q = (alpha-1)/alpha. Suggested value: alpha = 100
        !           832:  */
        !           833: GEN
        !           834: lllgramintern(GEN x, long alpha, long flag, long prec)
        !           835: {
        !           836:   GEN xinit,L,h,B,L1,QR;
        !           837:   long retry = 2, av = avma,lim,l,i,j,k,k1,lx=lg(x),n,kmax,KMAX;
        !           838:   long last_prec;
        !           839:
        !           840:   if (typ(x) != t_MAT) err(typeer,"lllgram");
        !           841:   n=lx-1; if (n && lg((GEN)x[1])!=lx) err(mattype1,"lllgram");
        !           842:   if (n<=1) return idmat(n);
        !           843:   xinit = x; lim = stack_lim(av,1);
        !           844:   for (k=2,j=1; j<lx; j++)
        !           845:   {
        !           846:     GEN p1=(GEN)x[j];
        !           847:     for (i=1; i<=j; i++)
        !           848:       if (typ(p1[i]) == t_REAL) { l = lg((GEN)p1[i]); if (l>k) k=l; }
        !           849:   }
        !           850:   if (k == 2)
        !           851:   {
        !           852:     if (!prec) return lllgramint(x);
        !           853:     x = gmul(x, realun(prec+1));
        !           854:   }
        !           855:   else
        !           856:   {
        !           857:     if (prec < k) prec = k;
        !           858:     x = gprec_w(x, prec+1);
        !           859:   }
        !           860:  /* kmax = maximum column index attained during this run
        !           861:   * KMAX = same over all runs (after PRECPB) */
        !           862:   kmax = KMAX = 1;
        !           863:
        !           864: PRECPB:
        !           865:   switch(retry--)
        !           866:   {
        !           867:     case 2: h = idmat(n); break; /* entry */
        !           868:     case 1:
        !           869:       if (kmax > 2)
        !           870:       { /* some progress but precision loss, try again */
        !           871:         prec = (prec<<1)-2; kmax = 1;
        !           872:         if (DEBUGLEVEL > 3) fprintferr("\n");
        !           873:         if (DEBUGLEVEL) err(warnprec,"lllgramintern",prec);
        !           874:         x = qf_base_change(gprec_w(xinit,prec),h,1);
        !           875:         {
        !           876:           GEN *gsav[2]; gsav[0]=&h; gsav[1]=&x;
        !           877:           gerepilemany(av, gsav, 2);
        !           878:         }
        !           879:         if (DEBUGLEVEL) err(warner,"lllgramintern starting over");
        !           880:         break;
        !           881:       } /* fall through */
        !           882:     case 0: /* give up */
        !           883:       if (DEBUGLEVEL > 3) fprintferr("\n");
        !           884:       if (DEBUGLEVEL) err(warner,"lllgramintern giving up");
        !           885:       if (flag) { avma=av; return NULL; }
        !           886:       if (DEBUGLEVEL) outerr(xinit);
        !           887:       err(lllger3);
        !           888:   }
        !           889:   last_prec = prec;
        !           890:   QR = cgetr(prec+1); affsr(alpha-1,QR);
        !           891:   QR = divrs(QR,alpha);
        !           892:
        !           893:   L=cgetg(lx,t_MAT);
        !           894:   B=cgetg(lx,t_COL);
        !           895:   for (j=1; j<lx; j++) { L[j] = (long)zerocol(n); B[j] = zero; }
        !           896:   k=2; B[1]=coeff(x,1,1);
        !           897:   if (gcmp0((GEN)B[1]))
        !           898:   {
        !           899:     if (flag) return NULL;
        !           900:     err(lllger3);
        !           901:   }
        !           902:   if (DEBUGLEVEL>5) fprintferr("k =");
        !           903:   for(;;)
        !           904:   {
        !           905:     if (k>kmax)
        !           906:     {
        !           907:       kmax = k; if (KMAX < kmax) KMAX = kmax;
        !           908:       if (DEBUGLEVEL>3) {fprintferr(" K%ld",k);flusherr();}
        !           909:       if (!get_Gram_Schmidt(x,L,B,k)) goto PRECPB;
        !           910:     }
        !           911:     else if (DEBUGLEVEL>5) fprintferr(" %ld",k);
        !           912:     L1 = gcoeff(L,k,k-1);
        !           913:     if (typ(L1) == t_REAL &&
        !           914:         (2*gexpo(L1) > bit_accuracy(lg(L1)) || 2*lg(L1) < last_prec))
        !           915:     {
        !           916:       last_prec = lg(L1);
        !           917:       if (DEBUGLEVEL>3)
        !           918:        fprintferr("\nRecomputing Gram-Schmidt, kmax = %ld, prec was %ld\n",
        !           919:                    kmax,last_prec);
        !           920:       for (k1=1; k1<=kmax; k1++)
        !           921:         if (!get_Gram_Schmidt(x,L,B,k1)) goto PRECPB;
        !           922:     }
        !           923:     RED(x,h,L,KMAX,k,k-1);
        !           924:     if (do_SWAP(x,h,L,B,kmax,k,QR))
        !           925:     {
        !           926:       if (!B[k]) goto PRECPB;
        !           927:       if (k>2) k--;
        !           928:     }
        !           929:     else
        !           930:     {
        !           931:       for (l=k-2; l; l--) RED(x,h,L,KMAX,k,l);
        !           932:       if (++k > n) break;
        !           933:     }
        !           934:     if (low_stack(lim, stack_lim(av,1)))
        !           935:     {
        !           936:       GEN *gptr[5]; gptr[0]=&B; gptr[1]=&L; gptr[2]=&h; gptr[3]=&x; gptr[4]=&QR;
        !           937:       if(DEBUGMEM>1)
        !           938:       {
        !           939:         if (DEBUGLEVEL > 3) fprintferr("\n");
        !           940:         err(warnmem,"lllgram");
        !           941:       }
        !           942:       gerepilemany(av,gptr,5);
        !           943:     }
        !           944:   }
        !           945:   if (DEBUGLEVEL>3) fprintferr("\n");
        !           946:   return gerepilecopy(av, h);
        !           947: }
        !           948:
        !           949: static GEN
        !           950: lllgram_noerr(GEN x,long prec) { return lllgramintern(x,100,1,prec); }
        !           951:
        !           952: GEN
        !           953: lllgram(GEN x,long prec) { return lllgramintern(x,100,0,prec); }
        !           954:
        !           955: GEN
        !           956: qflll0(GEN x, long flag, long prec)
        !           957: {
        !           958:   switch(flag)
        !           959:   {
        !           960:     case 0: return lll(x,prec);
        !           961:     case 1: return lllint(x);
        !           962:     case 2: return lllintpartial(x);
        !           963:     case 3: return lllrat(x);
        !           964:     case 4: return lllkerim(x);
        !           965:     case 5: return lllkerimgen(x);
        !           966:     case 7: return lll1(x,prec);
        !           967:     case 8: return lllgen(x);
        !           968:     case 9: return lllintwithcontent(x);
        !           969:     default: err(flagerr,"qflll");
        !           970:   }
        !           971:   return NULL; /* not reached */
        !           972: }
        !           973:
        !           974: GEN
        !           975: qflllgram0(GEN x, long flag, long prec)
        !           976: {
        !           977:   switch(flag)
        !           978:   {
        !           979:     case 0: return lllgram(x,prec);
        !           980:     case 1: return lllgramint(x);
        !           981:     case 4: return lllgramkerim(x);
        !           982:     case 5: return lllgramkerimgen(x);
        !           983:     case 7: return lllgram1(x,prec);
        !           984:     case 8: return lllgramgen(x);
        !           985:     default: err(flagerr,"qflllgram");
        !           986:   }
        !           987:   return NULL; /* not reached */
        !           988: }
        !           989:
        !           990: /* x est la matrice d'une base b_i; retourne la matrice u (entiere
        !           991:  * unimodulaire) d'une base LLL-reduite c_i en fonction des b_i (la base
        !           992:  * reduite est c=b*u).
        !           993:  */
        !           994: static GEN
        !           995: lll_proto(GEN x, GEN f(GEN, long), long prec)
        !           996: {
        !           997:   long lx=lg(x),i,j,av,av1;
        !           998:   GEN g;
        !           999:
        !          1000:   if (typ(x) != t_MAT) err(typeer,"lll_proto");
        !          1001:   if (lx==1) return cgetg(1,t_MAT);
        !          1002:   av=avma; g=cgetg(lx,t_MAT);
        !          1003:   for (j=1; j<lx; j++) g[j]=lgetg(lx,t_COL);
        !          1004:   for (i=1; i<lx; i++)
        !          1005:     for (j=1; j<=i; j++)
        !          1006:       coeff(g,i,j)=coeff(g,j,i)=(long)gscal((GEN)x[i],(GEN)x[j]);
        !          1007:   av1=avma; x = f(g,prec);
        !          1008:   if (!x) { avma=av; return NULL; }
        !          1009:   return gerepile(av,av1,x);
        !          1010: }
        !          1011:
        !          1012: GEN
        !          1013: lllintern(GEN x,long flag,long prec)
        !          1014: {
        !          1015:   return lll_proto(x,flag? lllgram_noerr: lllgram,prec);
        !          1016: }
        !          1017:
        !          1018: GEN
        !          1019: lll(GEN x,long prec) { return lll_proto(x,lllgram,prec); }
        !          1020:
        !          1021: GEN
        !          1022: lll1(GEN x,long prec) { return lll_proto(x,lllgram1,prec); }
        !          1023:
        !          1024: GEN
        !          1025: lllrat(GEN x) { return lll_proto(x,lllgram,lll_ALL); }
        !          1026:
        !          1027: GEN
        !          1028: lllint(GEN x) { return lll_proto(x,lllgramall0,lll_IM); }
        !          1029:
        !          1030: GEN
        !          1031: lllgen(GEN x) { return lll_proto(x,lllgramallgen,lll_IM); }
        !          1032:
        !          1033: GEN
        !          1034: lllgramgen(GEN x) { return lllgramallgen(x,lll_IM); }
        !          1035:
        !          1036: GEN
        !          1037: lllgramkerimgen(GEN x) { return lllgramallgen(x,lll_ALL); }
        !          1038:
        !          1039: static GEN
        !          1040: lllkerim_proto(GEN x, GEN f(GEN,long))
        !          1041: {
        !          1042:   long lx=lg(x), i,j,av,av1;
        !          1043:   GEN g;
        !          1044:
        !          1045:   if (typ(x) != t_MAT) err(typeer,"lllkerim_proto");
        !          1046:   if (lx==1)
        !          1047:   {
        !          1048:     g=cgetg(3,t_VEC);
        !          1049:     g[1]=lgetg(1,t_MAT);
        !          1050:     g[2]=lgetg(1,t_MAT); return g;
        !          1051:   }
        !          1052:   if (lg((GEN)x[1])==1)
        !          1053:   {
        !          1054:     g=cgetg(3,t_VEC);
        !          1055:     g[1]=(long)idmat(lx-1);
        !          1056:     g[2]=lgetg(1,t_MAT); return g;
        !          1057:   }
        !          1058:   av=avma; g=cgetg(lx,t_MAT);
        !          1059:   for (j=1; j<lx; j++) g[j]=lgetg(lx,t_COL);
        !          1060:   for (i=1; i<lx; i++)
        !          1061:     for (j=1; j<=i; j++)
        !          1062:       coeff(g,i,j)=coeff(g,j,i)=(long)gscal((GEN)x[i],(GEN)x[j]);
        !          1063:   av1=avma; return gerepile(av,av1,f(g,lll_ALL));
        !          1064: }
        !          1065:
        !          1066: GEN
        !          1067: lllkerim(GEN x) { return lllkerim_proto(x,lllgramall0); }
        !          1068:
        !          1069: GEN
        !          1070: lllkerimgen(GEN x) { return lllkerim_proto(x,lllgramallgen); }
        !          1071:
        !          1072: /* x est ici la matrice de GRAM des bi.  */
        !          1073: GEN
        !          1074: lllgram1(GEN x, long prec)
        !          1075: {
        !          1076:   GEN mu,u,B,BB,BK,p,q,r,cst,unreel,sv,mu1,mu2;
        !          1077:   long av,tetpil,lim,l,i,j,k,lx=lg(x),n,e;
        !          1078:
        !          1079:   if (typ(x) != t_MAT) err(typeer,"lllgram1");
        !          1080:   if (lg((GEN)x[1])!=lx) err(mattype1,"lllgram1"); n=lx-1;
        !          1081:   if (n<=1) return idmat(n);
        !          1082:   cst=gdivgs(stoi(99),100); /* LLL proposent 0.75 */
        !          1083:   if (prec)
        !          1084:   {
        !          1085:     unreel = realun(prec+1);
        !          1086:     x = gmul(x,unreel);
        !          1087:     cst = gmul(cst,unreel);
        !          1088:   }
        !          1089:   av=avma; lim=stack_lim(av,1);
        !          1090:   mu=gtrans(sqred(x)); B=cgetg(lx,t_COL);
        !          1091:   for (i=1,l=0; i<=n; i++)
        !          1092:   {
        !          1093:     if (gsigne((GEN)(B[i]=coeff(mu,i,i)))>0) l++;
        !          1094:     coeff(mu,i,i)=un;
        !          1095:   }
        !          1096:   if (l<n) err(lllger3);
        !          1097:
        !          1098:   u=idmat(n); k=2;
        !          1099:   do
        !          1100:   {
        !          1101:     if (!gcmp0(r=grndtoi(gcoeff(mu,k,k-1),&e)))
        !          1102:     {
        !          1103:       u[k]=lsub((GEN)u[k],gmul(r,(GEN)u[k-1]));
        !          1104:       for (j=1; j<k-1; j++)
        !          1105:        coeff(mu,k,j)=lsub(gcoeff(mu,k,j),gmul(r,gcoeff(mu,k-1,j)));
        !          1106:       mu1=(GEN)(coeff(mu,k,k-1)=lsub(gcoeff(mu,k,k-1),r));
        !          1107:     }
        !          1108:     else mu1=gcoeff(mu,k,k-1);
        !          1109:     q=gmul((GEN)B[k-1],gsub(cst,mu2=gsqr(mu1)));
        !          1110:     if (gcmp(q,(GEN)B[k])>0)
        !          1111:     {
        !          1112:       BB=gadd((GEN)B[k],gmul((GEN)B[k-1],mu2));
        !          1113:       coeff(mu,k,k-1)=ldiv(gmul(mu1,(GEN)B[k-1]),BB);
        !          1114:       B[k]=lmul((GEN)B[k-1],BK=gdiv((GEN)B[k],BB));
        !          1115:       B[k-1]=(long)BB;
        !          1116:       swap(u[k-1],u[k]);
        !          1117:       for (j=1; j<=k-2; j++) swap(coeff(mu,k-1,j), coeff(mu,k,j));
        !          1118:       for (i=k+1; i<=n; i++)
        !          1119:       {
        !          1120:        p=gcoeff(mu,i,k);
        !          1121:        coeff(mu,i,k)=lsub(gcoeff(mu,i,k-1),gmul(mu1,p));
        !          1122:        coeff(mu,i,k-1)=ladd(gmul(BK,p),gmul(gcoeff(mu,k,k-1),gcoeff(mu,i,k-1)));
        !          1123:       }
        !          1124:       if (k>2) k--;
        !          1125:     }
        !          1126:     else
        !          1127:     {
        !          1128:       for (l=k-2; l; l--)
        !          1129:       {
        !          1130:        if (!gcmp0(r=grndtoi(gcoeff(mu,k,l),&e)))
        !          1131:        {
        !          1132:          u[k]=lsub((GEN)u[k],gmul(r,(GEN)u[l]));
        !          1133:          for (j=1; j<l; j++)
        !          1134:            coeff(mu,k,j)=lsub(gcoeff(mu,k,j),gmul(r,gcoeff(mu,l,j)));
        !          1135:          coeff(mu,k,l)=lsub(gcoeff(mu,k,l),r);
        !          1136:         }
        !          1137:       }
        !          1138:       k++;
        !          1139:     }
        !          1140:     if (low_stack(lim, stack_lim(av,1)))
        !          1141:     {
        !          1142:       if(DEBUGMEM>1) err(warnmem,"lllgram1");
        !          1143:       tetpil=avma;
        !          1144:       sv=cgetg(4,t_VEC);
        !          1145:       sv[1]=lcopy(B); sv[2]=lcopy(u); sv[3]=lcopy(mu);
        !          1146:       sv=gerepile(av,tetpil,sv);
        !          1147:       B=(GEN)sv[1]; u=(GEN)sv[2]; mu=(GEN)sv[3];
        !          1148:     }
        !          1149:   }
        !          1150:   while (k<=n);
        !          1151:   return gerepilecopy(av,u);
        !          1152: }
        !          1153:
        !          1154: GEN
        !          1155: lllgramint(GEN x)
        !          1156: {
        !          1157:   return lllgramall0(x,lll_IM);
        !          1158: }
        !          1159:
        !          1160: GEN
        !          1161: lllgramkerim(GEN x)
        !          1162: {
        !          1163:   return lllgramall0(x,lll_ALL);
        !          1164: }
        !          1165:
        !          1166: /*  This routine is functionally similar to lllint when all = 0.
        !          1167:  *
        !          1168:  *    The input is an integer matrix mat (not necessarily square) whose
        !          1169:  *  columns are linearly independent.  It outputs another matrix T such that
        !          1170:  *  mat * T is partially reduced.  If all = 0, the size of mat * T is the
        !          1171:  *  same as the size of mat.  If all = 1 the number of columns of mat * T
        !          1172:  *  is at most equal to its number of rows.  A matrix M is said to be
        !          1173:  *  -partially reduced- if | m1 +- m2 | >= |m1| for any two distinct
        !          1174:  *  columns m1, m2, in M.
        !          1175:  *
        !          1176:  *    This routine is designed to quickly reduce lattices in which one row
        !          1177:  *  is huge compared to the other rows.  For example, when searching for a
        !          1178:  *  polynomial of degree 3 with root a mod p, the four input vectors might
        !          1179:  *  be the coefficients of
        !          1180:  *      X^3 - (a^3 mod p), X^2 - (a^2 mod p), X - (a mod p), p.
        !          1181:  *  All four constant coefficients are O(p) and the rest are O(1). By the
        !          1182:  *  pigeon-hole principle, the coefficients of the smallest vector in the
        !          1183:  *  lattice are O(p^(1/4)), Hence significant reduction of vector lengths
        !          1184:  *  can be anticipated.
        !          1185:  *
        !          1186:  *             Peter Montgomery (July, 1994)
        !          1187:  *
        !          1188:  *  If flag = 1 complete the reduction using lllint, otherwise return
        !          1189:  *  partially reduced basis.
        !          1190:  */
        !          1191: GEN
        !          1192: lllintpartialall(GEN m, long flag)
        !          1193: {
        !          1194:   const long ncol = lg(m)-1;
        !          1195:   const long ltop1 = avma;
        !          1196:   long ncolnz;
        !          1197:   GEN tm1, tm2, mid, *gptr[4];
        !          1198:
        !          1199:   if (typ(m) != t_MAT) err(typeer,"lllintpartialall");
        !          1200:   if (ncol <= 1) return idmat(ncol);
        !          1201:
        !          1202:   {
        !          1203:     GEN dot11 = sqscali((GEN)m[1]);
        !          1204:     GEN dot22 = sqscali((GEN)m[2]);
        !          1205:     GEN dot12 = gscali((GEN)m[1], (GEN)m[2]);
        !          1206:     GEN tm  = idmat(2); /* For first two columns only */
        !          1207:
        !          1208:     int progress = 0;
        !          1209:     long npass2 = 0;
        !          1210:
        !          1211: /* Try to row reduce the first two columns of m.
        !          1212:  * Our best result so far is (first two columns of m)*tm.
        !          1213:  *
        !          1214:  * Initially tm = 2 x 2 identity matrix.
        !          1215:  * The inner products of the reduced matrix are in
        !          1216:  * dot11, dot12, dot22.
        !          1217:  */
        !          1218:     while (npass2 < 2 || progress)
        !          1219:     {
        !          1220:       GEN dot12new,q = gdivround(dot12, dot22);
        !          1221:
        !          1222:       npass2++; progress = signe(q);
        !          1223:       if (progress)
        !          1224:       {
        !          1225:        /* Conceptually replace (v1, v2) by (v1 - q*v2, v2),
        !          1226:         * where v1 and v2 represent the reduced basis for the
        !          1227:         * first two columns of the matrix.
        !          1228:         *
        !          1229:         * We do this by updating tm and the inner products.
        !          1230:         *
        !          1231:         * An improved algorithm would look only at the leading
        !          1232:         * digits of dot11, dot12, dot22.  It would use
        !          1233:         * single-precision calculations as much as possible.
        !          1234:         */
        !          1235:         q = negi(q);
        !          1236:         dot12new = addii(dot12, mulii(q, dot22));
        !          1237:         dot11 = addii(dot11, mulii(q, addii(dot12, dot12new)));
        !          1238:         dot12 = dot12new;
        !          1239:         tm[1] = (long)ZV_lincomb(gun,q, (GEN)tm[1],(GEN)tm[2]);
        !          1240:       }
        !          1241:
        !          1242:       /* Interchange the output vectors v1 and v2.  */
        !          1243:       gswap(dot11,dot22); swap(tm[1],tm[2]);
        !          1244:
        !          1245:       /* Occasionally (including final pass) do garbage collection.  */
        !          1246:       if (npass2 % 8 == 0 || !progress)
        !          1247:       {
        !          1248:         gptr[0] = &dot11; gptr[1] = &dot12;
        !          1249:         gptr[2] = &dot22; gptr[3] = &tm;
        !          1250:         gerepilemany(ltop1, gptr, 4);
        !          1251:       }
        !          1252:     } /* while npass2 < 2 || progress */
        !          1253:
        !          1254:     {
        !          1255:       long icol;
        !          1256:       GEN det12 = subii(mulii(dot11, dot22), mulii(dot12, dot12));
        !          1257:
        !          1258:       tm1 = idmat(ncol);
        !          1259:       mid = cgetg(ncol+1, t_MAT);
        !          1260:       for (icol = 1; icol <= 2; icol++)
        !          1261:       {
        !          1262:         coeff(tm1,1,icol) = coeff(tm,1,icol);
        !          1263:        coeff(tm1,2,icol) = coeff(tm,2,icol);
        !          1264:         mid[icol] = (long)ZV_lincomb(
        !          1265:            gcoeff(tm,1,icol),gcoeff(tm,2,icol), (GEN)m[1],(GEN)m[2]);
        !          1266:       }
        !          1267:       for (icol = 3; icol <= ncol; icol++)
        !          1268:       {
        !          1269:         GEN curcol = (GEN)m[icol];
        !          1270:        GEN dot1i = gscali((GEN)mid[1], curcol);
        !          1271:         GEN dot2i = gscali((GEN)mid[2], curcol);
        !          1272:        /* Try to solve
        !          1273:         *
        !          1274:         * ( dot11  dot12 ) (q1)    ( dot1i )
        !          1275:         * ( dot12  dot22 ) (q2)  = ( dot2i )
        !          1276:         *
        !          1277:         * Round -q1 and -q2 to the nearest integer.
        !          1278:         * Then compute curcol - q1*mid[1] - q2*mid[2].
        !          1279:         * This will be approximately orthogonal to the
        !          1280:         * first two vectors in the new basis.
        !          1281:         */
        !          1282:        GEN q1neg = subii(mulii(dot12, dot2i), mulii(dot22, dot1i));
        !          1283:         GEN q2neg = subii(mulii(dot12, dot1i), mulii(dot11, dot2i));
        !          1284:
        !          1285:         q1neg = gdivround(q1neg, det12);
        !          1286:         q2neg = gdivround(q2neg, det12);
        !          1287:         coeff(tm1, 1, icol) = ladd(gmul(q1neg, gcoeff(tm,1,1)),
        !          1288:                                   gmul(q2neg, gcoeff(tm,1,2)));
        !          1289:         coeff(tm1, 2, icol) = ladd(gmul(q1neg, gcoeff(tm,2,1)),
        !          1290:                                   gmul(q2neg, gcoeff(tm,2,2)));
        !          1291:         mid[icol] = ladd(curcol,
        !          1292:           ZV_lincomb(q1neg,q2neg, (GEN)mid[1],(GEN)mid[2]));
        !          1293:       } /* for icol */
        !          1294:     } /* local block */
        !          1295:   }
        !          1296:   if (DEBUGLEVEL>6)
        !          1297:   {
        !          1298:     fprintferr("tm1 = %Z",tm1);
        !          1299:     fprintferr("mid = %Z",mid);
        !          1300:   }
        !          1301:   gptr[0] = &tm1; gptr[1] = &mid;
        !          1302:   gerepilemany(ltop1, gptr, 2);
        !          1303:   {
        !          1304:    /* For each pair of column vectors v and w in mid * tm2,
        !          1305:     * try to replace (v, w) by (v, v - q*w) for some q.
        !          1306:     * We compute all inner products and check them repeatedly.
        !          1307:     */
        !          1308:     const long ltop3 = avma; /* Excludes region with tm1 and mid */
        !          1309:     long icol, lim, reductions, npass = 0;
        !          1310:     GEN dotprd = cgetg(ncol+1, t_MAT);
        !          1311:
        !          1312:     tm2 = idmat(ncol);
        !          1313:     for (icol=1; icol <= ncol; icol++)
        !          1314:     {
        !          1315:       long jcol;
        !          1316:
        !          1317:       dotprd[icol] = lgetg(ncol+1,t_COL);
        !          1318:       for (jcol=1; jcol <= icol; jcol++)
        !          1319:        coeff(dotprd,jcol,icol) = coeff(dotprd,icol,jcol) =
        !          1320:           (long)gscali((GEN)mid[icol], (GEN)mid[jcol]);
        !          1321:     } /* for icol */
        !          1322:     lim = stack_lim(ltop3,1);
        !          1323:     for(;;)
        !          1324:     {
        !          1325:       reductions = 0;
        !          1326:       for (icol=1; icol <= ncol; icol++)
        !          1327:       {
        !          1328:        long ijdif, jcol, k1, k2;
        !          1329:        GEN codi, q;
        !          1330:
        !          1331:         for (ijdif=1; ijdif < ncol; ijdif++)
        !          1332:        {
        !          1333:           const long previous_avma = avma;
        !          1334:
        !          1335:           jcol = (icol + ijdif - 1) % ncol; jcol++; /* Hack for NeXTgcc 2.5.8 */
        !          1336:           k1 = (cmpii(gcoeff(dotprd,icol,icol),
        !          1337:                      gcoeff(dotprd,jcol,jcol) ) > 0)
        !          1338:                ? icol : jcol;  /* index of larger column */
        !          1339:          k2 = icol + jcol - k1;        /* index of smaller column */
        !          1340:          codi = gcoeff(dotprd,k2,k2);
        !          1341:          q = gcmp0(codi)? gzero: gdivround(gcoeff(dotprd,k1,k2), codi);
        !          1342:
        !          1343:          /* Try to subtract a multiple of column k2 from column k1.  */
        !          1344:          if (gcmp0(q)) avma = previous_avma;
        !          1345:           else
        !          1346:          {
        !          1347:            long dcol;
        !          1348:
        !          1349:            reductions++; q = negi(q);
        !          1350:            tm2[k1]=(long)
        !          1351:               ZV_lincomb(gun,q, (GEN)tm2[k1], (GEN)tm2[k2]);
        !          1352:            dotprd[k1]=(long)
        !          1353:               ZV_lincomb(gun,q, (GEN)dotprd[k1], (GEN)dotprd[k2]);
        !          1354:            coeff(dotprd, k1, k1) = laddii(gcoeff(dotprd,k1,k1),
        !          1355:                                           mulii(q, gcoeff(dotprd,k2,k1)));
        !          1356:            for (dcol = 1; dcol <= ncol; dcol++)
        !          1357:              coeff(dotprd,k1,dcol) = coeff(dotprd,dcol,k1);
        !          1358:          } /* if q != 0 */
        !          1359:         } /* for ijdif */
        !          1360:         if (low_stack(lim, stack_lim(ltop3,1)))
        !          1361:        {
        !          1362:           if(DEBUGMEM>1) err(warnmem,"lllintpartialall");
        !          1363:          gptr[0] = &dotprd; gptr[1] = &tm2;
        !          1364:          gerepilemany(ltop3, gptr, 2);
        !          1365:         }
        !          1366:       } /* for icol */
        !          1367:       if (!reductions) break;
        !          1368:       if (DEBUGLEVEL>6)
        !          1369:       {
        !          1370:        GEN diag_prod = dbltor(1.0);
        !          1371:        for (icol = 1; icol <= ncol; icol++)
        !          1372:          diag_prod = gmul(diag_prod, gcoeff(dotprd,icol,icol));
        !          1373:         npass++;
        !          1374:        fprintferr("npass = %ld, red. last time = %ld, diag_prod = %Z\n\n",
        !          1375:                    npass, reductions, diag_prod);
        !          1376:       }
        !          1377:     } /* for(;;)*/
        !          1378:
        !          1379:    /* Sort columns so smallest comes first in m * tm1 * tm2.
        !          1380:     * Use insertion sort.
        !          1381:     */
        !          1382:     for (icol = 1; icol < ncol; icol++)
        !          1383:     {
        !          1384:       long jcol, s = icol;
        !          1385:
        !          1386:       for (jcol = icol+1; jcol <= ncol; jcol++)
        !          1387:        if (cmpii(gcoeff(dotprd,s,s),gcoeff(dotprd,jcol,jcol)) > 0) s = jcol;
        !          1388:       if (icol != s)
        !          1389:       { /* Exchange with proper column */
        !          1390:         /* Only diagonal of dotprd is updated */
        !          1391:         swap(tm2[icol], tm2[s]);
        !          1392:         swap(coeff(dotprd,icol,icol), coeff(dotprd,s,s));
        !          1393:       }
        !          1394:     } /* for icol */
        !          1395:     icol=1;
        !          1396:     while (icol <= ncol && !signe(gcoeff(dotprd,icol,icol))) icol++;
        !          1397:     ncolnz = ncol - icol + 1;
        !          1398:   } /* local block */
        !          1399:
        !          1400:   if (flag)
        !          1401:   {
        !          1402:     if (ncolnz == lg((GEN)m[1])-1)
        !          1403:     {
        !          1404:       tm2 += (ncol-ncolnz);
        !          1405:       tm2[0]=evaltyp(t_MAT)|evallg(ncolnz+1);
        !          1406:     }
        !          1407:     else
        !          1408:     {
        !          1409:       tm1 = gmul(tm1, tm2);
        !          1410:       tm2 = lllint(gmul(m, tm1));
        !          1411:     }
        !          1412:   }
        !          1413:   if (DEBUGLEVEL>6)
        !          1414:     fprintferr("lllintpartial output = %Z", gmul(tm1, tm2));
        !          1415:   return gerepileupto(ltop1, gmul(tm1, tm2));
        !          1416: }
        !          1417:
        !          1418: GEN
        !          1419: lllintpartial(GEN mat)
        !          1420: {
        !          1421:   return lllintpartialall(mat,1);
        !          1422: }
        !          1423:
        !          1424: /********************************************************************/
        !          1425: /**                                                                **/
        !          1426: /**                   LINEAR & ALGEBRAIC DEPENDANCE                **/
        !          1427: /**                                                                **/
        !          1428: /********************************************************************/
        !          1429:
        !          1430: GEN
        !          1431: lindep0(GEN x,long bit,long prec)
        !          1432: {
        !          1433:   if (!bit) return lindep(x,prec);
        !          1434:   if (bit>0) return lindep2(x,bit);
        !          1435:   return deplin(x);
        !          1436: }
        !          1437:
        !          1438: static int
        !          1439: real_indep(GEN re, GEN im, long bitprec)
        !          1440: {
        !          1441:   GEN p1 = gsub(gmul((GEN)re[1],(GEN)im[2]),
        !          1442:                 gmul((GEN)re[2],(GEN)im[1]));
        !          1443:   return (!gcmp0(p1) && gexpo(p1) > - bitprec);
        !          1444: }
        !          1445:
        !          1446: GEN
        !          1447: lindep2(GEN x, long bit)
        !          1448: {
        !          1449:   long tx=typ(x),lx=lg(x),ly,i,j,e, av = avma;
        !          1450:   GEN re,im,p1,p2;
        !          1451:
        !          1452:   if (! is_vec_t(tx)) err(typeer,"lindep2");
        !          1453:   if (lx<=2) return cgetg(1,t_VEC);
        !          1454:   re = greal(x);
        !          1455:   im = gimag(x); bit = (long) (bit/L2SL10);
        !          1456:   /* independant over R ? */
        !          1457:   if (lx == 3 && real_indep(re,im,bit))
        !          1458:     { avma = av; return cgetg(1, t_VEC); }
        !          1459:
        !          1460:   if (gcmp0(im)) im = NULL;
        !          1461:   ly = im? lx+2: lx+1;
        !          1462:   p2=cgetg(lx,t_MAT);
        !          1463:   for (i=1; i<lx; i++)
        !          1464:   {
        !          1465:     p1 = cgetg(ly,t_COL); p2[i] = (long)p1;
        !          1466:     for (j=1; j<lx; j++) p1[j] = (i==j)? un: zero;
        !          1467:     p1[lx]           = lcvtoi(gshift((GEN)re[i],bit),&e);
        !          1468:     if (im) p1[lx+1] = lcvtoi(gshift((GEN)im[i],bit),&e);
        !          1469:   }
        !          1470:   p1 = (GEN)gmul(p2,lllint(p2))[1];
        !          1471:   p1[0] = evaltyp(t_VEC) | evallg(lx);
        !          1472:   return gerepilecopy(av, p1);
        !          1473: }
        !          1474:
        !          1475: #define quazero(x) (gcmp0(x) || (typ(x)==t_REAL && expo(x) < EXP))
        !          1476: GEN
        !          1477: lindep(GEN x, long prec)
        !          1478: {
        !          1479:   GEN *b,*be,*bn,**m,qzer;
        !          1480:   GEN c1,c2,c3,px,py,pxy,re,im,p1,p2,r,f,em;
        !          1481:   long i,j,fl,i1, lx = lg(x), tx = typ(x), n = lx-1;
        !          1482:   long av = avma, lim = stack_lim(av,1), av0,av1,tetpil;
        !          1483:   const long EXP = - bit_accuracy(prec) + 2*n;
        !          1484:
        !          1485:   if (! is_vec_t(tx)) err(typeer,"lindep");
        !          1486:   if (lx<=2) return cgetg(1,t_VEC);
        !          1487:   x = gmul(x, realun(prec));
        !          1488:   re=greal(x); im=gimag(x);
        !          1489:   /* independant over R ? */
        !          1490:   if (lx == 3 && real_indep(re,im,bit_accuracy(prec)))
        !          1491:     { avma = av; return cgetg(1, t_VEC); }
        !          1492:
        !          1493:   qzer = new_chunk(lx);
        !          1494:   b = (GEN*)idmat(n);
        !          1495:   be= (GEN*)new_chunk(lx);
        !          1496:   bn= (GEN*)new_chunk(lx);
        !          1497:   m = (GEN**)new_chunk(lx);
        !          1498:   for (i=1; i<=n; i++)
        !          1499:   {
        !          1500:     bn[i]=cgetr(prec+1);
        !          1501:     be[i]=cgetg(lx,t_COL);
        !          1502:     m[i] = (GEN*)new_chunk(lx);
        !          1503:     for (j=1; j<i ; j++) m[i][j]=cgetr(prec+1);
        !          1504:     for (j=1; j<=n; j++) be[i][j]=lgetr(prec+1);
        !          1505:   }
        !          1506:   px=sqscal(re);
        !          1507:   py=sqscal(im); pxy=gscal(re,im);
        !          1508:   p1=mpsub(mpmul(px,py),gsqr(pxy));
        !          1509:   if (quazero(re)) { re=im; px=py; fl=1; } else fl=quazero(p1);
        !          1510:   av0 = av1 = avma;
        !          1511:   for (i=1; i<=n; i++)
        !          1512:   {
        !          1513:     p2 = gscal(b[i],re);
        !          1514:     if (fl) p2=gmul(gdiv(p2,px),re);
        !          1515:     else
        !          1516:     {
        !          1517:       GEN p5,p6,p7;
        !          1518:       p5=gscal(b[i],im);
        !          1519:       p6=gdiv(gsub(gmul(py,p2),gmul(pxy,p5)),p1);
        !          1520:       p7=gdiv(gsub(gmul(px,p5),gmul(pxy,p2)),p1);
        !          1521:       p2=gadd(gmul(p6,re),gmul(p7,im));
        !          1522:     }
        !          1523:     if (tx!=t_COL) p2=gtrans(p2);
        !          1524:     p2=gsub(b[i],p2);
        !          1525:     for (j=1; j<i; j++)
        !          1526:       if (qzer[j]) affrr(bn[j],m[i][j]);
        !          1527:       else
        !          1528:       {
        !          1529:         gdivz(gscal(b[i],be[j]),bn[j],m[i][j]);
        !          1530:         p2=gsub(p2,gmul(m[i][j],be[j]));
        !          1531:       }
        !          1532:     gaffect(p2,be[i]); affrr(sqscal(be[i]),bn[i]);
        !          1533:     qzer[i]=quazero(bn[i]); avma=av1;
        !          1534:   }
        !          1535:   while (qzer[n])
        !          1536:   {
        !          1537:     long e;
        !          1538:     if (DEBUGLEVEL>9)
        !          1539:     {
        !          1540:       fprintferr("qzer[%ld]=%ld\n",n,qzer[n]);
        !          1541:       for (i1=1; i1<=n; i1++)
        !          1542:        for (i=1; i<i1; i++) output(m[i1][i]);
        !          1543:     }
        !          1544:     em=bn[1]; j=1;
        !          1545:     for (i=2; i<n; i++)
        !          1546:     {
        !          1547:       p1=shiftr(bn[i],i);
        !          1548:       if (cmprr(p1,em)>0) { em=p1; j=i; }
        !          1549:     }
        !          1550:     i=j; i1=i+1;
        !          1551:     avma = av1; r = grndtoi(m[i1][i], &e);
        !          1552:     if (e >= 0) err(precer,"lindep");
        !          1553:     r  = negi(r);
        !          1554:     p1 = ZV_lincomb(gun,r, b[i1],b[i]);
        !          1555:     av1 = avma;
        !          1556:     b[i1]=b[i]; b[i]=p1; f=addir(r,m[i1][i]);
        !          1557:     for (j=1; j<i; j++)
        !          1558:       if (!qzer[j])
        !          1559:       {
        !          1560:         p1=mpadd(m[i1][j],mulir(r,m[i][j]));
        !          1561:         affrr(m[i][j],m[i1][j]); mpaff(p1,m[i][j]);
        !          1562:       }
        !          1563:     c1=addrr(bn[i1],mulrr(gsqr(f),bn[i]));
        !          1564:     if (!quazero(c1))
        !          1565:     {
        !          1566:       c2=divrr(mulrr(bn[i],f),c1); affrr(c2,m[i1][i]);
        !          1567:       c3=divrr(bn[i1],c1); mulrrz(c3,bn[i],bn[i1]);
        !          1568:       affrr(c1,bn[i]); qzer[i1]=quazero(bn[i1]); qzer[i]=0;
        !          1569:       for (j=i+2; j<=n; j++)
        !          1570:       {
        !          1571:         p1=addrr(mulrr(m[j][i1],c3),mulrr(m[j][i],c2));
        !          1572:         subrrz(m[j][i],mulrr(f,m[j][i1]), m[j][i1]);
        !          1573:         affrr(p1,m[j][i]);
        !          1574:       }
        !          1575:     }
        !          1576:     else
        !          1577:     {
        !          1578:       qzer[i1]=qzer[i]; qzer[i]=1;
        !          1579:       affrr(bn[i],bn[i1]); affrr(c1,bn[i]);
        !          1580:       for (j=i+2; j<=n; j++) affrr(m[j][i],m[j][i1]);
        !          1581:     }
        !          1582:     if (low_stack(lim, stack_lim(av,1)))
        !          1583:     {
        !          1584:       if(DEBUGMEM>1) err(warnmem,"lindep");
        !          1585:       b = (GEN*)gerepilecopy(av0, (GEN)b);
        !          1586:       av1 = avma;
        !          1587:     }
        !          1588:   }
        !          1589:   p1=cgetg(lx,t_COL); p1[n]=un; for (i=1; i<n; i++) p1[i]=zero;
        !          1590:   p2 = (GEN)b; p2[0] = evaltyp(t_MAT) | evallg(lx);
        !          1591:   p2=gauss(gtrans(p2),p1); tetpil=avma;
        !          1592:   return gerepile(av,tetpil,gtrans(p2));
        !          1593: }
        !          1594:
        !          1595: /* x is a vector of elts of a p-adic field */
        !          1596: GEN
        !          1597: plindep(GEN x)
        !          1598: {
        !          1599:   long av = avma,i,j, prec = VERYBIGINT, lx = lg(x)-1, ly,v;
        !          1600:   GEN p = NULL, pn,p1,m,a;
        !          1601:
        !          1602:   if (lx < 2) return cgetg(1,t_VEC);
        !          1603:   for (i=1; i<=lx; i++)
        !          1604:   {
        !          1605:     p1 = (GEN)x[i];
        !          1606:     if (typ(p1) != t_PADIC) continue;
        !          1607:
        !          1608:     j = precp(p1); if (j < prec) prec = j;
        !          1609:     if (!p) p = (GEN)p1[2];
        !          1610:     else if (!egalii(p, (GEN)p1[2]))
        !          1611:       err(talker,"inconsistent primes in plindep");
        !          1612:   }
        !          1613:   if (!p) err(talker,"not a p-adic vector in plindep");
        !          1614:   v = ggval(x,p); pn = gpowgs(p,prec);
        !          1615:   if (v != 0) x = gmul(x, gpowgs(p, -v));
        !          1616:   x = lift_intern(gmul(x, gmodulcp(gun, pn)));
        !          1617:
        !          1618:   ly = 2*lx - 1;
        !          1619:   m = cgetg(ly+1,t_MAT);
        !          1620:   for (j=1; j<=ly; j++)
        !          1621:   {
        !          1622:     p1 = cgetg(lx+1, t_COL); m[j] = (long)p1;
        !          1623:     for (i=1; i<=lx; i++) p1[i] = zero;
        !          1624:   }
        !          1625:   a = negi((GEN)x[1]);
        !          1626:   for (i=1; i<lx; i++)
        !          1627:   {
        !          1628:     coeff(m,1+i,i) = (long)a;
        !          1629:     coeff(m,1  ,i) = x[i+1];
        !          1630:   }
        !          1631:   for (i=1; i<=lx; i++) coeff(m,i,lx-1+i) = (long)pn;
        !          1632:   p1 = lllint(m);
        !          1633:   return gerepileupto(av, gmul(m, (GEN)p1[1]));
        !          1634: }
        !          1635:
        !          1636: GEN
        !          1637: algdep0(GEN x, long n, long bit, long prec)
        !          1638: {
        !          1639:   long tx=typ(x),av,i,k;
        !          1640:   GEN y,p1;
        !          1641:
        !          1642:   if (! is_scalar_t(tx)) err(typeer,"algdep0");
        !          1643:   if (tx==t_POLMOD) { y=forcecopy((GEN)x[1]); setvarn(y,0); return y; }
        !          1644:   if (gcmp0(x)) return gzero;
        !          1645:   if (!n) return gun;
        !          1646:
        !          1647:   av=avma; p1=cgetg(n+2,t_COL);
        !          1648:   p1[1] = un;
        !          1649:   p1[2] = (long)x; /* n >= 1 */
        !          1650:   for (i=3; i<=n+1; i++) p1[i]=lmul((GEN)p1[i-1],x);
        !          1651:   if (typ(x) == t_PADIC)
        !          1652:     p1 = plindep(p1);
        !          1653:   else
        !          1654:     p1 = bit? lindep2(p1,bit): lindep(p1,prec);
        !          1655:   if (lg(p1) < 2)
        !          1656:     err(talker,"higher degree than expected in algdep");
        !          1657:
        !          1658:   y=cgetg(n+3,t_POL);
        !          1659:   y[1] = evalsigne(1) | evalvarn(0);
        !          1660:   k=1; while (gcmp0((GEN)p1[k])) k++;
        !          1661:   for (i=0; i<=n+1-k; i++) y[i+2] = p1[k+i];
        !          1662:   normalizepol_i(y, n+4-k);
        !          1663:   y = (gsigne(leading_term(y)) > 0)? gcopy(y): gneg(y);
        !          1664:   return gerepileupto(av,y);
        !          1665: }
        !          1666:
        !          1667: GEN
        !          1668: algdep2(GEN x, long n, long bit)
        !          1669: {
        !          1670:   return algdep0(x,n,bit,0);
        !          1671: }
        !          1672:
        !          1673: GEN
        !          1674: algdep(GEN x, long n, long prec)
        !          1675: {
        !          1676:   return algdep0(x,n,0,prec);
        !          1677: }
        !          1678:
        !          1679: /********************************************************************/
        !          1680: /**                                                                **/
        !          1681: /**                   INTEGRAL KERNEL (LLL REDUCED)                **/
        !          1682: /**                                                                **/
        !          1683: /********************************************************************/
        !          1684:
        !          1685: GEN
        !          1686: matkerint0(GEN x, long flag)
        !          1687: {
        !          1688:   switch(flag)
        !          1689:   {
        !          1690:     case 0: return kerint(x);
        !          1691:     case 1: return kerint1(x);
        !          1692:     case 2: return kerint2(x);
        !          1693:     default: err(flagerr,"matkerint");
        !          1694:   }
        !          1695:   return NULL; /* not reached */
        !          1696: }
        !          1697:
        !          1698: GEN
        !          1699: kerint1(GEN x)
        !          1700: {
        !          1701:   long av=avma,tetpil;
        !          1702:   GEN p1,p2;
        !          1703:
        !          1704:   p1=matrixqz3(ker(x)); p2=lllint(p1); tetpil=avma;
        !          1705:   return gerepile(av,tetpil,gmul(p1,p2));
        !          1706: }
        !          1707:
        !          1708: GEN
        !          1709: kerint2(GEN x)
        !          1710: {
        !          1711:   long lx=lg(x), i,j,av,av1;
        !          1712:   GEN g,p1;
        !          1713:
        !          1714:   if (typ(x) != t_MAT) err(typeer,"kerint2");
        !          1715:   av=avma; g=cgetg(lx,t_MAT);
        !          1716:   for (j=1; j<lx; j++) g[j]=lgetg(lx,t_COL);
        !          1717:   for (i=1; i<lx; i++)
        !          1718:     for (j=1; j<=i; j++)
        !          1719:       coeff(g,i,j) = coeff(g,j,i) = (long)gscal((GEN)x[i],(GEN)x[j]);
        !          1720:   g=lllgramall0(g,lll_KER); p1=lllint(g);
        !          1721:   av1=avma; return gerepile(av,av1,gmul(g,p1));
        !          1722: }
        !          1723:
        !          1724: static GEN
        !          1725: lllall0(GEN x, long flag)
        !          1726: {
        !          1727:   long av0=avma,av,tetpil,lx=lg(x),i,j,k,l,n,lim,kmax;
        !          1728:   GEN u,B,L,q,r,h,la,p1,p2,p4,fl;
        !          1729:
        !          1730:   if (typ(x) != t_MAT) err(typeer,"lllall0");
        !          1731:   n=lx-1; if (n<=1) return lllall_trivial(x,n, flag | lll_GRAM);
        !          1732:   fl = new_chunk(lx);
        !          1733:
        !          1734:   av=avma; lim=stack_lim(av,1); x=dummycopy(x);
        !          1735:   B=gscalcol(gun, lx);
        !          1736:   L=cgetg(lx,t_MAT);
        !          1737:   for (k=lg(x[1]),j=1; j<lx; j++)
        !          1738:   {
        !          1739:     for (i=1; i<k; i++)
        !          1740:       if (typ(gcoeff(x,i,j))!=t_INT) err(lllger4);
        !          1741:     fl[j] = 0; L[j] = (long)zerocol(n);
        !          1742:   }
        !          1743:   k=2; h=idmat(n); kmax=1;
        !          1744:   u=sqscali((GEN)x[1]);
        !          1745:   if (signe(u)) { B[2]=(long)u; coeff(L,1,1)=un; fl[1]=1; } else B[2]=un;
        !          1746:   for(;;)
        !          1747:   {
        !          1748:     if (k > kmax)
        !          1749:     {
        !          1750:       kmax = k;
        !          1751:       for (j=1; j<=k; j++)
        !          1752:       {
        !          1753:        if (j==k || fl[j])
        !          1754:        {
        !          1755:           long av1 = avma;
        !          1756:          u=gscali((GEN)x[k],(GEN)x[j]);
        !          1757:          for (i=1; i<j; i++)
        !          1758:            if (fl[i])
        !          1759:               u = divii(subii(mulii((GEN)B[i+1],u),
        !          1760:                               mulii(gcoeff(L,k,i),gcoeff(L,j,i))),
        !          1761:                         (GEN)B[i]);
        !          1762:           u = gerepileuptoint(av1, u);
        !          1763:          if (j<k) coeff(L,k,j)=(long)u;
        !          1764:          else
        !          1765:          {
        !          1766:            if (signe(u)) { B[k+1]=(long)u; coeff(L,k,k)=un; fl[k]=1; }
        !          1767:            else { B[k+1]=B[k]; fl[k]=0; }
        !          1768:          }
        !          1769:        }
        !          1770:       }
        !          1771:     }
        !          1772:     if (fl[k-1] && !fl[k])
        !          1773:     {
        !          1774:       u = shifti(gcoeff(L,k,k-1),1);
        !          1775:       if (absi_cmp(u, (GEN)B[k]) > 0)
        !          1776:       {
        !          1777:        q = truedvmdii(addii(u,(GEN)B[k]),shifti((GEN)B[k],1), NULL);
        !          1778:         r = negi(q);
        !          1779:         h[k] = (long)ZV_lincomb(gun,r, (GEN)h[k],(GEN)h[k-1]);
        !          1780:         x[k] = (long)ZV_lincomb(gun,r, (GEN)x[k],(GEN)x[k-1]);
        !          1781:        coeff(L,k,k-1)=laddii(gcoeff(L,k,k-1),mulii(r,(GEN)B[k]));
        !          1782:        for (i=1; i<k-1; i++)
        !          1783:          coeff(L,k,i)=laddii(gcoeff(L,k,i),mulii(r,gcoeff(L,k-1,i)));
        !          1784:       }
        !          1785:       la=gcoeff(L,k,k-1); p4=sqri(la);
        !          1786:       swap(h[k-1], h[k]);
        !          1787:       swap(x[k-1], x[k]);
        !          1788:       for (j=1; j<k-1; j++) swap(coeff(L,k-1,j), coeff(L,k,j));
        !          1789:       if (signe(la))
        !          1790:       {
        !          1791:        p2=(GEN)B[k]; p1=divii(p4,p2);
        !          1792:        B[k+1]=B[k]=(long)p1;
        !          1793:        for (i=k+1; i<=kmax; i++)
        !          1794:          coeff(L,i,k-1)=ldivii(mulii(la,gcoeff(L,i,k-1)),p2);
        !          1795:        for (j=k+1; j<kmax; j++)
        !          1796:          for (i=j+1; i<=kmax; i++)
        !          1797:            coeff(L,i,j)=ldivii(mulii((GEN)p1,gcoeff(L,i,j)),p2);
        !          1798:        for (i=k+2; i<=kmax+1; i++)
        !          1799:          B[i]=ldivii(mulii((GEN)p1,(GEN)B[i]),p2);
        !          1800:       }
        !          1801:       else
        !          1802:       {
        !          1803:        for (i=k+1; i<=kmax; i++)
        !          1804:        { coeff(L,i,k)=coeff(L,i,k-1); coeff(L,i,k-1)=zero; }
        !          1805:        B[k]=B[k-1]; fl[k]=1; fl[k-1]=0;
        !          1806:       }
        !          1807:       if (k>2) k--;
        !          1808:     }
        !          1809:     else
        !          1810:     {
        !          1811:       for (l=k-1; l>=1; l--)
        !          1812:       {
        !          1813:         u = shifti(gcoeff(L,k,l),1);
        !          1814:        if (absi_cmp(u,(GEN)B[l+1]) > 0)
        !          1815:        {
        !          1816:          q = truedvmdii(addii(u,(GEN)B[l+1]),shifti((GEN)B[l+1],1), NULL);
        !          1817:           r = negi(q);
        !          1818:          h[k] = (long)ZV_lincomb(gun,r,(GEN)h[k],(GEN)h[l]);
        !          1819:          x[k] = (long)ZV_lincomb(gun,r,(GEN)x[k],(GEN)x[l]);
        !          1820:          coeff(L,k,l)=laddii(gcoeff(L,k,l),mulii(r,(GEN)B[l+1]));
        !          1821:          for (i=1; i<l; i++)
        !          1822:            coeff(L,k,i)=laddii(gcoeff(L,k,i),mulii(r,gcoeff(L,l,i)));
        !          1823:         }
        !          1824:       }
        !          1825:       if (++k > n) break;
        !          1826:     }
        !          1827:     if (low_stack(lim, stack_lim(av,1)))
        !          1828:     {
        !          1829:       GEN *gptr[4];
        !          1830:       if(DEBUGMEM>1) err(warnmem,"lllall0");
        !          1831:       gptr[0]=&B; gptr[1]=&L; gptr[2]=&h;
        !          1832:       gptr[3]=&x; gerepilemany(av,gptr,4);
        !          1833:     }
        !          1834:   }
        !          1835:   tetpil=avma;
        !          1836:   return gerepile(av0,tetpil,lllgramall_finish(h,fl,flag,n));
        !          1837: }
        !          1838:
        !          1839: GEN
        !          1840: kerint(GEN x)
        !          1841: {
        !          1842:   long av=avma,av1;
        !          1843:   GEN g,p1;
        !          1844:
        !          1845:   g=lllall0(x,lll_KER); if (lg(g)==1) return g;
        !          1846:   p1=lllint(g); av1=avma;
        !          1847:   return gerepile(av,av1,gmul(g,p1));
        !          1848: }
        !          1849:
        !          1850: /********************************************************************/
        !          1851: /**                                                                **/
        !          1852: /**                        POLRED & CO.                            **/
        !          1853: /**                                                                **/
        !          1854: /********************************************************************/
        !          1855: /* remove duplicate polynomials in y, updating a (same indexes), in place */
        !          1856: static long
        !          1857: remove_duplicates(GEN y, GEN a)
        !          1858: {
        !          1859:   long k,i, nv = lg(y), av = avma;
        !          1860:   GEN z;
        !          1861:
        !          1862:   if (nv < 2) return nv;
        !          1863:   z = new_chunk(3);
        !          1864:   z[1] = (long)y;
        !          1865:   z[2] = (long)a; (void)sort_factor(z, gcmp);
        !          1866:   for  (k=1, i=2; i<nv; i++)
        !          1867:     if (!gegal((GEN)y[i], (GEN)y[k]))
        !          1868:     {
        !          1869:       k++;
        !          1870:       a[k] = a[i];
        !          1871:       y[k] = y[i];
        !          1872:     }
        !          1873:   nv = k+1; setlg(a,nv); setlg(y,nv);
        !          1874:   avma = av; return nv;
        !          1875: }
        !          1876:
        !          1877: /* in place; make sure second non-zero coeff is negative (choose x or -x) */
        !          1878: int
        !          1879: canon_pol(GEN z)
        !          1880: {
        !          1881:   long i,s;
        !          1882:
        !          1883:   for (i=lgef(z)-2; i>=2; i-=2)
        !          1884:   {
        !          1885:     s = signe(z[i]);
        !          1886:     if (s > 0)
        !          1887:     {
        !          1888:       for (; i>=2; i-=2) z[i]=lnegi((GEN)z[i]);
        !          1889:       return -1;
        !          1890:     }
        !          1891:     if (s) return 1;
        !          1892:   }
        !          1893:   return 0;
        !          1894: }
        !          1895:
        !          1896: static GEN
        !          1897: pols_for_polred(GEN x, GEN base, GEN LLLbase, GEN *pta,
        !          1898:                int (*check)(GEN, GEN), GEN arg)
        !          1899: {
        !          1900:   long i, v = varn(x), n = lg(base);
        !          1901:   GEN p1,p2,p3,y, a = cgetg(n,t_VEC);
        !          1902:
        !          1903:   for (i=1; i<n; i++) a[i] = lmul(base,(GEN)LLLbase[i]);
        !          1904:   y=cgetg(n,t_VEC);
        !          1905:   for (i=1; i<n; i++)
        !          1906:   {
        !          1907:     if (DEBUGLEVEL > 2) { fprintferr("i = %ld\n",i); flusherr(); }
        !          1908:     p1=(GEN)a[i];
        !          1909:     p1 = primitive_part(p1, &p3);
        !          1910:     p1 = caractducos(x,p1,v);
        !          1911:     if (p3) p1 = ZX_rescale_pol(p1,p3);
        !          1912:     p2 = modulargcd(derivpol(p1),p1);
        !          1913:     p3 = leading_term(p2); if (!gcmp1(p3)) p2=gdiv(p2,p3);
        !          1914:     p1 = gdiv(p1,p2);
        !          1915:     if (canon_pol(p1) < 0 && pta) a[i] = (long)gneg_i((GEN)a[i]);
        !          1916:     y[i] = (long)p1; if (DEBUGLEVEL > 3) outerr(p1);
        !          1917:     if (check && check(arg, p1)) return p1;
        !          1918:   }
        !          1919:   if (check) return NULL; /* no suitable polynomial found */
        !          1920:   (void)remove_duplicates(y,a);
        !          1921:   if (pta) *pta = a;
        !          1922:   return y;
        !          1923: }
        !          1924:
        !          1925: GEN
        !          1926: nf_get_T2(GEN base, GEN polr)
        !          1927: {
        !          1928:   long i,j, n = lg(base);
        !          1929:   GEN p1,p2=cgetg(n,t_MAT);
        !          1930:
        !          1931:   for (i=1; i<n; i++)
        !          1932:   {
        !          1933:     p1=cgetg(n,t_COL); p2[i]=(long)p1;
        !          1934:     for (j=1; j<n; j++)
        !          1935:       p1[j] = (long) poleval((GEN)base[i],(GEN)polr[j]);
        !          1936:   }
        !          1937:   return mulmat_real(gconj(gtrans(p2)),p2);
        !          1938: }
        !          1939:
        !          1940: /* compute Tr(w_i w_j) */
        !          1941: static GEN
        !          1942: nf_get_T(GEN x, GEN w)
        !          1943: {
        !          1944:   long i,j,k, n = degpol(x);
        !          1945:   GEN p1,p2,p3;
        !          1946:   GEN ptrace = cgetg(n+2,t_VEC);
        !          1947:   GEN den = cgetg(n+1,t_VEC);
        !          1948:   GEN T = cgetg(n+1,t_MAT);
        !          1949:
        !          1950:   ptrace[2]=lstoi(n);
        !          1951:   for (k=2; k<=n; k++)
        !          1952:   { /* cf polsym */
        !          1953:     GEN y = x + (n-k+1);
        !          1954:     p1 = mulsi(k-1,(GEN)y[2]);
        !          1955:     for (i=3; i<=k; i++)
        !          1956:       p1 = addii(p1,mulii((GEN)y[i],(GEN)ptrace[i]));
        !          1957:     ptrace[i] = lnegi(p1);
        !          1958:   }
        !          1959:   w = dummycopy(w);
        !          1960:   for (i=1; i<=n; i++)
        !          1961:   {
        !          1962:     den[i] = (long)denom(content((GEN)w[i]));
        !          1963:     w[i] = lmul((GEN)w[i],(GEN)den[i]);
        !          1964:   }
        !          1965:
        !          1966:   for (i=1; i<=n; i++)
        !          1967:   {
        !          1968:     p1=cgetg(n+1,t_COL); T[i]=(long)p1;
        !          1969:     for (j=1; j<i ; j++) p1[j] = coeff(T,i,j);
        !          1970:     for (   ; j<=n; j++)
        !          1971:     { /* cf quicktrace */
        !          1972:       p2 = gres(gmul((GEN)w[i],(GEN)w[j]),x);
        !          1973:       p3 = gzero;
        !          1974:       for (k=lgef(p2)-1; k>1; k--)
        !          1975:         p3 = addii(p3, mulii((GEN)p2[k],(GEN)ptrace[k]));
        !          1976:       p1[j]=(long)divii(p3, mulii((GEN)den[i],(GEN)den[j]));
        !          1977:     }
        !          1978:   }
        !          1979:   return T;
        !          1980: }
        !          1981:
        !          1982: /* Return the base change matrix giving the an LLL-reduced basis for the
        !          1983:  * maximal order of the nf given by x. Expressed in terms of the standard
        !          1984:  * HNF basis (as polynomials) given in base (ignored if x is an nf)
        !          1985:  */
        !          1986: GEN
        !          1987: LLL_nfbasis(GEN *ptx, GEN polr, GEN base, long prec)
        !          1988: {
        !          1989:   GEN T2,p1, x = *ptx;
        !          1990:   int totally_real,n,i;
        !          1991:
        !          1992:   if (typ(x) != t_POL)
        !          1993:   {
        !          1994:     p1=checknf(x); *ptx=x=(GEN)p1[1];
        !          1995:     base=(GEN)p1[7]; n=degpol(x);
        !          1996:     totally_real = !signe(gmael(p1,2,2));
        !          1997:     T2=gmael(p1,5,3); if (totally_real) T2 = ground(T2);
        !          1998:   }
        !          1999:   else
        !          2000:   {
        !          2001:     n=degpol(x); totally_real = (!prec || sturm(x)==n);
        !          2002:     if (typ(base) != t_VEC || lg(base)-1 != n)
        !          2003:       err(talker,"incorrect Zk basis in LLL_nfbasis");
        !          2004:     if (!totally_real)
        !          2005:       T2 = nf_get_T2(base,polr? polr: roots(x,prec));
        !          2006:     else
        !          2007:       T2 = nf_get_T(x, base);
        !          2008:   }
        !          2009:   if (totally_real) return lllgramint(T2);
        !          2010:   for (i=1; ; i++)
        !          2011:   {
        !          2012:     if ((p1 = lllgramintern(T2,100,1,prec))) return p1;
        !          2013:     if (i == MAXITERPOL) err(accurer,"allpolred");
        !          2014:     prec=(prec<<1)-2;
        !          2015:     if (DEBUGLEVEL) err(warnprec,"allpolred",prec);
        !          2016:     T2=nf_get_T2(base,roots(x,prec));
        !          2017:   }
        !          2018: }
        !          2019:
        !          2020: /* x can be a polynomial, but also an nf or a bnf */
        !          2021: /* if check != NULL, return the first polynomial pol
        !          2022:    found such that check(arg, pol) != 0; return NULL
        !          2023:    if there are no such pol */
        !          2024: static GEN
        !          2025: allpolred0(GEN x, GEN *pta, long code, long prec,
        !          2026:           int (*check)(GEN,GEN), GEN arg)
        !          2027: {
        !          2028:   GEN y,p1, base = NULL, polr = NULL;
        !          2029:   long av = avma;
        !          2030:
        !          2031:   if (typ(x) == t_POL)
        !          2032:   {
        !          2033:     if (!signe(x)) return gcopy(x);
        !          2034:     check_pol_int(x,"polred");
        !          2035:     if (!gcmp1(leading_term(x)))
        !          2036:       err(impl,"allpolred for nonmonic polynomials");
        !          2037:     base = allbase4(x,code,&p1,NULL); /* p1 is junk */
        !          2038:   }
        !          2039:   else
        !          2040:   {
        !          2041:     long i = lg(x);
        !          2042:     if (typ(x) == t_VEC && i<=4 && i>=3 && typ(x[1])==t_POL)
        !          2043:     { /* polynomial + integer basis */
        !          2044:       base=(GEN)x[2]; x=(GEN)x[1];
        !          2045:     }
        !          2046:     else
        !          2047:     {
        !          2048:       x = checknf(x);
        !          2049:       base=(GEN)x[7]; x=(GEN)x[1];
        !          2050:     }
        !          2051:   }
        !          2052:   p1 = LLL_nfbasis(&x,polr,base,prec);
        !          2053:   y = pols_for_polred(x,base,p1,pta,check,arg);
        !          2054:   if (check)
        !          2055:   {
        !          2056:     if (y) return gerepileupto(av, y);
        !          2057:     avma = av; return NULL;
        !          2058:   }
        !          2059:
        !          2060:   if (pta)
        !          2061:   {
        !          2062:     GEN *gptr[2]; gptr[0]=&y; gptr[1]=pta;
        !          2063:     gerepilemany(av,gptr,2); return y;
        !          2064:   }
        !          2065:   return gerepileupto(av,y);
        !          2066: }
        !          2067:
        !          2068: static GEN
        !          2069: allpolred(GEN x, GEN *pta, long code, long prec)
        !          2070: {
        !          2071:   return allpolred0(x,pta,code,prec,NULL,NULL);
        !          2072: }
        !          2073:
        !          2074: GEN
        !          2075: polred0(GEN x,long flag, GEN p, long prec)
        !          2076: {
        !          2077:   GEN y;
        !          2078:   long smll = (flag & 1);
        !          2079:
        !          2080:   if (p && !gcmp0(p)) smll=(long) p; /* factored polred */
        !          2081:   if (flag & 2) /* polred2 */
        !          2082:   {
        !          2083:     y=cgetg(3,t_MAT);
        !          2084:     y[2]=(long)allpolred(x,(GEN*)(y+1),smll,prec);
        !          2085:     return y;
        !          2086:   }
        !          2087:   return allpolred(x,NULL,smll,prec);
        !          2088: }
        !          2089:
        !          2090: GEN
        !          2091: ordred(GEN x, long prec)
        !          2092: {
        !          2093:   GEN base,y;
        !          2094:   long n=degpol(x),i,av=avma,v = varn(x);
        !          2095:
        !          2096:   if (typ(x) != t_POL) err(typeer,"ordred");
        !          2097:   if (!signe(x)) return gcopy(x);
        !          2098:   if (!gcmp1((GEN)x[n+2])) err(impl,"ordred for nonmonic polynomials");
        !          2099:
        !          2100:   base = cgetg(n+1,t_VEC); /* power basis */
        !          2101:   for (i=1; i<=n; i++)
        !          2102:     base[i] = lpowgs(polx[v],i-1);
        !          2103:   y = cgetg(3,t_VEC);
        !          2104:   y[1] = (long)x;
        !          2105:   y[2] = (long)base;
        !          2106:   return gerepileupto(av, allpolred(y,NULL,0,prec));
        !          2107: }
        !          2108:
        !          2109: GEN
        !          2110: sum(GEN v, long a, long b)
        !          2111: {
        !          2112:   GEN p;
        !          2113:   long i;
        !          2114:   if (a > b) return gzero;
        !          2115:   p = (GEN)v[a];
        !          2116:   for (i=a+1; i<=b; i++) p = gadd(p, (GEN)v[i]);
        !          2117:   return p;
        !          2118: }
        !          2119:
        !          2120: GEN
        !          2121: T2_from_embed_norm(GEN x, long r1)
        !          2122: {
        !          2123:   GEN p = sum(x, 1, r1);
        !          2124:   GEN q = sum(x, r1+1, lg(x)-1);
        !          2125:   if (q != gzero) p = gadd(p, gmul2n(q,1));
        !          2126:   return p;
        !          2127: }
        !          2128:
        !          2129: GEN
        !          2130: T2_from_embed(GEN x, long r1)
        !          2131: {
        !          2132:   return T2_from_embed_norm(gnorm(x), r1);
        !          2133: }
        !          2134:
        !          2135: /* return T2 norm of the polynomial defining nf */
        !          2136: static GEN
        !          2137: get_Bnf(GEN nf)
        !          2138: {
        !          2139:   return T2_from_embed((GEN)nf[6], nf_get_r1(nf));
        !          2140: }
        !          2141:
        !          2142: /* characteristic pol of x */
        !          2143: static GEN
        !          2144: get_polchar(GEN data, GEN x)
        !          2145: {
        !          2146:   GEN basis_embed = (GEN)data[1];
        !          2147:   GEN g = gmul(basis_embed,x);
        !          2148:   return ground(roots_to_pol_r1r2(g, data[0], 0));
        !          2149: }
        !          2150:
        !          2151: /* return a defining polynomial for Q(x) */
        !          2152: static GEN
        !          2153: get_polmin(GEN data, GEN x)
        !          2154: {
        !          2155:   GEN g = get_polchar(data,x);
        !          2156:   GEN h = modulargcd(g,derivpol(g));
        !          2157:   if (lgef(h) > 3) g = gdivexact(g,h);
        !          2158:   return g;
        !          2159: }
        !          2160:
        !          2161: /* does x generate the correct field ? */
        !          2162: static GEN
        !          2163: chk_gen(GEN data, GEN x)
        !          2164: {
        !          2165:   long av = avma;
        !          2166:   GEN g = get_polchar(data,x);
        !          2167:   if (lgef(modulargcd(g,derivpol(g))) > 3) { avma=av; return NULL; }
        !          2168:   if (DEBUGLEVEL>3) fprintferr("  generator: %Z\n",g);
        !          2169:   return g;
        !          2170: }
        !          2171:
        !          2172: /* mat = base change matrix, gram = LLL-reduced T2 matrix */
        !          2173: static GEN
        !          2174: chk_gen_init(FP_chk_fun *chk, GEN nf, GEN gram, GEN mat, long *ptprec)
        !          2175: {
        !          2176:   GEN P,bound,prev,x,B,data, M = gmael(nf,5,1);
        !          2177:   long N = lg(nf[7]), n = N-1,i,prec,prec2;
        !          2178:   int skipfirst = 1; /* [1,0...0] --> x rational */
        !          2179:
        !          2180: /* data[0] = r1
        !          2181:  * data[1] = embeddings of LLL-reduced Zk basis
        !          2182:  * data[2] = LLL reduced Zk basis (in M_n(Z)) */
        !          2183:   data = new_chunk(3);
        !          2184:   data[0] = itos(gmael(nf,2,1));
        !          2185:   data[1] = lmul(M, mat);
        !          2186:   data[2] = lmul((GEN)nf[7],mat);
        !          2187:   chk->data = data;
        !          2188:
        !          2189:   x = cgetg(N,t_COL);
        !          2190:   bound = get_Bnf(nf); prev = NULL;
        !          2191:   for (i=1; i<N; i++) x[i]=zero;
        !          2192:   for (i=2; i<N; i++)
        !          2193:   {
        !          2194:     x[i] = un;
        !          2195:     P = get_polmin(data,x);
        !          2196:     x[i] = zero;
        !          2197:     if (degpol(P) == n)
        !          2198:     {
        !          2199:       B = gcoeff(gram,i,i);
        !          2200:       if (gcmp(B,bound) < 0) bound = B ;
        !          2201:     }
        !          2202:     else
        !          2203:     {
        !          2204:       if (DEBUGLEVEL>2) fprintferr("chk_gen_init: subfield %Z\n",P);
        !          2205:       if (skipfirst == i-1)
        !          2206:       {
        !          2207:         if (prev && !gegal(prev,P))
        !          2208:         {
        !          2209:           if (degpol(prev) * degpol(P) > 32) continue; /* too expensive */
        !          2210:           P = (GEN)compositum(prev,P)[1];
        !          2211:           if (degpol(P) == n) continue;
        !          2212:           if (DEBUGLEVEL>2 && lgef(P)>lgef(prev))
        !          2213:             fprintferr("chk_gen_init: subfield %Z\n",P);
        !          2214:         }
        !          2215:         skipfirst++; prev = P;
        !          2216:       }
        !          2217:     }
        !          2218:   }
        !          2219:   /* x_1,...,x_skipfirst generate a strict subfield [unless n=skipfirst=1] */
        !          2220:   chk->skipfirst = skipfirst;
        !          2221:   if (DEBUGLEVEL>2) fprintferr("chk_gen_init: skipfirst = %ld\n",skipfirst);
        !          2222:
        !          2223:   /* should be gexpo( [max_k C^n_k (bound/k) ^ k] ^ (1/2) ) */
        !          2224:   prec2 = (1 + (((gexpo(bound)*n)/2) >> TWOPOTBITS_IN_LONG));
        !          2225:   if (prec2 < 0) prec2 = 0;
        !          2226:   prec = 3 + prec2;
        !          2227:   prec2= nfgetprec(nf);
        !          2228:   if (DEBUGLEVEL)
        !          2229:     fprintferr("chk_gen_init: estimated prec = %ld (initially %ld)\n",
        !          2230:                 prec, prec2);
        !          2231:   if (prec > prec2) return NULL;
        !          2232:   if (prec < prec2) data[1] = (long)gprec_w((GEN)data[1], prec);
        !          2233:   *ptprec = prec; return bound;
        !          2234: }
        !          2235:
        !          2236: static GEN
        !          2237: chk_gen_post(GEN data, GEN res)
        !          2238: {
        !          2239:   GEN basis = (GEN)data[2];
        !          2240:   GEN p1 = (GEN)res[2];
        !          2241:   long i, l = lg(p1);
        !          2242:   for (i=1; i<l; i++) p1[i] = lmul(basis, (GEN)p1[i]);
        !          2243:   return res;
        !          2244: }
        !          2245:
        !          2246: /* no garbage collecting, done in polredabs0 */
        !          2247: static GEN
        !          2248: findmindisc(GEN nf, GEN y, GEN a, GEN phimax, long flun)
        !          2249: {
        !          2250:   long i,k, c = lg(y);
        !          2251:   GEN v,dmin,z,beta,discs = cgetg(c,t_VEC);
        !          2252:
        !          2253:   for (i=1; i<c; i++) discs[i] = labsi(discsr((GEN)y[i]));
        !          2254:   v = sindexsort(discs);
        !          2255:   k = v[1]; dmin = (GEN)discs[k]; z = (GEN)y[k]; beta = (GEN)a[k];
        !          2256:   for (i=2; i<c; i++)
        !          2257:   {
        !          2258:     k = v[i];
        !          2259:     if (!egalii((GEN)discs[k],dmin)) break;
        !          2260:     if (gpolcomp((GEN)y[k],z) < 0) { z = (GEN)y[k]; beta = (GEN)a[k]; }
        !          2261:   }
        !          2262:   if (flun & nf_RAW)
        !          2263:   {
        !          2264:     y=cgetg(3,t_VEC);
        !          2265:     y[1]=lcopy(z);
        !          2266:     y[2]=lcopy(beta);
        !          2267:   }
        !          2268:   else if (phimax)
        !          2269:   {
        !          2270:     y=cgetg(3,t_VEC);
        !          2271:     y[1]=lcopy(z);
        !          2272:     beta=polymodrecip(gmodulcp(beta,(GEN)nf[1]));
        !          2273:     y[2]=(long)poleval(phimax,beta);
        !          2274:   }
        !          2275:   else y = gcopy(z);
        !          2276:   return y;
        !          2277: }
        !          2278:
        !          2279: /* no garbage collecting, done in polredabs0 */
        !          2280: static GEN
        !          2281: storeallpols(GEN nf, GEN z, GEN a, GEN phimax, long flun)
        !          2282: {
        !          2283:   GEN p1,y,beta;
        !          2284:
        !          2285:   if (flun & nf_RAW)
        !          2286:   {
        !          2287:     long i, c = lg(z);
        !          2288:     y=cgetg(c,t_VEC);
        !          2289:     for (i=1; i<c; i++)
        !          2290:     {
        !          2291:       p1=cgetg(3,t_VEC); y[i]=(long)p1;
        !          2292:       p1[1]=lcopy((GEN)z[i]);
        !          2293:       p1[2]=lcopy((GEN)a[i]);
        !          2294:     }
        !          2295:   }
        !          2296:   else if (phimax)
        !          2297:   {
        !          2298:     long i, c = lg(z);
        !          2299:     beta = new_chunk(c);
        !          2300:     for (i=1; i<c; i++)
        !          2301:       beta[i] = (long)polymodrecip(gmodulcp((GEN)a[i],(GEN)nf[1]));
        !          2302:
        !          2303:     y=cgetg(c,t_VEC);
        !          2304:     for (i=1; i<c; i++)
        !          2305:     {
        !          2306:       p1=cgetg(3,t_VEC); y[i]=(long)p1;
        !          2307:       p1[1]=lcopy((GEN)z[i]);
        !          2308:       p1[2]=(long)poleval(phimax,(GEN)beta[i]);
        !          2309:     }
        !          2310:   }
        !          2311:   else y = gcopy(z);
        !          2312:   return y;
        !          2313: }
        !          2314:
        !          2315: GEN
        !          2316: polredabs0(GEN x, long flun, long prec)
        !          2317: {
        !          2318:   long i,nv, av = avma;
        !          2319:   GEN nf,v,y,a,phimax;
        !          2320:   GEN (*storepols)(GEN, GEN, GEN, GEN, long);
        !          2321:   FP_chk_fun *chk;
        !          2322:
        !          2323:   chk = (FP_chk_fun*)new_chunk(sizeof(FP_chk_fun));
        !          2324:   chk->f         = &chk_gen;
        !          2325:   chk->f_init    = &chk_gen_init;
        !          2326:   chk->f_post    = &chk_gen_post;
        !          2327:
        !          2328:   if ((ulong)flun >= 16) err(flagerr,"polredabs");
        !          2329:   nf = initalgall0(x,nf_SMALL|nf_REGULAR,prec);
        !          2330:   if (lg(nf) == 3)
        !          2331:   {
        !          2332:     phimax = lift_to_pol((GEN)nf[2]);
        !          2333:     nf = (GEN)nf[1];
        !          2334:   }
        !          2335:   else
        !          2336:     phimax = (flun & nf_ORIG)? polx[0]: (GEN)NULL;
        !          2337:   prec = nfgetprec(nf);
        !          2338:   x = (GEN)nf[1];
        !          2339:
        !          2340:   if (lgef(x) == 4)
        !          2341:   {
        !          2342:     y = _vec(polx[varn(x)]);
        !          2343:     a = _vec(gsub((GEN)y[1], (GEN)x[2]));
        !          2344:   }
        !          2345:   else
        !          2346:   {
        !          2347:     for (i=1; ; i++)
        !          2348:     {
        !          2349:       v = fincke_pohst(nf,NULL,5000,3,prec, chk);
        !          2350:       if (v) break;
        !          2351:       if (i==MAXITERPOL) err(accurer,"polredabs0");
        !          2352:       prec = (prec<<1)-2; nf = nfnewprec(nf,prec);
        !          2353:       if (DEBUGLEVEL) err(warnprec,"polredabs0",prec);
        !          2354:     }
        !          2355:     a = (GEN)v[2];
        !          2356:     y = (GEN)v[1];
        !          2357:   }
        !          2358:   nv = lg(a);
        !          2359:   for (i=1; i<nv; i++)
        !          2360:     if (canon_pol((GEN)y[i]) < 0 && phimax)
        !          2361:       a[i] = (long) gneg_i((GEN)a[i]);
        !          2362:   nv = remove_duplicates(y,a);
        !          2363:
        !          2364:   if (DEBUGLEVEL)
        !          2365:     { fprintferr("%ld minimal vectors found.\n",nv-1); flusherr(); }
        !          2366:   if (nv >= 10000) flun &= (~nf_ALL); /* should not happen */
        !          2367:   storepols = (flun & nf_ALL)? storeallpols: findmindisc;
        !          2368:
        !          2369:   if (DEBUGLEVEL) fprintferr("\n");
        !          2370:   if (nv==1)
        !          2371:   {
        !          2372:     y = _vec(x);
        !          2373:     a = _vec(polx[varn(x)]);
        !          2374:   }
        !          2375:   if (varn(y[1]) != varn(x))
        !          2376:   {
        !          2377:     long vx = varn(x);
        !          2378:     for (i=1; i<nv; i++) setvarn(y[i], vx);
        !          2379:   }
        !          2380:   return gerepileupto(av, storepols(nf,y,a,phimax,flun));
        !          2381: }
        !          2382:
        !          2383: GEN
        !          2384: polredabsall(GEN x, long flun, long prec)
        !          2385: {
        !          2386:   return polredabs0(x, flun | nf_ALL, prec);
        !          2387: }
        !          2388:
        !          2389: GEN
        !          2390: polredabs(GEN x, long prec)
        !          2391: {
        !          2392:   return polredabs0(x,nf_REGULAR,prec);
        !          2393: }
        !          2394:
        !          2395: GEN
        !          2396: polredabs2(GEN x, long prec)
        !          2397: {
        !          2398:   return polredabs0(x,nf_ORIG,prec);
        !          2399: }
        !          2400:
        !          2401: GEN
        !          2402: polredabsnored(GEN x, long prec)
        !          2403: {
        !          2404:   return polredabs0(x,nf_NORED,prec);
        !          2405: }
        !          2406:
        !          2407: GEN
        !          2408: polred(GEN x, long prec)
        !          2409: {
        !          2410:   return allpolred(x,(GEN*)0,0,prec);
        !          2411: }
        !          2412:
        !          2413: GEN
        !          2414: polredfirstpol(GEN x, long prec, int (*check)(GEN,GEN), GEN arg)
        !          2415: {
        !          2416:   return allpolred0(x,(GEN*)0,0,prec,check,arg);
        !          2417: }
        !          2418:
        !          2419: GEN
        !          2420: smallpolred(GEN x, long prec)
        !          2421: {
        !          2422:   return allpolred(x,(GEN*)0,1,prec);
        !          2423: }
        !          2424:
        !          2425: GEN
        !          2426: factoredpolred(GEN x, GEN p, long prec)
        !          2427: {
        !          2428:   return allpolred(x,(GEN*)0,(long)p,prec);
        !          2429: }
        !          2430:
        !          2431: GEN
        !          2432: polred2(GEN x, long prec)
        !          2433: {
        !          2434:   GEN y=cgetg(3,t_MAT);
        !          2435:
        !          2436:   y[2]= (long) allpolred(x,(GEN*)(y+1),0,prec);
        !          2437:   return y;
        !          2438: }
        !          2439:
        !          2440: GEN
        !          2441: smallpolred2(GEN x, long prec)
        !          2442: {
        !          2443:   GEN y=cgetg(3,t_MAT);
        !          2444:
        !          2445:   y[2]= (long) allpolred(x,(GEN*)(y+1),1,prec);
        !          2446:   return y;
        !          2447: }
        !          2448:
        !          2449: GEN
        !          2450: factoredpolred2(GEN x, GEN p, long prec)
        !          2451: {
        !          2452:   GEN y=cgetg(3,t_MAT);
        !          2453:
        !          2454:   y[2]= (long) allpolred(x,(GEN*)(y+1),(long)p,prec);
        !          2455:   return y;
        !          2456: }
        !          2457:
        !          2458: /* relative polredabs. Returns
        !          2459:  * flag = 0: relative polynomial
        !          2460:  * flag = 1: relative polynomial + element
        !          2461:  * flag = 2: absolute polynomial */
        !          2462: GEN
        !          2463: rnfpolredabs(GEN nf, GEN relpol, long flag, long prec)
        !          2464: {
        !          2465:   GEN p1,bpol,rnf,elt,pol;
        !          2466:   long va, av = avma;
        !          2467:
        !          2468:   if (typ(relpol)!=t_POL) err(typeer,"rnfpolredabs");
        !          2469:   nf=checknf(nf); va = varn(relpol);
        !          2470:   if (DEBUGLEVEL>1) timer2();
        !          2471:   p1 = makebasis(nf, unifpol(nf,relpol,1));
        !          2472:   rnf = (GEN)p1[3];
        !          2473:   if (DEBUGLEVEL>1)
        !          2474:   {
        !          2475:     msgtimer("absolute basis");
        !          2476:     fprintferr("original absolute generator: %Z\n",p1[1]);
        !          2477:   }
        !          2478:   p1 = polredabs0(p1, nf_RAW | nf_NORED, prec);
        !          2479:   bpol = (GEN)p1[1];
        !          2480:   if (DEBUGLEVEL>1) fprintferr("reduced absolute generator: %Z\n",bpol);
        !          2481:   if (flag==2) return gerepileupto(av,bpol);
        !          2482:
        !          2483:   elt = rnfelementabstorel(rnf,(GEN)p1[2]);
        !          2484:   p1=cgetg(3,t_VEC);
        !          2485:   pol = rnfcharpoly(nf,relpol,elt,va);
        !          2486:   if (!flag) p1 = pol;
        !          2487:   else
        !          2488:   {
        !          2489:     p1[1]=(long)pol;
        !          2490:     p1[2]=(long)polymodrecip(elt);
        !          2491:   }
        !          2492:   return gerepileupto(av,p1);
        !          2493: }
        !          2494:
        !          2495: /********************************************************************/
        !          2496: /**                                                                **/
        !          2497: /**                              MINIM                             **/
        !          2498: /**                                                                **/
        !          2499: /********************************************************************/
        !          2500: int addcolumntomatrix(GEN V,GEN INVP,GEN L);
        !          2501:
        !          2502: /* x is a non-empty matrix, y is a compatible VECSMALL (dimension > 0). */
        !          2503: GEN
        !          2504: gmul_mat_smallvec(GEN x, GEN y)
        !          2505: {
        !          2506:   long c = lg(x), l = lg(x[1]), av,i,j;
        !          2507:   GEN z=cgetg(l,t_COL), s;
        !          2508:
        !          2509:   for (i=1; i<l; i++)
        !          2510:   {
        !          2511:     av = avma; s = gmulgs(gcoeff(x,i,1),y[1]);
        !          2512:     for (j=2; j<c; j++)
        !          2513:        if (y[j]) s = gadd(s, gmulgs(gcoeff(x,i,j),y[j]));
        !          2514:     z[i] = lpileupto(av,s);
        !          2515:   }
        !          2516:   return z;
        !          2517: }
        !          2518:
        !          2519: /* same, x integral */
        !          2520: GEN
        !          2521: gmul_mati_smallvec(GEN x, GEN y)
        !          2522: {
        !          2523:   long c = lg(x), l = lg(x[1]), av,i,j;
        !          2524:   GEN z=cgetg(l,t_COL), s;
        !          2525:
        !          2526:   for (i=1; i<l; i++)
        !          2527:   {
        !          2528:     av = avma; s = mulis(gcoeff(x,i,1),y[1]);
        !          2529:     for (j=2; j<c; j++)
        !          2530:       if (y[j]) s = addii(s, mulis(gcoeff(x,i,j),y[j]));
        !          2531:     z[i]=(long)gerepileuptoint(av,s);
        !          2532:   }
        !          2533:   return z;
        !          2534: }
        !          2535:
        !          2536: void
        !          2537: minim_alloc(long n, double ***q, GEN *x, double **y,  double **z, double **v)
        !          2538: {
        !          2539:   long i, s;
        !          2540:   double **Q;
        !          2541:
        !          2542:   *x = cgetg(n, t_VECSMALL);
        !          2543:   *q = (double**) new_chunk(n);
        !          2544:
        !          2545:   /* correct alignment for the following */
        !          2546:   s = avma % sizeof(double); avma -= s;
        !          2547:   if (avma<bot) err(errpile);
        !          2548:
        !          2549:   s = (n * sizeof(double))/sizeof(long);
        !          2550:   *y = (double*) new_chunk(s);
        !          2551:   *z = (double*) new_chunk(s);
        !          2552:   *v = (double*) new_chunk(s); Q = *q;
        !          2553:   for (i=1; i<n; i++) Q[i] = (double*) new_chunk(s);
        !          2554: }
        !          2555:
        !          2556: /* Minimal vectors for the integral definite quadratic form: a.
        !          2557:  * Result u:
        !          2558:  *   u[1]= Number of vectors of square norm <= BORNE
        !          2559:  *   u[2]= maximum norm found
        !          2560:  *   u[3]= list of vectors found (at most STOCKMAX)
        !          2561:  *
        !          2562:  *  If BORNE = gzero: Minimal non-zero vectors.
        !          2563:  *  flag = min_ALL,   as above
        !          2564:  *  flag = min_FIRST, exits when first suitable vector is found.
        !          2565:  *  flag = min_PERF,  only compute rank of the family of v.v~ (v min.)
        !          2566:  */
        !          2567: static GEN
        !          2568: minim00(GEN a, GEN BORNE, GEN STOCKMAX, long flag)
        !          2569: {
        !          2570:   GEN x,res,p1,u,r,liste,gnorme,invp,V, *gptr[2];
        !          2571:   long n = lg(a), av0 = avma, av1,av,tetpil,lim, i,j,k,s,maxrank;
        !          2572:   double p,maxnorm,BOUND,*v,*y,*z,**q, eps = 0.000001;
        !          2573:
        !          2574:   maxrank = 0; res = V = invp = NULL; /* gcc -Wall */
        !          2575:   switch(flag)
        !          2576:   {
        !          2577:     case min_FIRST:
        !          2578:       if (gcmp0(BORNE)) err(talker,"bound = 0 in minim2");
        !          2579:       res = cgetg(3,t_VEC); break;
        !          2580:     case min_ALL: res = cgetg(4,t_VEC); break;
        !          2581:     case min_PERF: break;
        !          2582:     default: err(talker, "incorrect flag in minim00");
        !          2583:   }
        !          2584:   if (n == 1)
        !          2585:   {
        !          2586:     switch(flag)
        !          2587:     {
        !          2588:       case min_FIRST: avma=av0; return cgetg(1,t_VEC);
        !          2589:       case min_PERF:  avma=av0; return gzero;
        !          2590:     }
        !          2591:     res[1]=res[2]=zero;
        !          2592:     res[3]=lgetg(1,t_MAT); return res;
        !          2593:   }
        !          2594:
        !          2595:   av = avma;
        !          2596:   minim_alloc(n, &q, &x, &y, &z, &v);
        !          2597:   av1 = avma;
        !          2598:
        !          2599:   u = lllgramint(a);
        !          2600:   if (lg(u) != n)
        !          2601:     err(talker,"not a definite form in minim00");
        !          2602:   a = qf_base_change(a,u,1);
        !          2603:
        !          2604:   n--;
        !          2605:   a = gmul(a, realun(DEFAULTPREC)); r = sqred1(a);
        !          2606:   if (DEBUGLEVEL>4) { fprintferr("minim: r = "); outerr(r); }
        !          2607:   for (j=1; j<=n; j++)
        !          2608:   {
        !          2609:     v[j] = rtodbl(gcoeff(r,j,j));
        !          2610:     for (i=1; i<j; i++) q[i][j] = rtodbl(gcoeff(r,i,j));
        !          2611:   }
        !          2612:
        !          2613:   if (flag==min_PERF || gcmp0(BORNE))
        !          2614:   {
        !          2615:     double c, b = rtodbl(gcoeff(a,1,1));
        !          2616:
        !          2617:     for (i=2; i<=n; i++)
        !          2618:       { c=rtodbl(gcoeff(a,i,i)); if (c<b) b=c; }
        !          2619:     BOUND = b+eps;
        !          2620:     BORNE = ground(dbltor(BOUND));
        !          2621:     maxnorm = -1.; /* don't update maxnorm */
        !          2622:   }
        !          2623:   else
        !          2624:   {
        !          2625:     BORNE = gfloor(BORNE);
        !          2626:     BOUND = gtodouble(BORNE)+eps;
        !          2627:     maxnorm = 0.;
        !          2628:   }
        !          2629:
        !          2630:   switch(flag)
        !          2631:   {
        !          2632:     case min_ALL:
        !          2633:       maxrank=itos(STOCKMAX);
        !          2634:       liste = new_chunk(1+maxrank);
        !          2635:       break;
        !          2636:     case min_PERF:
        !          2637:       BORNE = gerepileupto(av1,BORNE);
        !          2638:       maxrank = (n*(n+1))>>1;
        !          2639:       liste = cgetg(1+maxrank, t_VECSMALL);
        !          2640:       V     = cgetg(1+maxrank, t_VECSMALL);
        !          2641:       for (i=1; i<=maxrank; i++) liste[i]=0;
        !          2642:   }
        !          2643:
        !          2644:   s=0; av1=avma; lim = stack_lim(av1,1);
        !          2645:   k = n; y[n] = z[n] = 0;
        !          2646:   x[n] = (long) sqrt(BOUND/v[n]);
        !          2647:   if (flag == min_PERF) invp = idmat(maxrank);
        !          2648:   for(;;x[1]--)
        !          2649:   {
        !          2650:     do
        !          2651:     {
        !          2652:       if (k>1)
        !          2653:       {
        !          2654:         long l = k-1;
        !          2655:        z[l]=0;
        !          2656:        for (j=k; j<=n; j++) z[l] += q[l][j]*x[j];
        !          2657:        p = x[k]+z[k];
        !          2658:        y[l] = y[k] + p*p*v[k];
        !          2659:        x[l] = (long) floor(sqrt((BOUND-y[l])/v[l])-z[l]);
        !          2660:         k = l;
        !          2661:       }
        !          2662:       for(;;)
        !          2663:       {
        !          2664:        p = x[k]+z[k];
        !          2665:        if (y[k] + p*p*v[k] <= BOUND) break;
        !          2666:        k++; x[k]--;
        !          2667:       }
        !          2668:     }
        !          2669:     while (k>1);
        !          2670:     if (! x[1] && y[1]<=eps) break;
        !          2671:     p = x[1]+z[1]; p = y[1] + p*p*v[1]; /* norm(x) */
        !          2672:     if (maxnorm >= 0)
        !          2673:     {
        !          2674:       if (flag == min_FIRST)
        !          2675:       {
        !          2676:         gnorme = dbltor(p);
        !          2677:         tetpil=avma; gnorme = ground(gnorme); r = gmul_mati_smallvec(u,x);
        !          2678:         gptr[0]=&gnorme; gptr[1]=&r; gerepilemanysp(av,tetpil,gptr,2);
        !          2679:         res[1]=(long)gnorme;
        !          2680:         res[2]=(long)r; return res;
        !          2681:       }
        !          2682:       if (p > maxnorm) maxnorm = p;
        !          2683:     }
        !          2684:     else
        !          2685:     {
        !          2686:       long av2 = avma;
        !          2687:       gnorme = ground(dbltor(p));
        !          2688:       if (gcmp(gnorme,BORNE) >= 0) avma = av2;
        !          2689:       else
        !          2690:       {
        !          2691:         BOUND=gtodouble(gnorme)+eps; s=0;
        !          2692:         affii(gnorme,BORNE); avma=av1;
        !          2693:         if (flag == min_PERF) invp = idmat(maxrank);
        !          2694:       }
        !          2695:     }
        !          2696:     s++;
        !          2697:
        !          2698:     switch(flag)
        !          2699:     {
        !          2700:       case min_ALL:
        !          2701:         if (s<=maxrank)
        !          2702:         {
        !          2703:           p1 = new_chunk(n+1); liste[s] = (long) p1;
        !          2704:           for (i=1; i<=n; i++) p1[i] = x[i];
        !          2705:         }
        !          2706:         break;
        !          2707:
        !          2708:       case min_PERF:
        !          2709:       {
        !          2710:         long av2=avma, I=1;
        !          2711:
        !          2712:         for (i=1; i<=n; i++)
        !          2713:           for (j=i; j<=n; j++,I++) V[I] = x[i]*x[j];
        !          2714:         if (! addcolumntomatrix(V,invp,liste))
        !          2715:         {
        !          2716:           if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
        !          2717:           s--; avma=av2; continue;
        !          2718:         }
        !          2719:
        !          2720:         if (DEBUGLEVEL>1) { fprintferr("*"); flusherr(); }
        !          2721:         if (s == maxrank)
        !          2722:         {
        !          2723:           if (DEBUGLEVEL>1) { fprintferr("\n"); flusherr(); }
        !          2724:           avma=av0; return stoi(s);
        !          2725:         }
        !          2726:
        !          2727:         if (low_stack(lim, stack_lim(av1,1)))
        !          2728:         {
        !          2729:           if(DEBUGMEM>1) err(warnmem,"minim00, rank>=%ld",s);
        !          2730:           invp = gerepilecopy(av1, invp);
        !          2731:         }
        !          2732:       }
        !          2733:     }
        !          2734:   }
        !          2735:   switch(flag)
        !          2736:   {
        !          2737:     case min_FIRST:
        !          2738:       avma=av0; return cgetg(1,t_VEC);
        !          2739:     case min_PERF:
        !          2740:       if (DEBUGLEVEL>1) { fprintferr("\n"); flusherr(); }
        !          2741:       avma=av0; return stoi(s);
        !          2742:   }
        !          2743:   k = min(s,maxrank);
        !          2744:
        !          2745:   tetpil = avma; p1=cgetg(k+1,t_MAT);
        !          2746:   for (j=1; j<=k; j++)
        !          2747:     p1[j] = (long) gmul_mati_smallvec(u,(GEN)liste[j]);
        !          2748:   liste = p1;
        !          2749:   r = (maxnorm >= 0) ? ground(dbltor(maxnorm)): BORNE;
        !          2750:
        !          2751:   r=icopy(r); gptr[0]=&r; gptr[1]=&liste;
        !          2752:   gerepilemanysp(av,tetpil,gptr,2);
        !          2753:   res[1]=lstoi(s<<1);
        !          2754:   res[2]=(long)r;
        !          2755:   res[3]=(long)liste; return res;
        !          2756: }
        !          2757:
        !          2758: GEN
        !          2759: qfminim0(GEN a, GEN borne, GEN stockmax, long flag, long prec)
        !          2760: {
        !          2761:   switch(flag)
        !          2762:   {
        !          2763:     case 0: return minim00(a,borne,stockmax,min_ALL);
        !          2764:     case 1: return minim00(a,borne,gzero   ,min_FIRST);
        !          2765:     case 2: return fincke_pohst(a,borne,itos(stockmax),0,prec,NULL);
        !          2766:     default: err(flagerr,"qfminim");
        !          2767:   }
        !          2768:   return NULL; /* not reached */
        !          2769: }
        !          2770:
        !          2771: GEN
        !          2772: minim(GEN a, GEN borne, GEN stockmax)
        !          2773: {
        !          2774:   return minim00(a,borne,stockmax,min_ALL);
        !          2775: }
        !          2776:
        !          2777: GEN
        !          2778: minim2(GEN a, GEN borne, GEN stockmax)
        !          2779: {
        !          2780:   return minim00(a,borne,stockmax,min_FIRST);
        !          2781: }
        !          2782:
        !          2783: GEN
        !          2784: perf(GEN a)
        !          2785: {
        !          2786:   return minim00(a,gzero,gzero,min_PERF);
        !          2787: }
        !          2788:
        !          2789: /* general program for positive definit quadratic forms (real coeffs).
        !          2790:  * One needs BORNE != 0; LLL reduction done in fincke_pohst().
        !          2791:  * If (flag & 2) stop as soon as stockmax is reached.
        !          2792:  * If (flag & 1) return NULL on precision problems (no error).
        !          2793:  * If (check != NULL consider only vectors passing the check [ assumes
        !          2794:  *   stockmax > 0 and we only want the smallest possible vectors ] */
        !          2795: static GEN
        !          2796: smallvectors(GEN a, GEN BORNE, long stockmax, long flag, FP_chk_fun *CHECK)
        !          2797: {
        !          2798:   long av,av1,lim,N,n,i,j,k,s,epsbit,prec, checkcnt = 1;
        !          2799:   GEN u,S,x,y,z,v,q,norme1,normax1,borne1,borne2,eps,p1,alpha,norms,dummy;
        !          2800:   GEN (*check)(GEN,GEN) = CHECK? CHECK->f: NULL;
        !          2801:   GEN data = CHECK? CHECK->data: NULL;
        !          2802:   int skipfirst = CHECK? CHECK->skipfirst: 0;
        !          2803:
        !          2804:   if (DEBUGLEVEL)
        !          2805:     fprintferr("smallvectors looking for norm <= %Z\n",gprec_w(BORNE,3));
        !          2806:
        !          2807:   q = sqred1intern(a,flag&1);
        !          2808:   if (q == NULL) return NULL;
        !          2809:   if (DEBUGLEVEL>5) fprintferr("q = %Z",q);
        !          2810:   prec = gprecision(q);
        !          2811:   epsbit = bit_accuracy(prec) >> 1;
        !          2812:   eps = realun(prec); setexpo(eps,-epsbit);
        !          2813:   alpha = dbltor(0.95);
        !          2814:   normax1 = gzero;
        !          2815:   borne1= gadd(BORNE,eps);
        !          2816:   borne2 = mpmul(borne1,alpha);
        !          2817:   N = lg(q); n = N-1;
        !          2818:   v = cgetg(N,t_VEC);
        !          2819:   dummy = cgetg(1,t_STR);
        !          2820:
        !          2821:   av = avma; lim = stack_lim(av,1);
        !          2822:   if (check) norms = cgetg(stockmax+1,t_VEC);
        !          2823:   S = cgetg(stockmax+1,t_VEC);
        !          2824:   x = cgetg(N,t_COL);
        !          2825:   y = cgetg(N,t_COL);
        !          2826:   z = cgetg(N,t_COL);
        !          2827:   for (i=1; i<N; i++) { v[i] = coeff(q,i,i); x[i]=y[i]=z[i] = zero; }
        !          2828:
        !          2829:   x[n] = lmpent(mpsqrt(gdiv(borne1,(GEN)v[n])));
        !          2830:   if (DEBUGLEVEL>3) { fprintferr("\nx[%ld] = %Z\n",n,x[n]); flusherr(); }
        !          2831:
        !          2832:   s = 0; k = n;
        !          2833:   for(;; x[k] = laddis((GEN)x[k],-1)) /* main */
        !          2834:   {
        !          2835:     do
        !          2836:     {
        !          2837:       int fl = 0;
        !          2838:       if (k > 1)
        !          2839:       {
        !          2840:         av1=avma; k--; p1 = mpmul(gcoeff(q,k,k+1),(GEN)x[k+1]);
        !          2841:        for (j=k+2; j<N; j++)
        !          2842:          p1 = mpadd(p1, mpmul(gcoeff(q,k,j),(GEN)x[j]));
        !          2843:         z[k] = (long)gerepileuptoleaf(av1,p1);
        !          2844:
        !          2845:         av1=avma; p1 = gsqr(mpadd((GEN)x[k+1],(GEN)z[k+1]));
        !          2846:         p1 = mpadd((GEN)y[k+1], mpmul(p1,(GEN)v[k+1]));
        !          2847:        y[k] = (long)gerepileuptoleaf(av1, p1);
        !          2848:
        !          2849:         av1=avma; p1 = mpsub(borne1, (GEN)y[k]);
        !          2850:        if (signe(p1) < 0) { avma=av1; fl = 1; }
        !          2851:         else
        !          2852:         {
        !          2853:           p1 = mpadd(eps,mpsub(mpsqrt(gdiv(p1,(GEN)v[k])), (GEN)z[k]));
        !          2854:           x[k] = (long)gerepileuptoleaf(av1,mpent(p1));
        !          2855:         }
        !          2856:         /* reject the [x_1,...,x_skipfirst,0,...,0] */
        !          2857:         if (k <= skipfirst && !signe(y[skipfirst])) goto END;
        !          2858:       }
        !          2859:       for(;; x[k] = laddis((GEN)x[k],-1))
        !          2860:       {
        !          2861:        if (!fl)
        !          2862:        {
        !          2863:           av1 = avma; /* p1 >= 0 */
        !          2864:          p1 = mpmul((GEN)v[k], gsqr(mpadd((GEN)x[k],(GEN)z[k])));
        !          2865:          i = mpcmp(mpsub(mpadd(p1,(GEN)y[k]), borne1), gmul2n(p1,-epsbit));
        !          2866:           avma = av1; if (i <= 0) break;
        !          2867:        }
        !          2868:         k++; fl=0;
        !          2869:       }
        !          2870:
        !          2871:       if (low_stack(lim, stack_lim(av,1)))
        !          2872:       {
        !          2873:        GEN *gptr[7];
        !          2874:         int cnt = 4;
        !          2875:        if(DEBUGMEM>1) err(warnmem,"smallvectors");
        !          2876:        gptr[0]=&x; gptr[1]=&y; gptr[2]=&z; gptr[3]=&normax1;
        !          2877:        if (stockmax)
        !          2878:         { /* initialize to dummy values */
        !          2879:           GEN T = S;
        !          2880:           for (i=s+1; i<=stockmax; i++) S[i]=(long)dummy;
        !          2881:           S = gclone(S); if (isclone(T)) gunclone(T);
        !          2882:         }
        !          2883:         if (check)
        !          2884:         {
        !          2885:           cnt+=3; gptr[4]=&borne1; gptr[5]=&borne2; gptr[6]=&norms;
        !          2886:           for (i=s+1; i<=stockmax; i++) norms[i]=(long)dummy;
        !          2887:         }
        !          2888:        gerepilemany(av,gptr,cnt);
        !          2889:       }
        !          2890:       if (DEBUGLEVEL>3)
        !          2891:       {
        !          2892:        if (DEBUGLEVEL>5) fprintferr("%ld ",k);
        !          2893:        if (k==n) fprintferr("\nx[%ld] = %Z\n",n,x[n]);
        !          2894:        flusherr();
        !          2895:       }
        !          2896:     }
        !          2897:     while (k > 1);
        !          2898:
        !          2899:     /* x = 0: we're done */
        !          2900:     if (!signe(x[1]) && !signe(y[1])) goto END;
        !          2901:
        !          2902:     av1=avma; p1 = gsqr(mpadd((GEN)x[1],(GEN)z[1]));
        !          2903:     norme1 = mpadd((GEN)y[1], mpmul(p1, (GEN)v[1]));
        !          2904:     if (mpcmp(norme1,borne1) > 0) { avma=av1; continue; /* main */ }
        !          2905:
        !          2906:     norme1 = gerepileupto(av1,norme1);
        !          2907:     if (check)
        !          2908:     {
        !          2909:       if (checkcnt < 5 && mpcmp(norme1, borne2) < 0)
        !          2910:       {
        !          2911:         if (check(data,x))
        !          2912:         {
        !          2913:           borne1 = mpadd(norme1,eps);
        !          2914:           borne2 = mpmul(borne1,alpha);
        !          2915:           s = 0; checkcnt = 0;
        !          2916:         }
        !          2917:         else { checkcnt++ ; continue; /* main */}
        !          2918:       }
        !          2919:     }
        !          2920:     else if (mpcmp(norme1,normax1) > 0) normax1 = norme1;
        !          2921:     if (++s <= stockmax)
        !          2922:     {
        !          2923:       if (check) norms[s] = (long)norme1;
        !          2924:       S[s] = (long)dummycopy(x);
        !          2925:       if (s == stockmax && (flag&2) && check)
        !          2926:       {
        !          2927:         long av1 = avma;
        !          2928:         GEN per = sindexsort(norms);
        !          2929:         if (DEBUGLEVEL) fprintferr("sorting...\n");
        !          2930:         for (i=1; i<=s; i++)
        !          2931:         {
        !          2932:           long k = per[i];
        !          2933:           if (check(data,(GEN)S[k]))
        !          2934:           {
        !          2935:             S[1] = S[k]; avma = av1;
        !          2936:             borne1 = mpadd(norme1,eps);
        !          2937:             borne2 = mpmul(borne1,alpha);
        !          2938:             s = 1; checkcnt = 0; break;
        !          2939:           }
        !          2940:         }
        !          2941:         if (checkcnt) s = 0;
        !          2942:       }
        !          2943:     }
        !          2944:   }
        !          2945: END:
        !          2946:   if (s < stockmax) stockmax = s;
        !          2947:   if (check)
        !          2948:   {
        !          2949:     GEN per, alph,pols,p;
        !          2950:     if (DEBUGLEVEL) fprintferr("final sort & check...\n");
        !          2951:     setlg(norms,s+1); per = sindexsort(norms);
        !          2952:     alph = cgetg(s+1,t_VEC);
        !          2953:     pols = cgetg(s+1,t_VEC);
        !          2954:     for (j=0,i=1; i<=s; i++)
        !          2955:     {
        !          2956:       long k = per[i];
        !          2957:       if (j && mpcmp((GEN)norms[k], borne1) > 0) break;
        !          2958:       if ((p = check(data,(GEN)S[k])))
        !          2959:       {
        !          2960:         if (!j) borne1 = gadd((GEN)norms[k],eps);
        !          2961:         j++; pols[j]=(long)p; alph[j]=S[k];
        !          2962:       }
        !          2963:     }
        !          2964:     u = cgetg(3,t_VEC);
        !          2965:     setlg(pols,j+1); u[1] = (long)pols;
        !          2966:     setlg(alph,j+1); u[2] = (long)alph;
        !          2967:     if (isclone(S)) { u[2] = (long)forcecopy(alph); gunclone(S); }
        !          2968:     return u;
        !          2969:   }
        !          2970:   u = cgetg(4,t_VEC);
        !          2971:   u[1] = lstoi(s<<1);
        !          2972:   u[2] = (long)normax1;
        !          2973:   if (stockmax)
        !          2974:   {
        !          2975:     setlg(S,stockmax+1);
        !          2976:     settyp(S,t_MAT);
        !          2977:     if (isclone(S)) { p1 = S; S = forcecopy(S); gunclone(p1); }
        !          2978:   }
        !          2979:   else
        !          2980:     S = cgetg(1,t_MAT);
        !          2981:   u[3] = (long)S; return u;
        !          2982: }
        !          2983:
        !          2984: /* solve x~.a.x <= bound, a > 0. If check is non-NULL keep x only if check(x).
        !          2985:  * flag & 1, return NULL in case of precision problems (sqred1 or lllgram)
        !          2986:  *   raise an error otherwise.
        !          2987:  * flag & 2, return as soon as stockmax vectors found.
        !          2988:  * If a is a number field, use its T2 matrix
        !          2989:  */
        !          2990: GEN
        !          2991: fincke_pohst(GEN a,GEN B0,long stockmax,long flag, long PREC, FP_chk_fun *CHECK)
        !          2992: {
        !          2993:   VOLATILE long pr,av=avma,i,j,n;
        !          2994:   VOLATILE GEN B,nf,r,rinvtrans,u,v,res,z,vnorm,sperm,perm,uperm,gram;
        !          2995:   VOLATILE GEN bound = B0;
        !          2996:   void *catcherr = NULL;
        !          2997:   long prec = PREC;
        !          2998:
        !          2999:   if (DEBUGLEVEL>2) { fprintferr("entering fincke_pohst\n"); flusherr(); }
        !          3000:   if (typ(a) == t_VEC) { nf = checknf(a); a = gmael(nf,5,3); } else nf = NULL;
        !          3001:   pr = gprecision(a);
        !          3002:   if (pr) prec = pr; else a = gmul(a,realun(prec));
        !          3003:   if (DEBUGLEVEL>2) fprintferr("first LLL: prec = %ld\n", prec);
        !          3004:   if (nf && !signe(gmael(nf,2,2))) /* totally real */
        !          3005:   {
        !          3006:     GEN T = nf_get_T((GEN)nf[1], (GEN)nf[7]);
        !          3007:     u = lllgramint(T);
        !          3008:     prec += 2 * ((gexpo(u) + gexpo((GEN)nf[1])) >> TWOPOTBITS_IN_LONG);
        !          3009:     nf = nfnewprec(nf, prec);
        !          3010:     r = qf_base_change(T,u,1);
        !          3011:     i = PREC + (gexpo(r) >> TWOPOTBITS_IN_LONG);
        !          3012:     if (i < prec) prec = i;
        !          3013:     r = gmul(r, realun(prec));
        !          3014:   }
        !          3015:   else
        !          3016:   {
        !          3017:     u = lllgramintern(a,4,flag&1, (prec<<1)-2);
        !          3018:     if (!u) goto PRECPB;
        !          3019:     r = qf_base_change(a,u,1);
        !          3020:   }
        !          3021:   r = sqred1intern(r,flag&1);
        !          3022:   if (!r) goto PRECPB;
        !          3023:
        !          3024:   n = lg(a);
        !          3025:   if (n == 1)
        !          3026:   {
        !          3027:     if (CHECK) err(talker, "dimension 0 in fincke_pohst");
        !          3028:     avma = av; z=cgetg(4,t_VEC);
        !          3029:     z[1]=z[2]=zero;
        !          3030:     z[3]=lgetg(1,t_MAT); return z;
        !          3031:   }
        !          3032:   for (i=1; i<n; i++)
        !          3033:   {
        !          3034:     GEN p1 = gsqrt(gcoeff(r,i,i), prec);
        !          3035:     coeff(r,i,i)=(long)p1;
        !          3036:     for (j=i+1; j<n; j++)
        !          3037:       coeff(r,i,j) = lmul(p1, gcoeff(r,i,j));
        !          3038:   }
        !          3039:   /* now r~ * r = a in approximate LLL basis */
        !          3040:   rinvtrans = gtrans(invmat(r));
        !          3041:
        !          3042:   v = NULL;
        !          3043:   for (i=1; i<6; i++) /* try to get close to a genuine LLL basis */
        !          3044:   {
        !          3045:     GEN p1;
        !          3046:     if (DEBUGLEVEL>2)
        !          3047:       fprintferr("final LLLs: prec = %ld, precision(rinvtrans) = %ld\n",
        !          3048:                   prec,gprecision(rinvtrans));
        !          3049:     p1 = lllintern(rinvtrans,flag&1, (gprecision(rinvtrans)<<1)-2);
        !          3050:     if (!p1) goto PRECPB;
        !          3051:     if (ishnfall(p1)) break; /* upper triangular */
        !          3052:     if (v) v = gmul(v,p1); else v = p1;
        !          3053:     rinvtrans = gmul(rinvtrans,p1);
        !          3054:   }
        !          3055:   if (i == 6) goto PRECPB; /* diverges... */
        !          3056:
        !          3057:   if (v)
        !          3058:   {
        !          3059:     GEN u2 = ZM_inv(gtrans(v),gun);
        !          3060:     r = gmul(r,u2); /* r = LLL basis now */
        !          3061:     u = gmul(u,u2);
        !          3062:   }
        !          3063:
        !          3064:   vnorm = cgetg(n,t_VEC);
        !          3065:   for (j=1; j<n; j++) vnorm[j] = lnorml2((GEN)rinvtrans[j]);
        !          3066:   sperm = cgetg(n,t_MAT);
        !          3067:   uperm = cgetg(n,t_MAT); perm = sindexsort(vnorm);
        !          3068:   for (i=1; i<n; i++) { uperm[n-i] = u[perm[i]]; sperm[n-i] = r[perm[i]]; }
        !          3069:
        !          3070:   gram = gram_matrix(sperm);
        !          3071:   B = gcoeff(gram,n-1,n-1);
        !          3072:   if (gexpo(B) >= bit_accuracy(lg(B)-2)) goto PRECPB;
        !          3073:
        !          3074:   { /* catch precision problems (truncation error) */
        !          3075:     jmp_buf env;
        !          3076:     if (setjmp(env)) goto PRECPB;
        !          3077:     catcherr = err_catch(precer, env, NULL);
        !          3078:   }
        !          3079:   if (CHECK && CHECK->f_init)
        !          3080:   {
        !          3081:     bound = CHECK->f_init(CHECK,nf,gram,uperm, &prec);
        !          3082:     if (!bound) goto PRECPB;
        !          3083:   }
        !          3084:   if (!bound)
        !          3085:   { /* set bound */
        !          3086:     GEN x = cgetg(n,t_COL);
        !          3087:     if (nf) bound = get_Bnf(nf);
        !          3088:     for (i=2; i<n; i++) x[i]=zero;
        !          3089:     for (i=1; i<n; i++)
        !          3090:     {
        !          3091:       x[i] = un; B = gcoeff(gram,i,i);
        !          3092:       if (!bound || mpcmp(B,bound) < 0) bound = B;
        !          3093:       x[i] = zero;
        !          3094:     }
        !          3095:   }
        !          3096:
        !          3097:   if (DEBUGLEVEL>2) {fprintferr("entering smallvectors\n"); flusherr();}
        !          3098:   for (i=1; i<n; i++)
        !          3099:   {
        !          3100:     res = smallvectors(gram, bound? bound: gcoeff(gram,i,i),
        !          3101:                        stockmax,flag,CHECK);
        !          3102:     if (!res) goto PRECPB;
        !          3103:     if (!CHECK || bound || lg(res[2]) > 1) break;
        !          3104:     if (DEBUGLEVEL>2) fprintferr("  i = %ld failed\n",i);
        !          3105:   }
        !          3106:   err_leave(&catcherr); catcherr = NULL;
        !          3107:   if (CHECK)
        !          3108:   {
        !          3109:     if (CHECK->f_post) res = CHECK->f_post(CHECK->data, res);
        !          3110:     return res;
        !          3111:   }
        !          3112:
        !          3113:   if (DEBUGLEVEL>2) {fprintferr("leaving fincke_pohst\n"); flusherr();}
        !          3114:   z=cgetg(4,t_VEC);
        !          3115:   z[1]=lcopy((GEN)res[1]);
        !          3116:   z[2]=pr? lcopy((GEN)res[2]) : lround((GEN)res[2]);
        !          3117:   z[3]=lmul(uperm, (GEN)res[3]); return gerepileupto(av,z);
        !          3118: PRECPB:
        !          3119:   if (catcherr) err_leave(&catcherr);
        !          3120:   if (!(flag & 1))
        !          3121:     err(talker,"not a positive definite form in fincke_pohst");
        !          3122:   avma = av; return NULL;
        !          3123: }

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