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] = ∣
! 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>