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