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