Annotation of OpenXM_contrib/pari/src/basemath/alglin2.c, Revision 1.1
1.1 ! maekawa 1: /********************************************************************/
! 2: /** **/
! 3: /** LINEAR ALGEBRA **/
! 4: /** (second part) **/
! 5: /** **/
! 6: /********************************************************************/
! 7: /* $Id: alglin2.c,v 1.3 1999/09/23 17:50:55 karim Exp $ */
! 8: #include "pari.h"
! 9:
! 10: /*******************************************************************/
! 11: /* */
! 12: /* CHARACTERISTIC POLYNOMIAL */
! 13: /* */
! 14: /*******************************************************************/
! 15:
! 16: GEN
! 17: charpoly0(GEN x, int v, long flag)
! 18: {
! 19: if (v<0) v = 0;
! 20: switch(flag)
! 21: {
! 22: case 0: return caradj(x,v,0);
! 23: case 1: return caract(x,v);
! 24: case 2: return carhess(x,v);
! 25: }
! 26: err(flagerr,"charpoly"); return NULL; /* not reached */
! 27: }
! 28:
! 29:
! 30: static GEN
! 31: caract2_i(GEN p, GEN x, int v, GEN (subres_f)(GEN,GEN,GEN*))
! 32: {
! 33: long av = avma, d;
! 34: GEN p1, p2 = leading_term(p);
! 35:
! 36: if (!signe(x)) return gpowgs(polx[v], lgef(p)-3);
! 37: x = gneg_i(x); x[2] = ladd((GEN)x[2], polx[MAXVARN]);
! 38: p1=subres_f(p, x, NULL);
! 39: if (varn(p1)==MAXVARN) setvarn(p1,v); else p1=gsubst(p1,MAXVARN,polx[v]);
! 40:
! 41: if (!gcmp1(p2) && (d=lgef(x)-3) > 0) p1 = gdiv(p1, gpuigs(p2,d));
! 42: return gerepileupto(av,p1);
! 43: }
! 44:
! 45: /* return caract(Mod(x,p)) in variable v */
! 46: GEN
! 47: caract2(GEN p, GEN x, int v)
! 48: {
! 49: return caract2_i(p,x,v, subresall);
! 50: }
! 51: GEN
! 52: caractducos(GEN p, GEN x, int v)
! 53: {
! 54: return caract2_i(p,x,v, (GEN (*)(GEN,GEN,GEN*))resultantducos);
! 55: }
! 56:
! 57: /* characteristic pol. Easy cases. Return NULL in case it's not so easy. */
! 58: static GEN
! 59: easychar(GEN x, int v, GEN *py)
! 60: {
! 61: long l,tetpil,lx;
! 62: GEN p1,p2;
! 63:
! 64: switch(typ(x))
! 65: {
! 66: case t_INT: case t_REAL: case t_INTMOD:
! 67: case t_FRAC: case t_FRACN: case t_PADIC:
! 68: p1=cgetg(4,t_POL);
! 69: p1[1]=evalsigne(1) | evallgef(4) | evalvarn(v);
! 70: p1[2]=lneg(x); p1[3]=un;
! 71: if (py)
! 72: {
! 73: p2=cgetg(2,t_MAT);
! 74: p2[1]=lgetg(2,t_COL);
! 75: coeff(p2,1,1)=lcopy(x);
! 76: *py=p2;
! 77: }
! 78: return p1;
! 79:
! 80: case t_COMPLEX: case t_QUAD:
! 81: if (py) err(typeer,"easychar");
! 82: p1=cgetg(5,t_POL);
! 83: p1[1]=evalsigne(1) | evallgef(5) | evalvarn(v);
! 84: p1[2]=lnorm(x); l=avma; p2=gtrace(x); tetpil=avma;
! 85: p1[3]=lpile(l,tetpil,gneg(p2));
! 86: p1[4]=un; return p1;
! 87:
! 88: case t_POLMOD:
! 89: if (py) err(typeer,"easychar");
! 90: return caract2((GEN)x[1], (GEN)x[2], v);
! 91:
! 92: case t_MAT:
! 93: lx=lg(x);
! 94: if (lx==1)
! 95: {
! 96: if (py) *py = cgetg(1,t_MAT);
! 97: return polun[v];
! 98: }
! 99: if (lg(x[1]) != lx) break;
! 100: return NULL;
! 101: }
! 102: err(mattype1,"easychar");
! 103: return NULL; /* not reached */
! 104: }
! 105:
! 106: GEN
! 107: caract(GEN x, int v)
! 108: {
! 109: long n,k,l=avma,tetpil;
! 110: GEN p1,p2,p3,p4,p5,p6;
! 111:
! 112: if ((p1 = easychar(x,v,NULL))) return p1;
! 113:
! 114: p1=gzero; p2=gun;
! 115: n=lg(x)-1; if (n&1) p2=gneg_i(p2);
! 116: p4=cgetg(3,t_RFRACN); p5=dummycopy(polx[v]); p4[2]=(long)p5;
! 117: p6=cgeti(3); p6[1] = evalsigne(-1) | evallgefint(3);
! 118: for (k=0; k<=n; k++)
! 119: {
! 120: p3=det(gsub(gscalmat(stoi(k),n), x));
! 121: p4[1]=lmul(p3,p2); p6[2]=k;
! 122: p1=gadd(p4,p1); p5[2]=(long)p6;
! 123: if (k!=n) p2=gdivgs(gmulsg(k-n,p2),k+1);
! 124: }
! 125: p2=mpfact(n); tetpil=avma;
! 126: return gerepile(l,tetpil,gdiv((GEN) p1[1],p2));
! 127: }
! 128:
! 129: GEN
! 130: caradj0(GEN x, long v)
! 131: {
! 132: return caradj(x,v,NULL);
! 133: }
! 134:
! 135: /* Using traces: return the characteristic polynomial of x (in variable v).
! 136: * If py != NULL, the adjoint matrix is put there.
! 137: */
! 138: GEN
! 139: caradj(GEN x, long v, GEN *py)
! 140: {
! 141: long i,j,k,l,av,tetpil;
! 142: GEN p,y,t,*gptr[2];
! 143:
! 144: if ((p = easychar(x,v,py))) return p;
! 145:
! 146: l=lg(x);
! 147: if (l==1) { p=polun[v]; if (py) *py=gcopy(x); return p; }
! 148: if (l==2) { p=gsub(polx[v],gtrace(x)); if (py) *py=idmat(1); return p; }
! 149:
! 150: p=cgetg(l+2,t_POL); p[1]=evalsigne(1) | evallgef(l+2) | evalvarn(v);
! 151: av=avma; t=gtrace(x); tetpil=avma;
! 152: t=gerepile(av,tetpil,gneg(t));
! 153: p[l]=(long)t; p[l+1]=un;
! 154:
! 155: av=avma; y=cgetg(l,t_MAT);
! 156: for (j=1; j<l; j++)
! 157: {
! 158: y[j]=lgetg(l,t_COL);
! 159: for (i=1; i<l; i++)
! 160: coeff(y,i,j) = (i==j) ? ladd(gcoeff(x,i,j),t) : coeff(x,i,j);
! 161: }
! 162:
! 163: for (k=2; k<l-1; k++)
! 164: {
! 165: GEN z=gmul(x,y);
! 166:
! 167: t=gtrace(z); tetpil=avma;
! 168: t=gdivgs(t,-k); y=cgetg(l,t_MAT);
! 169: for (j=1; j<l; j++)
! 170: {
! 171: y[j]=lgetg(l,t_COL);
! 172: for (i=1;i<l;i++)
! 173: coeff(y,i,j) = (i==j)? ladd(gcoeff(z,i,i),t): lcopy(gcoeff(z,i,j));
! 174: }
! 175: gptr[0]=&y; gptr[1]=&t;
! 176: gerepilemanysp(av,tetpil,gptr,2);
! 177: p[l-k+1]=(long)t; av=avma;
! 178: }
! 179:
! 180: t=gzero;
! 181: for (i=1; i<l; i++)
! 182: t=gadd(t,gmul(gcoeff(x,1,i),gcoeff(y,i,1)));
! 183: tetpil=avma; t=gneg(t);
! 184:
! 185: if (py)
! 186: {
! 187: *py = (l&1) ? gneg(y) : gcopy(y);
! 188: gptr[0] = &t; gptr[1] = py;
! 189: gerepilemanysp(av,tetpil,gptr,2);
! 190: p[2]=(long)t;
! 191: }
! 192: else p[2]=lpile(av,tetpil,t);
! 193: i = gvar2(p);
! 194: if (i == v) err(talker,"incorrect variable in caradj");
! 195: if (i < v) p = poleval(p, polx[v]);
! 196: return p;
! 197: }
! 198:
! 199: GEN
! 200: adj(GEN x)
! 201: {
! 202: GEN y;
! 203: caradj(x,MAXVARN,&y); return y;
! 204: }
! 205:
! 206: /*******************************************************************/
! 207: /* */
! 208: /* HESSENBERG FORM */
! 209: /* */
! 210: /*******************************************************************/
! 211:
! 212: GEN
! 213: hess(GEN x)
! 214: {
! 215: long lx=lg(x),av=avma,tetpil,m,i,j;
! 216: GEN p,p1,p2;
! 217:
! 218: if (typ(x) != t_MAT) err(mattype1,"hess");
! 219: if (lx==1) return cgetg(1,t_MAT);
! 220: if (lg(x[1])!=lx) err(mattype1,"hess");
! 221: x = dummycopy(x);
! 222:
! 223: for (m=2; m<lx-1; m++)
! 224: for (i=m+1; i<lx; i++)
! 225: {
! 226: p = gcoeff(x,i,m-1);
! 227: if (!gcmp0(p))
! 228: {
! 229: for (j=m-1; j<lx; j++)
! 230: {
! 231: p1 = gcoeff(x,i,j);
! 232: coeff(x,i,j) = coeff(x,m,j);
! 233: coeff(x,m,j) = (long)p1;
! 234: }
! 235: p1=(GEN)x[i]; x[i]=x[m]; x[m]=(long)p1;
! 236: for (i=m+1; i<lx; i++)
! 237: {
! 238: p1 = gcoeff(x,i,m-1);
! 239: if (!gcmp0(p1))
! 240: {
! 241: p1 = gdiv(p1,p); p2 = gneg_i(p1);
! 242: coeff(x,i,m-1) = zero;
! 243: for (j=m; j<lx; j++)
! 244: coeff(x,i,j) = ladd(gcoeff(x,i,j), gmul(p2,gcoeff(x,m,j)));
! 245: for (j=1; j<lx; j++)
! 246: coeff(x,j,m) = ladd(gcoeff(x,j,m), gmul(p1,gcoeff(x,j,i)));
! 247: }
! 248: }
! 249: break;
! 250: }
! 251: }
! 252: tetpil=avma; return gerepile(av,tetpil,gcopy(x));
! 253: }
! 254:
! 255: GEN
! 256: carhess(GEN x, long v)
! 257: {
! 258: long av,tetpil,lx,r,i;
! 259: GEN *y,p1,p2,p3,p4;
! 260:
! 261: if ((p1 = easychar(x,v,NULL))) return p1;
! 262:
! 263: lx=lg(x); av=avma; y = (GEN*) new_chunk(lx);
! 264: y[0]=polun[v]; p1=hess(x); p2=polx[v];
! 265: tetpil=avma;
! 266: for (r=1; r<lx; r++)
! 267: {
! 268: y[r]=gmul(y[r-1], gsub(p2,gcoeff(p1,r,r)));
! 269: p3=gun; p4=gzero;
! 270: for (i=r-1; i; i--)
! 271: {
! 272: p3=gmul(p3,gcoeff(p1,i+1,i));
! 273: p4=gadd(p4,gmul(gmul(p3,gcoeff(p1,i,r)),y[i-1]));
! 274: }
! 275: tetpil=avma; y[r]=gsub(y[r],p4);
! 276: }
! 277: return gerepile(av,tetpil,y[lx-1]);
! 278: }
! 279:
! 280: /*******************************************************************/
! 281: /* */
! 282: /* NORM */
! 283: /* */
! 284: /*******************************************************************/
! 285:
! 286: GEN
! 287: gnorm(GEN x)
! 288: {
! 289: long l,lx,i,tetpil, tx=typ(x);
! 290: GEN p1,p2,y;
! 291:
! 292: switch(tx)
! 293: {
! 294: case t_INT:
! 295: return sqri(x);
! 296:
! 297: case t_REAL:
! 298: return mulrr(x,x);
! 299:
! 300: case t_FRAC: case t_FRACN:
! 301: return gsqr(x);
! 302:
! 303: case t_COMPLEX:
! 304: l=avma; p1=gsqr((GEN) x[1]); p2=gsqr((GEN) x[2]);
! 305: tetpil=avma; return gerepile(l,tetpil,gadd(p1,p2));
! 306:
! 307: case t_QUAD:
! 308: l=avma; p1=(GEN)x[1];
! 309: p2=gmul((GEN) p1[2], gsqr((GEN) x[3]));
! 310: p1 = gcmp0((GEN) p1[3])? gsqr((GEN) x[2])
! 311: : gmul((GEN) x[2], gadd((GEN) x[2],(GEN) x[3]));
! 312: tetpil=avma; return gerepile(l,tetpil,gadd(p1,p2));
! 313:
! 314: case t_POL: case t_SER: case t_RFRAC: case t_RFRACN:
! 315: l=avma; p1=gmul(gconj(x),x); tetpil=avma;
! 316: return gerepile(l,tetpil,greal(p1));
! 317:
! 318: case t_POLMOD:
! 319: p1=(GEN)x[1]; p2=leading_term(p1);
! 320: if (gcmp1(p2) || gcmp0((GEN) x[2])) return subres(p1,(GEN) x[2]);
! 321: l=avma; y=subres(p1,(GEN)x[2]); p1=gpuigs(p2,lgef(x[2])-3);
! 322: tetpil=avma; return gerepile(l,tetpil,gdiv(y,p1));
! 323:
! 324: case t_VEC: case t_COL: case t_MAT:
! 325: lx=lg(x); y=cgetg(lx,tx);
! 326: for (i=1; i<lx; i++) y[i]=lnorm((GEN) x[i]);
! 327: return y;
! 328: }
! 329: err(typeer,"gnorm");
! 330: return NULL; /* not reached */
! 331: }
! 332:
! 333: GEN
! 334: gnorml2(GEN x)
! 335: {
! 336: GEN y;
! 337: long i,tx=typ(x),lx,av;
! 338:
! 339: if (! is_matvec_t(tx)) return gnorm(x);
! 340: lx=lg(x); if (lx==1) return gzero;
! 341:
! 342: av=avma; y = gnorml2((GEN) x[1]);
! 343: for (i=2; i<lx; i++)
! 344: y = gadd(gnorml2((GEN) x[i]), y);
! 345: return gerepileupto(av,y);
! 346: }
! 347:
! 348: /*******************************************************************/
! 349: /* */
! 350: /* CONJUGATION */
! 351: /* */
! 352: /*******************************************************************/
! 353:
! 354: GEN
! 355: gconj(GEN x)
! 356: {
! 357: long lx,i,tx=typ(x);
! 358: GEN z;
! 359:
! 360: switch(tx)
! 361: {
! 362: case t_INT: case t_REAL: case t_INTMOD:
! 363: case t_FRAC: case t_FRACN: case t_PADIC:
! 364: return gcopy(x);
! 365:
! 366: case t_COMPLEX:
! 367: z=cgetg(3,t_COMPLEX);
! 368: z[1]=lcopy((GEN) x[1]);
! 369: z[2]=lneg((GEN) x[2]);
! 370: break;
! 371:
! 372: case t_QUAD:
! 373: z=cgetg(4,t_QUAD);
! 374: copyifstack(x[1],z[1]);
! 375: z[2]=gcmp0(gmael(x,1,3))? lcopy((GEN) x[2])
! 376: : ladd((GEN) x[2],(GEN) x[3]);
! 377: z[3]=lneg((GEN) x[3]);
! 378: break;
! 379:
! 380: case t_POL:
! 381: lx=lgef(x); z=cgetg(lx,tx); z[1]=x[1];
! 382: for (i=2; i<lx; i++) z[i]=lconj((GEN) x[i]);
! 383: break;
! 384:
! 385: case t_SER:
! 386: lx=lg(x); z=cgetg(lx,tx); z[1]=x[1];
! 387: for (i=2; i<lx; i++) z[i]=lconj((GEN) x[i]);
! 388: break;
! 389:
! 390: case t_RFRAC: case t_RFRACN: case t_VEC: case t_COL: case t_MAT:
! 391: lx=lg(x); z=cgetg(lx,tx);
! 392: for (i=1; i<lx; i++) z[i]=lconj((GEN) x[i]);
! 393: break;
! 394:
! 395: default:
! 396: err(typeer,"gconj");
! 397: return NULL; /* not reached */
! 398: }
! 399: return z;
! 400: }
! 401:
! 402: GEN
! 403: conjvec(GEN x,long prec)
! 404: {
! 405: long lx,s,av,tetpil,i,tx=typ(x);
! 406: GEN z,y,p1,p2,p;
! 407:
! 408: switch(tx)
! 409: {
! 410: case t_INT: case t_INTMOD: case t_FRAC: case t_FRACN:
! 411: z=cgetg(2,t_COL); z[1]=lcopy(x); break;
! 412:
! 413: case t_COMPLEX: case t_QUAD:
! 414: z=cgetg(3,t_COL); z[1]=lcopy(x); z[2]=lconj(x); break;
! 415:
! 416: case t_VEC: case t_COL:
! 417: lx=lg(x); z=cgetg(lx,t_MAT);
! 418: for (i=1; i<lx; i++) z[i]=(long)conjvec((GEN)x[i],prec);
! 419: s=lg(z[1]);
! 420: for (i=2; i<lx; i++)
! 421: if (lg(z[i])!=s) err(talker,"incompatible field degrees in conjvec");
! 422: break;
! 423:
! 424: case t_POLMOD:
! 425: y=(GEN)x[1]; lx=lgef(y);
! 426: if (lx<=3) return cgetg(1,t_COL);
! 427: av=avma; p=NULL;
! 428: for (i=2; i<lx; i++)
! 429: {
! 430: tx=typ(y[i]);
! 431: if (tx==t_INTMOD) p=gmael(y,i,1);
! 432: else
! 433: if (tx != t_INT && ! is_frac_t(tx))
! 434: err(polrationer,"conjvec");
! 435: }
! 436: if (!p)
! 437: {
! 438: p1=roots(y,prec); x = (GEN)x[2]; tetpil=avma;
! 439: z=cgetg(lx-2,t_COL);
! 440: for (i=1; i<=lx-3; i++)
! 441: {
! 442: p2=(GEN)p1[i]; if (gcmp0((GEN)p2[2])) p2 = (GEN)p2[1];
! 443: z[i] = (long)poleval(x, p2);
! 444: }
! 445: return gerepile(av,tetpil,z);
! 446: }
! 447: z=cgetg(lx-2,t_COL); z[1]=lcopy(x);
! 448: for (i=2; i<=lx-3; i++) z[i] = lpui((GEN) z[i-1],p,prec);
! 449: break;
! 450:
! 451: default:
! 452: err(typeer,"conjvec");
! 453: return NULL; /* not reached */
! 454: }
! 455: return z;
! 456: }
! 457:
! 458: /*******************************************************************/
! 459: /* */
! 460: /* TRACES */
! 461: /* */
! 462: /*******************************************************************/
! 463:
! 464: GEN
! 465: assmat(GEN x)
! 466: {
! 467: long lx,i,j;
! 468: GEN y,p1,p2;
! 469:
! 470: if (typ(x)!=t_POL) err(notpoler,"assmat");
! 471: if (gcmp0(x)) err(zeropoler,"assmat");
! 472:
! 473: lx=lgef(x)-2; y=cgetg(lx,t_MAT);
! 474: for (i=1; i<lx-1; i++)
! 475: {
! 476: p1=cgetg(lx,t_COL); y[i]=(long)p1;
! 477: for (j=1; j<lx; j++)
! 478: p1[j] = (j==(i+1))? un: zero;
! 479: }
! 480: p1=cgetg(lx,t_COL); y[i]=(long)p1;
! 481: if (gcmp1((GEN) x[lx+1]))
! 482: for (j=1; j<lx; j++)
! 483: p1[j] = lneg((GEN)x[j+1]);
! 484: else
! 485: {
! 486: p2 = (GEN)x[lx+1]; gnegz(p2,p2);
! 487: for (j=1; j<lx; j++)
! 488: p1[j] = ldiv((GEN)x[j+1],p2);
! 489: gnegz(p2,p2);
! 490: }
! 491: return y;
! 492: }
! 493:
! 494: GEN
! 495: gtrace(GEN x)
! 496: {
! 497: long i,l,n,tx=typ(x),lx,tetpil;
! 498: GEN y,p1,p2;
! 499:
! 500: switch(tx)
! 501: {
! 502: case t_INT: case t_REAL: case t_FRAC: case t_FRACN:
! 503: return gmul2n(x,1);
! 504:
! 505: case t_COMPLEX:
! 506: return gmul2n((GEN)x[1],1);
! 507:
! 508: case t_QUAD:
! 509: p1=(GEN)x[1];
! 510: if (!gcmp0((GEN) p1[3]))
! 511: {
! 512: l=avma; p2=gmul2n((GEN)x[2],1);
! 513: tetpil=avma; return gerepile(l,tetpil,gadd((GEN)x[3],p2));
! 514: }
! 515: return gmul2n((GEN)x[2],1);
! 516:
! 517: case t_POL:
! 518: lx=lgef(x); y=cgetg(lx,tx); y[1]=x[1];
! 519: for (i=2; i<lx; i++) y[i]=ltrace((GEN)x[i]);
! 520: return y;
! 521:
! 522: case t_SER:
! 523: lx=lg(x); y=cgetg(lx,tx); y[1]=x[1];
! 524: for (i=2; i<lx; i++) y[i]=ltrace((GEN)x[i]);
! 525: return y;
! 526:
! 527: case t_POLMOD:
! 528: l=avma; n=(lgef(x[1])-4);
! 529: p1=polsym((GEN)x[1],n); p2=gzero;
! 530: for (i=0; i<=n; i++)
! 531: p2=gadd(p2,gmul(truecoeff((GEN)x[2],i),(GEN)p1[i+1]));
! 532: return gerepileupto(l,p2);
! 533:
! 534: case t_RFRAC: case t_RFRACN:
! 535: return gadd(x,gconj(x));
! 536:
! 537: case t_VEC: case t_COL:
! 538: lx=lg(x); y=cgetg(lx,tx);
! 539: for (i=1; i<lx; i++) y[i]=ltrace((GEN)x[i]);
! 540: return y;
! 541:
! 542: case t_MAT:
! 543: lx=lg(x); if (lx!=lg(x[1])) err(mattype1,"gtrace");
! 544: l=avma; p1=gcoeff(x,1,1); if (lx==2) return gcopy(p1);
! 545: for (i=2; i<lx-1; i++)
! 546: p1=gadd(p1,gcoeff(x,i,i));
! 547: tetpil=avma; return gerepile(l,tetpil,gadd(p1,gcoeff(x,i,i)));
! 548:
! 549: }
! 550: err(typeer,"gtrace");
! 551: return NULL; /* not reached */
! 552: }
! 553:
! 554: /* Gauss reduction for positive definite matrix a
! 555: * If a is not positive definite:
! 556: * if flag is zero: raise an error
! 557: * else: return NULL.
! 558: */
! 559: GEN
! 560: sqred1intern(GEN a,long flag)
! 561: {
! 562: GEN b,p;
! 563: long av = avma,tetpil,i,j,k, lim=stack_lim(av,1), n=lg(a);
! 564:
! 565: if (typ(a)!=t_MAT) err(typeer,"sqred1");
! 566: if (lg(a[1])!=n) err(mattype1,"sqred1");
! 567: b=cgetg(n,t_MAT);
! 568: for (j=1; j<n; j++)
! 569: {
! 570: GEN p1=cgetg(n,t_COL), p2=(GEN)a[j];
! 571:
! 572: b[j]=(long)p1;
! 573: for (i=1; i<=j; i++) p1[i] = p2[i];
! 574: for ( ; i<n ; i++) p1[i] = zero;
! 575: }
! 576: for (k=1; k<n; k++)
! 577: {
! 578: p = gcoeff(b,k,k);
! 579: if (gsigne(p)<=0) /* not positive definite */
! 580: {
! 581: if (flag) { avma=av; return NULL; }
! 582: err(talker,"not a positive definite matrix in sqred1");
! 583: }
! 584: p = ginv(p);
! 585: for (i=k+1; i<n; i++)
! 586: for (j=i; j<n; j++)
! 587: coeff(b,i,j)=lsub(gcoeff(b,i,j),
! 588: gmul(gmul(gcoeff(b,k,i),gcoeff(b,k,j)), p));
! 589: for (j=k+1; j<n; j++)
! 590: coeff(b,k,j)=lmul(gcoeff(b,k,j), p);
! 591: if (low_stack(lim, stack_lim(av,1)))
! 592: {
! 593: if (DEBUGMEM>1) err(warnmem,"sqred1");
! 594: tetpil=avma; b=gerepile(av,tetpil,gcopy(b));
! 595: }
! 596: }
! 597: tetpil=avma; return gerepile(av,tetpil,gcopy(b));
! 598: }
! 599:
! 600: GEN
! 601: sqred1(GEN a)
! 602: {
! 603: return sqred1intern(a,0);
! 604: }
! 605:
! 606: GEN
! 607: sqred3(GEN a)
! 608: {
! 609: long av=avma,tetpil,i,j,k,l, lim=stack_lim(av,1), n=lg(a);
! 610: GEN p1,b;
! 611:
! 612: if (typ(a)!=t_MAT) err(typeer,"sqred3");
! 613: if (lg(a[1])!=n) err(mattype1,"sqred3");
! 614: av=avma; b=cgetg(n,t_MAT);
! 615: for (j=1; j<n; j++)
! 616: {
! 617: p1=cgetg(n,t_COL); b[j]=(long)p1;
! 618: for (i=1; i<n; i++) p1[i]=zero;
! 619: }
! 620: for (i=1; i<n; i++)
! 621: {
! 622: for (k=1; k<i; k++)
! 623: {
! 624: p1=gzero;
! 625: for (l=1; l<k; l++)
! 626: p1=gadd(p1, gmul(gmul(gcoeff(b,l,l),gcoeff(b,k,l)), gcoeff(b,i,l)));
! 627: coeff(b,i,k)=ldiv(gsub(gcoeff(a,i,k),p1),gcoeff(b,k,k));
! 628: }
! 629: p1=gzero;
! 630: for (l=1; l<i; l++)
! 631: p1=gadd(p1, gmul(gcoeff(b,l,l), gsqr(gcoeff(b,i,l))));
! 632: coeff(b,i,k)=lsub(gcoeff(a,i,i),p1);
! 633: if (low_stack(lim, stack_lim(av,1)))
! 634: {
! 635: if (DEBUGMEM>1) err(warnmem,"sqred3");
! 636: tetpil=avma; b=gerepile(av,tetpil,gcopy(b));
! 637: }
! 638: }
! 639: tetpil=avma; return gerepile(av,tetpil,gcopy(b));
! 640: }
! 641:
! 642: /* Gauss reduction (arbitrary symetric matrix, only the part above the
! 643: * diagonal is considered). If no_signature is zero, return only the
! 644: * signature
! 645: */
! 646: static GEN
! 647: sqred2(GEN a, long no_signature)
! 648: {
! 649: GEN r,p,mun;
! 650: long av,tetpil,av1,lim,n,i,j,k,l,sp,sn,t;
! 651:
! 652: if (typ(a)!=t_MAT) err(typeer,"sqred2");
! 653: n=lg(a); if (lg(a[1]) != n) err(mattype1,"sqred2");
! 654:
! 655: av=avma; mun=negi(gun); r=new_chunk(n);
! 656: for (i=1; i<n; i++) r[i]=1;
! 657: av1=avma; lim=stack_lim(av1,1); a=dummycopy(a);
! 658: n--; t=n; sp=sn=0;
! 659: while (t)
! 660: {
! 661: k=1; while (k<=n && (gcmp0(gcoeff(a,k,k)) || !r[k])) k++;
! 662: if (k<=n)
! 663: {
! 664: p=gcoeff(a,k,k); if (gsigne(p)>0) sp++; else sn++;
! 665: r[k]=0; t--;
! 666: for (j=1; j<=n; j++)
! 667: coeff(a,k,j)=r[j] ? ldiv(gcoeff(a,k,j),p) : zero;
! 668:
! 669: for (i=1; i<=n; i++) if (r[i])
! 670: for (j=1; j<=n; j++)
! 671: coeff(a,i,j) = r[j] ? lsub(gcoeff(a,i,j),
! 672: gmul(gmul(gcoeff(a,k,i),gcoeff(a,k,j)),p))
! 673: : zero;
! 674: coeff(a,k,k)=(long)p;
! 675: }
! 676: else
! 677: {
! 678: for (k=1; k<=n; k++) if (r[k])
! 679: {
! 680: l=k+1; while (l<=n && (gcmp0(gcoeff(a,k,l)) || !r[l])) l++;
! 681: if (l<=n)
! 682: {
! 683: p=gcoeff(a,k,l); r[k]=r[l]=0; sp++; sn++; t-=2;
! 684: for (i=1; i<=n; i++) if (r[i])
! 685: {
! 686: for (j=1; j<=n; j++)
! 687: coeff(a,i,j) =
! 688: r[j]? lsub(gcoeff(a,i,j),
! 689: gdiv(gadd(gmul(gcoeff(a,k,i),gcoeff(a,l,j)),
! 690: gmul(gcoeff(a,k,j),gcoeff(a,l,i))),
! 691: p))
! 692: : zero;
! 693: coeff(a,k,i)=ldiv(gadd(gcoeff(a,k,i),gcoeff(a,l,i)),p);
! 694: coeff(a,l,i)=ldiv(gsub(gcoeff(a,k,i),gcoeff(a,l,i)),p);
! 695: }
! 696: coeff(a,k,l)=un; coeff(a,l,k)=(long)mun;
! 697: coeff(a,k,k)=lmul2n(p,-1); coeff(a,l,l)=lneg(gcoeff(a,k,k));
! 698: if (low_stack(lim, stack_lim(av1,1)))
! 699: {
! 700: if(DEBUGMEM>1) err(warnmem,"sqred2");
! 701: tetpil=avma; a=gerepile(av1,tetpil,gcopy(a));
! 702: }
! 703: break;
! 704: }
! 705: }
! 706: if (k>n) break;
! 707: }
! 708: }
! 709: if (no_signature) { tetpil=avma; return gerepile(av,tetpil,gcopy(a)); }
! 710: avma=av;
! 711: a=cgetg(3,t_VEC); a[1]=lstoi(sp); a[2]=lstoi(sn); return a;
! 712: }
! 713:
! 714: GEN
! 715: sqred(GEN a) { return sqred2(a,1); }
! 716:
! 717: GEN
! 718: signat(GEN a) { return sqred2(a,0); }
! 719:
! 720: /* Diagonalization of a REAL symetric matrix. Return a 2-component vector:
! 721: * 1st comp = vector of eigenvalues
! 722: * 2nd comp = matrix of eigenvectors
! 723: */
! 724: GEN
! 725: jacobi(GEN a, long prec)
! 726: {
! 727: long de,e,e1,e2,l,n,i,j,p,q,av1,av2;
! 728: GEN c,s,t,u,ja,lambda,r,unr,x,y,x1,y1;
! 729:
! 730: if (typ(a)!=t_MAT) err(mattype1,"jacobi");
! 731: ja=cgetg(3,t_VEC); l=lg(a); n=l-1;
! 732: e1=HIGHEXPOBIT-1;
! 733: lambda=cgetg(l,t_COL); ja[1]=(long)lambda;
! 734: for (j=1; j<=n; j++)
! 735: {
! 736: lambda[j]=lgetr(prec);
! 737: gaffect(gcoeff(a,j,j), (GEN)lambda[j]);
! 738: e=expo(lambda[j]); if (e<e1) e1=e;
! 739: }
! 740: r=cgetg(l,t_MAT); ja[2]=(long)r;
! 741: for (j=1; j<=n; j++)
! 742: {
! 743: r[j]=lgetg(l,t_COL);
! 744: for (i=1; i<=n; i++)
! 745: affsr(i==j, (GEN)(coeff(r,i,j)=lgetr(prec)));
! 746: }
! 747: av1=avma;
! 748:
! 749: e2=-HIGHEXPOBIT;p=q=1;
! 750: c=cgetg(l,t_MAT);
! 751: for (j=1; j<=n; j++)
! 752: {
! 753: c[j]=lgetg(j,t_COL);
! 754: for (i=1; i<j; i++)
! 755: {
! 756: gaffect(gcoeff(a,i,j), (GEN)(coeff(c,i,j)=lgetr(prec)));
! 757: e=expo(gcoeff(c,i,j)); if (e>e2) { e2=e; p=i; q=j; }
! 758: }
! 759: }
! 760: a=c; unr = realun(prec);
! 761: de=bit_accuracy(prec);
! 762:
! 763: /* e1 = min des expo des coeff diagonaux
! 764: * e2 = max des expo des coeff extra-diagonaux
! 765: * Test d'arret: e2 < e1-precision
! 766: */
! 767: while (e1-e2<de)
! 768: {
! 769: /*calcul de la rotation associee dans le plan
! 770: des p et q-iemes vecteurs de base */
! 771: av2=avma;
! 772: x=divrr(subrr((GEN)lambda[q],(GEN)lambda[p]),shiftr(gcoeff(a,p,q),1));
! 773: y=mpsqrt(addrr(unr,mulrr(x,x)));
! 774: t=(gsigne(x)>0)? divrr(unr,addrr(x,y)) : divrr(unr,subrr(x,y));
! 775: c=divrr(unr,mpsqrt(addrr(unr,mulrr(t,t))));
! 776: s=mulrr(t,c); u=divrr(s,addrr(unr,c));
! 777:
! 778: /* Recalcul des transformees successives de a et de la matrice
! 779: cumulee (r) des rotations : */
! 780:
! 781: for (i=1; i<p; i++)
! 782: {
! 783: x=gcoeff(a,i,p); y=gcoeff(a,i,q);
! 784: x1=subrr(x,mulrr(s,addrr(y,mulrr(u,x))));
! 785: y1=addrr(y,mulrr(s,subrr(x,mulrr(u,y))));
! 786: affrr(x1,gcoeff(a,i,p)); affrr(y1,gcoeff(a,i,q));
! 787: }
! 788: for (i=p+1; i<q; i++)
! 789: {
! 790: x=gcoeff(a,p,i); y=gcoeff(a,i,q);
! 791: x1=subrr(x,mulrr(s,addrr(y,mulrr(u,x))));
! 792: y1=addrr(y,mulrr(s,subrr(x,mulrr(u,y))));
! 793: affrr(x1,gcoeff(a,p,i)); affrr(y1,gcoeff(a,i,q));
! 794: }
! 795: for (i=q+1; i<=n; i++)
! 796: {
! 797: x=gcoeff(a,p,i); y=gcoeff(a,q,i);
! 798: x1=subrr(x,mulrr(s,addrr(y,mulrr(u,x))));
! 799: y1=addrr(y,mulrr(s,subrr(x,mulrr(u,y))));
! 800: affrr(x1,gcoeff(a,p,i)); affrr(y1,gcoeff(a,q,i));
! 801: }
! 802: x=(GEN)lambda[p]; y=gcoeff(a,p,q); subrrz(x,mulrr(t,y),(GEN)lambda[p]);
! 803: x=y; y=(GEN)lambda[q]; addrrz(y,mulrr(t,x),y);
! 804: setexpo(x,expo(x)-de-1);
! 805:
! 806: for (i=1; i<=n; i++)
! 807: {
! 808: x=gcoeff(r,i,p); y=gcoeff(r,i,q);
! 809: x1=subrr(x,mulrr(s,addrr(y,mulrr(u,x))));
! 810: y1=addrr(y,mulrr(s,subrr(x,mulrr(u,y))));
! 811: affrr(x1,gcoeff(r,i,p)); affrr(y1,gcoeff(r,i,q));
! 812: }
! 813:
! 814: e2=expo(gcoeff(a,1,2)); p=1; q=2;
! 815: for (j=1; j<=n; j++)
! 816: {
! 817: for (i=1; i<j; i++)
! 818: if ((e=expo(gcoeff(a,i,j))) > e2) { e2=e; p=i; q=j; }
! 819: for (i=j+1; i<=n; i++)
! 820: if ((e=expo(gcoeff(a,j,i))) > e2) { e2=e; p=j; q=i; }
! 821: }
! 822: avma=av2;
! 823: }
! 824: avma=av1; return ja;
! 825: }
! 826:
! 827: /*************************************************************************/
! 828: /** **/
! 829: /** MATRICE RATIONNELLE --> ENTIERE **/
! 830: /** **/
! 831: /*************************************************************************/
! 832:
! 833: GEN
! 834: matrixqz0(GEN x,GEN p)
! 835: {
! 836: if (typ(p)!=t_INT) err(typeer,"matrixqz0");
! 837: if (signe(p)>=0) return matrixqz(x,p);
! 838: if (!cmpsi(-1,p)) return matrixqz2(x);
! 839: if (!cmpsi(-2,p)) return matrixqz3(x);
! 840: err(flagerr,"matrixqz"); return NULL; /* not reached */
! 841: }
! 842:
! 843: GEN
! 844: matrixqz(GEN x, GEN p)
! 845: {
! 846: long av=avma,av1,tetpil,i,j,j1,m,n,t,lim,nfact;
! 847: GEN p1,p2,p3,unmodp;
! 848:
! 849: if (typ(x)!=t_MAT) err(typeer,"matrixqz");
! 850: n=lg(x)-1; if (!n) return gcopy(x);
! 851: m=lg(x[1])-1;
! 852: if (n > m) err(talker,"more rows than columns in matrixqz");
! 853: if (n==m)
! 854: {
! 855: p1=det(x);
! 856: if (gcmp0(p1)) err(talker,"matrix of non-maximal rank in matrixqz");
! 857: avma=av; return idmat(n);
! 858: }
! 859: p1=cgetg(n+1,t_MAT);
! 860: for (j=1; j<=n; j++)
! 861: {
! 862: p2=gun; p3=(GEN)x[j];
! 863: for (i=1; i<=m; i++)
! 864: {
! 865: t=typ(p3[i]);
! 866: if (t != t_INT && !is_frac_t(t))
! 867: err(talker,"not a rational or integral matrix in matrixqz");
! 868: p2=ggcd(p2,(GEN)p3[i]);
! 869: }
! 870: p1[j]=ldiv(p3,p2);
! 871: }
! 872: x=p1; unmodp=cgetg(3,t_INTMOD); unmodp[2]=un;
! 873:
! 874: if (gcmp0(p))
! 875: {
! 876: p1=cgetg(n+1,t_MAT); p2=gtrans(x);
! 877: for (j=1; j<=n; j++) p1[j]=p2[j];
! 878: p3=det(p1); p1[n]=p2[n+1]; p3=ggcd(p3,det(p1));
! 879: if (!signe(p3))
! 880: err(impl,"matrixqz when the first 2 dets are zero");
! 881: if (gcmp1(p3))
! 882: { tetpil=avma; return gerepile(av,tetpil,gcopy(x)); }
! 883:
! 884: p3=factor(p3); p1=(GEN)p3[1]; nfact=lg(p1)-1;
! 885: }
! 886: else
! 887: {
! 888: p1=cgetg(2,t_VEC); p1[1]=(long)p; nfact=1;
! 889: }
! 890: av1=avma; lim=stack_lim(av1,1);
! 891: for (i=1; i<=nfact; i++)
! 892: {
! 893: p=(GEN)p1[i]; unmodp[1]=(long)p;
! 894: for(;;)
! 895: {
! 896: p2=ker(gmul(unmodp,x));
! 897: if (lg(p2)==1) break;
! 898:
! 899: p2=centerlift(p2); p3=gdiv(gmul(x,p2),p);
! 900: for (j=1; j<lg(p2); j++)
! 901: {
! 902: j1=n; while (gcmp0(gcoeff(p2,j1,j))) j1--;
! 903: x[j1] = p3[j];
! 904: }
! 905: if (low_stack(lim, stack_lim(av1,1)))
! 906: {
! 907: if (DEBUGMEM>1) err(warnmem,"matrixqz");
! 908: tetpil=avma; x=gerepile(av1,tetpil,gcopy(x));
! 909: }
! 910: }
! 911: }
! 912: tetpil=avma; return gerepile(av,tetpil,gcopy(x));
! 913: }
! 914:
! 915: static GEN
! 916: matrixqz_aux(GEN x, long m, long n)
! 917: {
! 918: long av = avma, lim = stack_lim(av,1), tetpil,i,j,k,in[2];
! 919: GEN p1;
! 920:
! 921: for (i=1; i<=m; i++)
! 922: {
! 923: for(;;)
! 924: {
! 925: long fl=0;
! 926:
! 927: for (j=1; j<=n; j++)
! 928: if (!gcmp0(gcoeff(x,i,j)))
! 929: { in[fl]=j; fl++; if (fl==2) break; }
! 930: if (j>n) break;
! 931:
! 932: j=(gcmp(gabs(gcoeff(x,i,in[0]),DEFAULTPREC),
! 933: gabs(gcoeff(x,i,in[1]),DEFAULTPREC)) > 0)? in[1]: in[0];
! 934: p1=gcoeff(x,i,j);
! 935: for (k=1; k<=n; k++)
! 936: if (k!=j)
! 937: x[k]=lsub((GEN)x[k],gmul(ground(gdiv(gcoeff(x,i,k),p1)),(GEN)x[j]));
! 938: }
! 939:
! 940: j=1; while (j<=n && gcmp0(gcoeff(x,i,j))) j++;
! 941: if (j<=n)
! 942: {
! 943: p1=denom(gcoeff(x,i,j));
! 944: if (!gcmp1(p1)) x[j]=lmul(p1,(GEN)x[j]);
! 945: }
! 946: if (low_stack(lim, stack_lim(av,1)))
! 947: {
! 948: if(DEBUGMEM>1) err(warnmem,"matrixqz_aux");
! 949: tetpil=avma; x=gerepile(av,tetpil,gcopy(x));
! 950: }
! 951: }
! 952: return hnf(x);
! 953: }
! 954:
! 955: GEN
! 956: matrixqz2(GEN x)
! 957: {
! 958: long av = avma,m,n;
! 959:
! 960: if (typ(x)!=t_MAT) err(typeer,"matrixqz2");
! 961: n=lg(x)-1; if (!n) return gcopy(x);
! 962: m=lg(x[1])-1; x=dummycopy(x);
! 963: return gerepileupto(av, matrixqz_aux(x,m,n));
! 964: }
! 965:
! 966: GEN
! 967: matrixqz3(GEN x)
! 968: {
! 969: long av=avma,av1,j,j1,k,m,n,lim;
! 970: GEN c;
! 971:
! 972: if (typ(x)!=t_MAT) err(typeer,"matrixqz3");
! 973: n=lg(x)-1; if (!n) return gcopy(x);
! 974: m=lg(x[1])-1; x=dummycopy(x); c=new_chunk(n+1);
! 975: for (j=1; j<=n; j++) c[j]=0;
! 976: av1=avma; lim=stack_lim(av1,1);
! 977: for (k=1; k<=m; k++)
! 978: {
! 979: j=1; while (j<=n && (c[j] || gcmp0(gcoeff(x,k,j)))) j++;
! 980: if (j<=n)
! 981: {
! 982: c[j]=k; x[j]=ldiv((GEN)x[j],gcoeff(x,k,j));
! 983: for (j1=1; j1<=n; j1++)
! 984: if (j1!=j) x[j1]=lsub((GEN)x[j1],gmul(gcoeff(x,k,j1),(GEN)x[j]));
! 985: if (low_stack(lim, stack_lim(av1,1)))
! 986: {
! 987: long tetpil = avma;
! 988: if(DEBUGMEM>1) err(warnmem,"matrixqz3");
! 989: x=gerepile(av1,tetpil,gcopy(x));
! 990: }
! 991: }
! 992: }
! 993: return gerepileupto(av, matrixqz_aux(x,m,n));
! 994: }
! 995:
! 996: GEN
! 997: intersect(GEN x, GEN y)
! 998: {
! 999: long av,tetpil,j, lx = lg(x);
! 1000: GEN z;
! 1001:
! 1002: if (typ(x)!=t_MAT || typ(y)!=t_MAT) err(typeer,"intersect");
! 1003: if (lx==1 || lg(y)==1) return cgetg(1,t_MAT);
! 1004:
! 1005: av=avma; z=ker(concatsp(x,y));
! 1006: for (j=lg(z)-1; j; j--) setlg(z[j],lx);
! 1007: tetpil=avma; return gerepile(av,tetpil,gmul(x,z));
! 1008: }
! 1009:
! 1010: /**************************************************************/
! 1011: /** **/
! 1012: /** HERMITE NORMAL FORM REDUCTION **/
! 1013: /** **/
! 1014: /**************************************************************/
! 1015:
! 1016: GEN
! 1017: mathnf0(GEN x, long flag)
! 1018: {
! 1019: switch(flag)
! 1020: {
! 1021: case 0: return hnf(x);
! 1022: case 1: return hnfall(x);
! 1023: case 2: return hnfhavas(x);
! 1024: case 3: return hnfperm(x);
! 1025: case 4: return hnflll(x);
! 1026: default: err(flagerr,"mathnf");
! 1027: }
! 1028: return NULL; /* not reached */
! 1029: }
! 1030:
! 1031: static GEN
! 1032: init_hnf(GEN x, GEN *denx, long *co, long *li, long *av)
! 1033: {
! 1034: if (typ(x) != t_MAT) err(typeer,"mathnf");
! 1035: *co=lg(x); if (*co==1) return NULL; /* empty matrix */
! 1036: *li=lg(x[1]); *denx=denom(x); *av=avma;
! 1037:
! 1038: if (gcmp1(*denx)) /* no denominator */
! 1039: { *denx = NULL; return dummycopy(x); }
! 1040: return gmul(x,*denx);
! 1041: }
! 1042:
! 1043: /* return c * X */
! 1044: #ifdef INLINE
! 1045: INLINE
! 1046: #endif
! 1047: GEN
! 1048: int_col_mul(GEN c, GEN X)
! 1049: {
! 1050: long i,m = lg(X);
! 1051: GEN A = new_chunk(m);
! 1052: for (i=1; i<m; i++) A[i] = lmulii(c,(GEN)X[i]);
! 1053: A[0] = X[0]; return A;
! 1054: }
! 1055:
! 1056: /* X,Y columns; u,v scalars; everybody is integral. return A = u*X + v*Y */
! 1057: GEN
! 1058: lincomb_integral(GEN u, GEN v, GEN X, GEN Y)
! 1059: {
! 1060: long av,i,lx,m;
! 1061: GEN p1,p2,A;
! 1062:
! 1063: if (!signe(u)) return int_col_mul(v,Y);
! 1064: if (!signe(v)) return int_col_mul(u,X);
! 1065: lx = lg(X); A = cgetg(lx,t_COL); m = lgefint(u)+lgefint(v)+4;
! 1066: if (gcmp1(u))
! 1067: {
! 1068: for (i=1; i<lx; i++)
! 1069: {
! 1070: p1=(GEN)X[i]; p2=(GEN)Y[i];
! 1071: if (!signe(p1)) A[i] = lmulii(v,p2);
! 1072: else if (!signe(p2)) A[i] = licopy(p1);
! 1073: else
! 1074: {
! 1075: av = avma; (void)new_chunk(m+lgefint(p1)+lgefint(p2));
! 1076: p2 = mulii(v,p2);
! 1077: avma = av; A[i] = laddii(p1,p2);
! 1078: }
! 1079: }
! 1080: }
! 1081: else
! 1082: for (i=1; i<lx; i++)
! 1083: {
! 1084: p1=(GEN)X[i]; p2=(GEN)Y[i];
! 1085: if (!signe(p1)) A[i] = lmulii(v,p2);
! 1086: else if (!signe(p2)) A[i] = lmulii(u,p1);
! 1087: else
! 1088: {
! 1089: av = avma; (void)new_chunk(m+lgefint(p1)+lgefint(p2));
! 1090: p1 = mulii(u,p1);
! 1091: p2 = mulii(v,p2);
! 1092: avma = av; A[i] = laddii(p1,p2);
! 1093: }
! 1094: }
! 1095: return A;
! 1096: }
! 1097:
! 1098: GEN
! 1099: hnf_special(GEN x, long remove)
! 1100: {
! 1101: long av0, s,li,co,av,tetpil,i,j,k,def,ldef,lim;
! 1102: GEN p1,u,v,d,denx,a,b, x2,res;
! 1103:
! 1104: if (typ(x) != t_VEC || lg(x) !=3) err(typeer,"hnf_special");
! 1105: res = cgetg(3,t_VEC);
! 1106: av0 = avma;
! 1107: x2 = (GEN)x[2];
! 1108: x = (GEN)x[1];
! 1109: x = init_hnf(x,&denx,&co,&li,&av);
! 1110: if (!x) return cgetg(1,t_MAT);
! 1111:
! 1112: lim = stack_lim(av,1);
! 1113: def=co-1; ldef=(li>co)? li-co: 0;
! 1114: if (lg(x2) != co) err(talker,"incompatible matrices in hnf_special");
! 1115: x2 = dummycopy(x2);
! 1116: for (i=li-1; i>ldef; i--)
! 1117: {
! 1118: for (j=def-1; j; j--)
! 1119: {
! 1120: while (j && !signe(gcoeff(x,i,j))) j--;
! 1121: if (!j) break;
! 1122: k = (j==1)? def: j-1;
! 1123: a = gcoeff(x,i,j);
! 1124: b = gcoeff(x,i,k); d = bezout(a,b,&u,&v);
! 1125: if (!is_pm1(d)) { a = divii(a,d); b = divii(b,d); }
! 1126: if (DEBUGLEVEL>5) { outerr(u); outerr(v); }
! 1127: p1 = (GEN)x[j]; b = negi(b);
! 1128: x[j] = (long)lincomb_integral(a,b, (GEN)x[k], p1);
! 1129: x[k] = (long)lincomb_integral(u,v, p1, (GEN)x[k]);
! 1130: p1 = (GEN)x2[j];
! 1131: x2[j]= ladd(gmul(a, (GEN)x2[k]), gmul(b,p1));
! 1132: x2[k] = ladd(gmul(u,p1), gmul(v, (GEN)x2[k]));
! 1133: if (low_stack(lim, stack_lim(av,1)))
! 1134: {
! 1135: GEN *gptr[2]; gptr[0]=&x; gptr[1]=&x2;
! 1136: if (DEBUGMEM>1) err(warnmem,"hnf_special[1]. i=%ld",i);
! 1137: gerepilemany(av,gptr,2);
! 1138: }
! 1139: }
! 1140: p1 = gcoeff(x,i,def); s = signe(p1);
! 1141: if (s)
! 1142: {
! 1143: if (s < 0)
! 1144: {
! 1145: x[def] = lneg((GEN)x[def]); p1 = gcoeff(x,i,def);
! 1146: x2[def]= lneg((GEN)x2[def]);
! 1147: }
! 1148: for (j=def+1; j<co; j++)
! 1149: {
! 1150: b = negi(gdivent(gcoeff(x,i,j),p1));
! 1151: x[j] = (long)lincomb_integral(gun,b, (GEN)x[j], (GEN)x[def]);
! 1152: x2[j]= ladd((GEN)x2[j], gmul(b, (GEN)x2[def]));
! 1153: }
! 1154: def--;
! 1155: }
! 1156: else
! 1157: if (ldef && i==ldef+1) ldef--;
! 1158: if (low_stack(lim, stack_lim(av,1)))
! 1159: {
! 1160: GEN *gptr[2]; gptr[0]=&x; gptr[1]=&x2;
! 1161: if (DEBUGMEM>1) err(warnmem,"hnf_special[2]. i=%ld",i);
! 1162: gerepilemany(av,gptr,2);
! 1163: }
! 1164: }
! 1165: if (remove)
! 1166: { /* remove null columns */
! 1167: for (i=1,j=1; j<co; j++)
! 1168: if (!gcmp0((GEN)x[j]))
! 1169: {
! 1170: x[i] = x[j];
! 1171: x2[i] = x2[j]; i++;
! 1172: }
! 1173: setlg(x,i);
! 1174: setlg(x2,i);
! 1175: }
! 1176: tetpil=avma;
! 1177: x = denx? gdiv(x,denx): gcopy(x);
! 1178: x2 = gcopy(x2);
! 1179: {
! 1180: GEN *gptr[2]; gptr[0]=&x; gptr[1]=&x2;
! 1181: gerepilemanysp(av0,tetpil,gptr,2);
! 1182: }
! 1183: res[1] = (long)x;
! 1184: res[2] = (long)x2;
! 1185: return res;
! 1186: }
! 1187:
! 1188: GEN
! 1189: hnf0(GEN x, long remove) /* remove: throw away lin.dep.columns, GN */
! 1190: {
! 1191: long av0 = avma, s,li,co,av,tetpil,i,j,k,def,ldef,lim;
! 1192: GEN p1,u,v,d,denx,a,b;
! 1193:
! 1194: if (typ(x) == t_VEC) return hnf_special(x,remove);
! 1195: x = init_hnf(x,&denx,&co,&li,&av);
! 1196: if (!x) return cgetg(1,t_MAT);
! 1197:
! 1198: lim = stack_lim(av,1);
! 1199: def=co-1; ldef=(li>co)? li-co: 0;
! 1200: for (i=li-1; i>ldef; i--)
! 1201: {
! 1202: for (j=def-1; j; j--)
! 1203: {
! 1204: while (j && !signe(gcoeff(x,i,j))) j--;
! 1205: if (!j) break;
! 1206: k = (j==1)? def: j-1;
! 1207: a = gcoeff(x,i,j);
! 1208: b = gcoeff(x,i,k); d = bezout(a,b,&u,&v);
! 1209: if (!is_pm1(d)) { a = divii(a,d); b = divii(b,d); }
! 1210: if (DEBUGLEVEL>5) { outerr(u); outerr(v); }
! 1211: p1 = (GEN)x[j];
! 1212: x[j] = (long)lincomb_integral(a,negi(b), (GEN)x[k],p1);
! 1213: x[k] = (long)lincomb_integral(u,v, p1,(GEN)x[k]);
! 1214: if (low_stack(lim, stack_lim(av,1)))
! 1215: {
! 1216: if (DEBUGMEM>1) err(warnmem,"hnf[1]. i=%ld",i);
! 1217: tetpil=avma; x=gerepile(av,tetpil,gcopy(x));
! 1218: }
! 1219: }
! 1220: p1 = gcoeff(x,i,def); s = signe(p1);
! 1221: if (s)
! 1222: {
! 1223: if (s < 0) { x[def] = lneg((GEN)x[def]); p1 = gcoeff(x,i,def); }
! 1224: for (j=def+1; j<co; j++)
! 1225: {
! 1226: b = negi(gdivent(gcoeff(x,i,j),p1));
! 1227: x[j] = (long)lincomb_integral(gun,b, (GEN)x[j], (GEN)x[def]);
! 1228: }
! 1229: def--;
! 1230: }
! 1231: else
! 1232: if (ldef && i==ldef+1) ldef--;
! 1233: if (low_stack(lim, stack_lim(av,1)))
! 1234: {
! 1235: if (DEBUGMEM>1) err(warnmem,"hnf[2]. i=%ld",i);
! 1236: tetpil=avma; x=gerepile(av,tetpil,gcopy(x));
! 1237: }
! 1238: }
! 1239: if (remove)
! 1240: { /* remove null columns */
! 1241: for (i=1,j=1; j<co; j++)
! 1242: if (!gcmp0((GEN)x[j])) x[i++] = x[j];
! 1243: setlg(x,i);
! 1244: }
! 1245: tetpil=avma;
! 1246: x = denx? gdiv(x,denx): gcopy(x);
! 1247: return gerepile(av0,tetpil,x);
! 1248: }
! 1249:
! 1250: GEN
! 1251: hnf(GEN x) { return hnf0(x,1); }
! 1252:
! 1253: #define cmod(x,u,us2) \
! 1254: {GEN a=modii((GEN)x,u); if (cmpii(a,us2)>0) a=subii(a,u); x=(long)a;}
! 1255:
! 1256: /* dm = multiple of diag element (usually detint(x)) */
! 1257: /* flag: don't/do append dm*matid. */
! 1258: static GEN
! 1259: allhnfmod(GEN x,GEN dm,long flag)
! 1260: {
! 1261: long li,co,av0,av,tetpil,i,j,k,def,ldef,lim,ldm;
! 1262: GEN a,b,w,p1,p2,d,u,v,dms2;
! 1263:
! 1264: if (typ(dm)!=t_INT) err(typeer,"allhnfmod");
! 1265: if (!signe(dm)) return hnf(x);
! 1266: if (typ(x)!=t_MAT) err(typeer,"allhnfmod");
! 1267: if (DEBUGLEVEL>6) fprintferr("Enter hnfmod");
! 1268:
! 1269: co=lg(x); if (co==1) return cgetg(1,t_MAT);
! 1270: av0=avma; lim=stack_lim(av0,1);
! 1271: dms2=shifti(dm,-1); li=lg(x[1]);
! 1272: av=avma;
! 1273:
! 1274: if (flag)
! 1275: {
! 1276: p1 = cgetg(co,t_MAT); for (i=1; i<co; i++) p1[i]=x[i];
! 1277: if (li > co) err(talker,"nb lines > nb columns in hnfmod");
! 1278: x = p1;
! 1279: }
! 1280: else
! 1281: {
! 1282: /* concatenate dm * Id to x */
! 1283: x = concatsp(x, idmat_intern(li-1,dm,gzero));
! 1284: for (i=1; i<co; i++) x[i] = lmod((GEN)x[i], dm);
! 1285: co += li-1;
! 1286: }
! 1287: def=co-1; ldef=0;
! 1288: for (i=li-1; i>ldef; i--,def--)
! 1289: {
! 1290: if (DEBUGLEVEL>6) { fprintferr(" %ld",i); flusherr(); }
! 1291: for (j=def-1; j; j--)
! 1292: {
! 1293: while (j && !signe(gcoeff(x,i,j))) j--;
! 1294: if (!j) break;
! 1295: if (DEBUGLEVEL>8) { fprintferr(" %ld",j); flusherr(); }
! 1296: k = (j==1)? def: j-1;
! 1297: a = gcoeff(x,i,j);
! 1298: b = gcoeff(x,i,k); d = bezout(a,b,&u,&v);
! 1299: if (!is_pm1(d)) { a = divii(a,d); b = divii(b,d); }
! 1300: p1 = lincomb_integral(u,v, (GEN)x[j], (GEN)x[k]);
! 1301: p2 = lincomb_integral(a, negi(b), (GEN)x[k], (GEN)x[j]);
! 1302: x[k] = (long)p1;
! 1303: x[j] = (long)p2;
! 1304: for (k=1; k<=i; k++)
! 1305: {
! 1306: cmod(p1[k], dm, dms2);
! 1307: cmod(p2[k], dm, dms2);
! 1308: }
! 1309: if (low_stack(lim, stack_lim(av0,1)))
! 1310: {
! 1311: if (DEBUGMEM>1) err(warnmem,"allhnfmod[1]. i=%ld",i);
! 1312: tetpil=avma; x=gerepile(av,tetpil,gcopy(x));
! 1313: }
! 1314: }
! 1315: }
! 1316: w=cgetg(li,t_MAT); b=dm;
! 1317: for (i=li-1; i>=1; i--)
! 1318: {
! 1319: d = bezout(gcoeff(x,i,i+def),b,&u,&v);
! 1320: w[i] = lmod(gmul(u,(GEN)x[i+def]), b);
! 1321: if (!signe(gcoeff(w,i,i))) coeff(w,i,i)=(long)d;
! 1322: if (i > 1 && flag) b=divii(b,d);
! 1323: }
! 1324: ldm = lgefint(dm);
! 1325: for (i=li-2; i>=1; i--)
! 1326: {
! 1327: GEN diag = gcoeff(w,i,i);
! 1328: for (j=i+1; j<li; j++)
! 1329: {
! 1330: b = negi(gdivent(gcoeff(w,i,j), diag));
! 1331: p1 = lincomb_integral(gun,b, (GEN)w[j], (GEN)w[i]);
! 1332: w[j] = (long)p1;
! 1333: for (k=1; k<i; k++)
! 1334: {
! 1335: p2 = (GEN)p1[k];
! 1336: if (lgefint(p2) > ldm) p1[k] = lmodii(p2, dm);
! 1337: }
! 1338: if (low_stack(lim, stack_lim(av0,1)))
! 1339: {
! 1340: if (DEBUGMEM>1) err(warnmem,"allhnfmod[2]. i=%ld", i);
! 1341: tetpil=avma; w=gerepile(av,tetpil,gcopy(w));
! 1342: diag = gcoeff(w,i,i);
! 1343: }
! 1344: }
! 1345: }
! 1346: if (DEBUGLEVEL>6) { fprintferr("\nEnd hnfmod\n"); flusherr(); }
! 1347: tetpil=avma; return gerepile(av0,tetpil,gcopy(w));
! 1348: }
! 1349: #undef cmod
! 1350:
! 1351: GEN
! 1352: hnfmod(GEN x, GEN detmat) { return allhnfmod(x,detmat,1); }
! 1353:
! 1354: GEN
! 1355: hnfmodid(GEN x, GEN p) { return allhnfmod(x,p,0); }
! 1356:
! 1357: /* Return [y,U,V] such that y=V.x.U, V permutation vector, U unimodular
! 1358: * matrix, and y in HNF form
! 1359: */
! 1360: GEN
! 1361: hnfhavas(GEN x)
! 1362: {
! 1363: long av0=avma, av,av1,tetpil,li,co,i,j,k,def,ldef,lim,imin,jmin,vpk;
! 1364: long jpro,com,vi;
! 1365: GEN p1,p2,z,u,denx,vperm,mat1,col2,lil2,s,pmin,apro,bpro,cpro;
! 1366:
! 1367: if (DEBUGLEVEL>6)
! 1368: { fprintferr("Entering hnfhavas: AVMA = %ld\n",avma); flusherr(); }
! 1369: if (typ(x)!=t_MAT) err(typeer,"hnfhavas");
! 1370: co=lg(x);
! 1371: if (co==1)
! 1372: {
! 1373: z=cgetg(4,t_VEC); z[1]=lgetg(1,t_MAT);
! 1374: z[2]=lgetg(1,t_MAT); z[3]=lgetg(1,t_VEC);
! 1375: return z;
! 1376: }
! 1377: li=lg(x[1]); denx=denom(x);
! 1378: vperm=new_chunk(li); for (i=1; i<li; i++) vperm[i]=i;
! 1379:
! 1380: av=avma; lim=stack_lim(av,1); u=idmat(co-1);
! 1381: x = gcmp1(denx)? dummycopy(x): gmul(denx,x);
! 1382: def=co; ldef=(li>co)?li-co+1:1;
! 1383: for (i=li-1; i>=ldef; i--)
! 1384: {
! 1385: def--; av1=avma; mat1=cgetg(def+1,t_MAT); col2=cgetg(def+1,t_COL);
! 1386: for (j=1; j<=def; j++)
! 1387: {
! 1388: p1=cgetg(i+1,t_COL); mat1[j]=(long)p1; s=gzero;
! 1389: for (k=1; k<=i; k++)
! 1390: {
! 1391: p2=gsqr(gcoeff(x,vperm[k],j));
! 1392: p1[k]=(long)p2; s=gadd(s,p2);
! 1393: }
! 1394: col2[j]=(long)s;
! 1395: }
! 1396: lil2=cgetg(i+1,t_COL);
! 1397: for (k=1; k<=i; k++)
! 1398: {
! 1399: s=gzero;
! 1400: for (j=1; j<=def; j++) s=gadd(s,gcoeff(mat1,k,j));
! 1401: lil2[k]=(long)s;
! 1402: }
! 1403:
! 1404: pmin = NULL;
! 1405: for (k=i; k>=1; k--)
! 1406: {
! 1407: while (k>=1 && !signe(lil2[k])) k--;
! 1408: if (!k) goto comterm;
! 1409: vpk=vperm[k];
! 1410: if (!pmin || cmpii((GEN)lil2[k],pmin) <= 0)
! 1411: {
! 1412: j=1; while (!signe(gcoeff(x,vpk,j))) j++;
! 1413: if (!pmin)
! 1414: {
! 1415: imin=k; jmin=j; pmin=mulii((GEN)lil2[k],(GEN)col2[j]);
! 1416: cpro=absi(gcoeff(x,vpk,j));
! 1417: }
! 1418: jpro=j; apro=absi(gcoeff(x,vpk,j)); j++;
! 1419: for (; j<=def; j++)
! 1420: {
! 1421: com=cmpii((GEN)col2[j],(GEN)col2[jpro]);
! 1422: if (signe(gcoeff(x,vpk,j)) && com <=0)
! 1423: {
! 1424: if (com<0) { jpro=j; apro=absi(gcoeff(x,vpk,j)); }
! 1425: else
! 1426: {
! 1427: bpro=absi(gcoeff(x,vpk,j));
! 1428: if (cmpii(bpro,apro)<0) { jpro=j; apro=bpro; }
! 1429: }
! 1430: }
! 1431: }
! 1432: p1=mulii((GEN)lil2[k],(GEN)col2[jpro]);
! 1433: com=cmpii(p1,pmin);
! 1434: if (com<0 || (com==0 && cmpii(apro,cpro)<0))
! 1435: {
! 1436: imin=k; jmin=jpro; pmin=p1; cpro=apro;
! 1437: }
! 1438: }
! 1439: }
! 1440: avma=av1;
! 1441: if (jmin!=def)
! 1442: {
! 1443: p1=(GEN)x[def]; x[def]=x[jmin]; x[jmin]=(long)p1;
! 1444: p1=(GEN)u[def]; u[def]=u[jmin]; u[jmin]=(long)p1;
! 1445: }
! 1446: if (imin!=i) { vpk=vperm[i]; vperm[i]=vperm[imin]; vperm[imin]=vpk; }
! 1447: vi=vperm[i];
! 1448: for(;;)
! 1449: {
! 1450: GEN p3,p12,p13;
! 1451:
! 1452: if (signe(gcoeff(x,vi,def))<0)
! 1453: {
! 1454: x[def]=lneg((GEN)x[def]); u[def]=lneg((GEN)u[def]);
! 1455: }
! 1456: p1=gcoeff(x,vi,def); p12=shifti(p1,-1); p13=negi(p12);
! 1457: for (j=1; j<def; j++)
! 1458: {
! 1459: p2=dvmdii(gcoeff(x,vi,j),p1,&p3);
! 1460: if (cmpii(p3,p13)<0) p2=addis(p2,-1);
! 1461: else { if (cmpii(p3,p12)>0) p2=addis(p2,1); }
! 1462: if (DEBUGLEVEL>5) outerr(p2);
! 1463: setsigne(p2,-signe(p2));
! 1464: x[j]=ladd((GEN)x[j],gmul(p2,(GEN)x[def]));
! 1465: u[j]=ladd((GEN)u[j],gmul(p2,(GEN)u[def]));
! 1466: }
! 1467: j=1; while (!signe(gcoeff(x,vi,j))) j++;
! 1468: if (j<def)
! 1469: {
! 1470: pmin=gnorml2((GEN)x[j]); jmin=j; apro=absi(gcoeff(x,vi,j));
! 1471: j++;
! 1472: for (; j<def; j++)
! 1473: {
! 1474: if (signe(gcoeff(x,vi,j)))
! 1475: {
! 1476: p1=gnorml2((GEN)x[j]);
! 1477: com=cmpii(p1,pmin);
! 1478: if (com<0)
! 1479: {
! 1480: pmin=p1; jmin=j;
! 1481: }
! 1482: else if (com==0)
! 1483: {
! 1484: bpro=absi(gcoeff(x,vi,j));
! 1485: if (cmpii(bpro,apro)<0)
! 1486: {
! 1487: pmin=p1; jmin=j; apro=bpro;
! 1488: }
! 1489: }
! 1490: }
! 1491: }
! 1492: p1=(GEN)x[def]; x[def]=x[jmin]; x[jmin]=(long)p1;
! 1493: p1=(GEN)u[def]; u[def]=u[jmin]; u[jmin]=(long)p1;
! 1494: }
! 1495: else break;
! 1496: }
! 1497: vi=vperm[i]; p1=gcoeff(x,vi,def);
! 1498: for (j=def+1; j<co; j++)
! 1499: {
! 1500: p2=gdivent(gcoeff(x,vi,j),p1); setsigne(p2,-signe(p2));
! 1501: if (DEBUGLEVEL>5) outerr(p2);
! 1502: x[j]=ladd((GEN)x[j],gmul(p2,(GEN)x[def]));
! 1503: u[j]=ladd((GEN)u[j],gmul(p2,(GEN)u[def]));
! 1504: }
! 1505:
! 1506: if (low_stack(lim, stack_lim(av,1)))
! 1507: {
! 1508: GEN *gptr[2];
! 1509: if (DEBUGMEM>1) err(warnmem,"hnfhavas");
! 1510: gptr[0]=&x; gptr[1]=&u;
! 1511: gerepilemany(av,gptr,2);
! 1512: }
! 1513: }
! 1514:
! 1515: comterm:
! 1516: tetpil=avma; z=cgetg(4,t_VEC); p1=cgetg(co,t_MAT);
! 1517: if (gcmp1(denx))
! 1518: {
! 1519: for (j=1; j<co; j++)
! 1520: {
! 1521: p2=cgetg(li,t_COL); p1[j]=(long)p2;
! 1522: for (i=1; i<li; i++)
! 1523: p2[i] = lcopy(gcoeff(x,vperm[i],j));
! 1524: }
! 1525: }
! 1526: else
! 1527: {
! 1528: for (j=1; j<co; j++)
! 1529: {
! 1530: p2=cgetg(li,t_COL); p1[j]=(long)p2;
! 1531: for (i=1; i<li; i++)
! 1532: p2[i] = ldiv(gcoeff(x,vperm[i],j),denx);
! 1533: }
! 1534: }
! 1535: z[1]=(long)p1; z[2]=lcopy(u);
! 1536: p1=cgetg(li,t_VEC); for (i=1; i<li; i++) p1[i]=lstoi(vperm[i]);
! 1537: z[3]=(long)p1; return gerepile(av0,tetpil,z);
! 1538: }
! 1539:
! 1540: /* HNF by Bo Majewski and Allan Steele */
! 1541:
! 1542: /* premier indice non nul de la j-eme ligne de la matrice b */
! 1543: static long
! 1544: depthvector(GEN b,long j)
! 1545: {
! 1546: long lv = lg(b), i = 1;
! 1547:
! 1548: while (i<lv && gcmp0(gcoeff(b,j,i))) i++;
! 1549: return (i==lv)?-1:i;
! 1550: }
! 1551:
! 1552: static GEN
! 1553: incompleteprod(GEN b,long k,long l,long deb,long fin)
! 1554: {
! 1555: GEN p1 = gzero;
! 1556: long j;
! 1557:
! 1558: for (j=deb; j<=fin; j++)
! 1559: p1 = addii(p1,mulii(gcoeff(b,k,j),gcoeff(b,l,j)));
! 1560: return p1;
! 1561: }
! 1562:
! 1563: static void
! 1564: redlll(GEN b,GEN mu,long l,long c,long k)
! 1565: {
! 1566: long i,j, lb;
! 1567: GEN q, p1=gcoeff(b,l,c);
! 1568:
! 1569: if (signe(p1)) q=gdivround(gcoeff(b,k,c),p1); else q=ground(gcoeff(mu,k,l));
! 1570: if (signe(q))
! 1571: {
! 1572: q=negi(q); lb=lg(b);
! 1573: for (j=1; j<lb; j++)
! 1574: coeff(b,k,j) = laddii(gcoeff(b,k,j),mulii(q,gcoeff(b,l,j)));
! 1575: coeff(mu,k,l)=ladd(gcoeff(mu,k,l),q);
! 1576: for (i=1; i<l; i++)
! 1577: {
! 1578: p1=gcoeff(mu,l,i);
! 1579: if (gsigne(p1))
! 1580: coeff(mu,k,i) = ladd(gcoeff(mu,k,i),gmul(q,p1));
! 1581: }
! 1582: }
! 1583: }
! 1584:
! 1585: GEN
! 1586: hnflll(GEN x)
! 1587: {
! 1588: long n,m,i,j,k,ii,jj,p,c,s,av=avma,tetpil,kmax,ok;
! 1589: GEN q,qneg,p1,bnew,B,mu,mmu,cst,E,U,y,t,BB;
! 1590:
! 1591: if (typ(x)!=t_MAT) err(typeer,"hnflll");
! 1592: n=lg(x)-1;
! 1593: if (!n)
! 1594: {
! 1595: y=cgetg(3,t_VEC);
! 1596: y[1]=lgetg(1,t_MAT);
! 1597: y[2]=lgetg(1,t_MAT); return y;
! 1598: }
! 1599: cst=gdivgs(stoi(9),10);
! 1600: x=gcopy(x); n=lg(x)-1; m=lg(x[1])-1; p=n+m;
! 1601: bnew=cgetg(p+1,t_MAT);
! 1602: for (j=1; j<=n; j++) bnew[j]=x[j];
! 1603: for (j=n+1; j<=p; j++)
! 1604: {
! 1605: p1=cgetg(m+1,t_COL); bnew[j]=(long)p1;
! 1606: for (i=1; i<=m; i++) p1[i]=(i==(j-n))?un:zero;
! 1607: }
! 1608: x=bnew; c=n+1;
! 1609: for (i=1; i<=m; i++) c=min(c,depthvector(x,i));
! 1610: s=0; mu=cgetg(m+2,t_MAT);
! 1611: for (j=1; j<=m; j++) mu[j]=lgetg(m+2,t_COL); B=cgetg(m+2,t_COL);
! 1612: while (c<=n)
! 1613: {
! 1614: k=2; kmax=1;
! 1615: B[1]=(long)incompleteprod(x,1,1,c+1,p);
! 1616: while (k<=m-c+1)
! 1617: {
! 1618: if (k>kmax)
! 1619: {
! 1620: kmax=k;
! 1621: for (j=1; j<k; j++)
! 1622: {
! 1623: mmu=incompleteprod(x,k,j,c+1,p);
! 1624: for (i=1; i<j; i++) mmu=gsub(mmu,gmul(gcoeff(mu,j,i),gcoeff(mu,k,i)));
! 1625: coeff(mu,k,j)=(long)mmu;
! 1626: }
! 1627: for (j=1; j<k; j++) coeff(mu,k,j)=ldiv(gcoeff(mu,k,j),(GEN)B[j]);
! 1628: B[k]=(long)incompleteprod(x,k,k,c+1,p);
! 1629: for (j=1; j<k; j++)
! 1630: B[k]=lsub((GEN)B[k],gmul((GEN)B[j],gsqr(gcoeff(mu,k,j))));
! 1631: }
! 1632: redlll(x,mu,k-1,c,k);
! 1633: ok = (absi(gcoeff(x,k-1,c))>absi(gcoeff(x,k,c))) ||
! 1634: (gegal(gcoeff(x,k-1,c),gcoeff(x,k,c)) &&
! 1635: (gcmp((GEN) B[k],
! 1636: gmul(gsub(cst,gsqr(gcoeff(mu,k,k-1))), (GEN) B[k-1])) < 0) );
! 1637: while (ok)
! 1638: {
! 1639: for (j=1; j<=p; j++)
! 1640: {
! 1641: t=gcoeff(x,k,j); coeff(x,k,j)=coeff(x,k-1,j);
! 1642: coeff(x,k-1,j)=(long)t;
! 1643: }
! 1644: for (j=1; j<=k-2; j++)
! 1645: {
! 1646: t=gcoeff(mu,k,j); coeff(mu,k,j)=coeff(mu,k-1,j);
! 1647: coeff(mu,k-1,j)=(long)t;
! 1648: }
! 1649: mmu=gcoeff(mu,k,k-1);
! 1650: BB=gadd((GEN)B[k],gmul(gmul(mmu,mmu),(GEN)B[k-1]));
! 1651: q=gdiv((GEN)B[k-1],BB);
! 1652: coeff(mu,k,k-1)=lmul(mmu,q);
! 1653: B[k]=lmul((GEN)B[k],q); B[k-1]=(long)BB;
! 1654: for (i=k+1; i<=kmax; i++)
! 1655: {
! 1656: t=gcoeff(mu,i,k);
! 1657: coeff(mu,i,k)=lsub(gcoeff(mu,i,k-1),gmul(mmu,t));
! 1658: coeff(mu,i,k-1)=ladd(t,gmul(gcoeff(mu,k,k-1),gcoeff(mu,i,k)));
! 1659: }
! 1660: if (k>2) k--;
! 1661: redlll(x,mu,k-1,c,k);
! 1662: ok=(absi(gcoeff(x,k-1,c))>absi(gcoeff(x,k,c))) ||
! 1663: (gegal(gcoeff(x,k-1,c),gcoeff(x,k,c)) &&
! 1664: (gcmp((GEN) B[k],
! 1665: gmul(gsub(cst,gsqr(gcoeff(mu,k,k-1))), (GEN) B[k-1])) < 0));
! 1666: }
! 1667: for (i=k-2; i; i--) redlll(x,mu,i,c,k);
! 1668: k++;
! 1669: }
! 1670: s++; c=n+1;
! 1671: for (i=1; i<=m-s; i++) c=min(c,depthvector(x,i));
! 1672: }
! 1673: s=m-s+1;
! 1674: if (signe(gcoeff(x,s,depthvector(x,s)))<0)
! 1675: for (j=1; j<=p; j++)
! 1676: coeff(x,s,j)=lnegi(gcoeff(x,s,j));
! 1677: for (i=s+1; i<=m; i++)
! 1678: {
! 1679: if (signe(gcoeff(x,i,depthvector(x,i)))<0)
! 1680: for (j=1; j<=p; j++)
! 1681: coeff(x,i,j)=lnegi(gcoeff(x,i,j));
! 1682: for (j=i-1; j>=s; j--)
! 1683: {
! 1684: k=depthvector(x,j);
! 1685: qneg=negi(gdivent(gcoeff(x,i,k),gcoeff(x,j,k)));
! 1686: for (jj=1; jj<=p; jj++)
! 1687: coeff(x,i,jj)=laddii(gcoeff(x,i,jj),mulii(qneg,gcoeff(x,j,jj)));
! 1688: }
! 1689: }
! 1690: for (k=s; k<=m; k++)
! 1691: {
! 1692: for (j=1; j<s; j++)
! 1693: {
! 1694: mmu=incompleteprod(x,k,j,n+1,p);
! 1695: for (i=1; i<j; i++) mmu=gsub(mmu,gmul(gcoeff(mu,j,i),gcoeff(mu,k,i)));
! 1696: coeff(mu,k,j)=(long)mmu;
! 1697: }
! 1698: for (j=1; j<s; j++) coeff(mu,k,j)=ldiv(gcoeff(mu,k,j),(GEN)B[j]);
! 1699: B[k]=(long)incompleteprod(x,k,k,n+1,p);
! 1700: for (j=1; j<s; j++)
! 1701: B[k]=lsub((GEN)B[k],gmul(gsqr(gcoeff(mu,k,j)),(GEN)B[j]));
! 1702: for (j=s-1; j; j--)
! 1703: {
! 1704: qneg=negi(ground(gcoeff(mu,k,j)));
! 1705: if (signe(qneg))
! 1706: {
! 1707: for (jj=1; jj<=p; jj++)
! 1708: coeff(x,k,jj)=laddii(gcoeff(x,k,jj),mulii(qneg,gcoeff(x,j,jj)));
! 1709: for (i=1; i<j; i++)
! 1710: if (gsigne(gcoeff(mu,j,i)))
! 1711: coeff(mu,k,i)=ladd(gcoeff(mu,k,i),gmul(qneg,gcoeff(mu,j,i)));
! 1712: }
! 1713: }
! 1714: }
! 1715: tetpil=avma; y=cgetg(3,t_VEC);
! 1716: E=cgetg(n+1,t_MAT);
! 1717: for (i=1; i<=n; i++)
! 1718: {
! 1719: p1=cgetg(m-s+2,t_COL); E[i]=(long)p1;
! 1720: for (ii=1; ii<=m-s+1; ii++)
! 1721: p1[ii]=lcopy(gcoeff(x,m-ii+1,i));
! 1722: }
! 1723: y[1]=(long)E; U=cgetg(m+1,t_MAT);
! 1724: for (i=1; i<=m; i++)
! 1725: {
! 1726: p1=cgetg(m+1,t_COL); U[i]=(long)p1;
! 1727: for (ii=m; ii>=1; ii--)
! 1728: p1[m-ii+1]=lcopy(gcoeff(x,ii,i+n));
! 1729: }
! 1730: y[2]=(long)U; return gerepile(av,tetpil,y);
! 1731: }
! 1732:
! 1733: /* HNF with permutation */
! 1734: GEN
! 1735: hnfperm(GEN A)
! 1736: {
! 1737: GEN U,c,l,perm,d,u,v,p,q,y,a,b,p1;
! 1738: long r,t,i,j,j1,k,m,n,av=avma,av1,tetpil,lim;
! 1739:
! 1740: if (typ(A)!=t_MAT) err(typeer,"hnfperm");
! 1741: n=lg(A)-1;
! 1742: if (!n)
! 1743: {
! 1744: y=cgetg(4,t_VEC);
! 1745: y[1]=lgetg(1,t_MAT);
! 1746: y[2]=lgetg(1,t_MAT);
! 1747: y[3]=lgetg(1,t_VEC); return y;
! 1748: }
! 1749: m=lg(A[1])-1;
! 1750: c=new_chunk(m+1); for (i=1; i<=m; i++) c[i]=0;
! 1751: l=new_chunk(n+1); for (j=1; j<=n; j++) l[j]=0;
! 1752: perm=new_chunk(m+1);
! 1753: av1=avma; lim=stack_lim(av1,1);
! 1754: U=idmat(n); A=dummycopy(A);
! 1755: /* U base change matrix : A0*U=A all along */
! 1756:
! 1757: for (r=0,k=1; k<=n; k++)
! 1758: {
! 1759: for (j=1; j<k; j++) if (l[j])
! 1760: {
! 1761: t=l[j]; b=gcoeff(A,t,k);
! 1762: if (signe(b) == 0) continue;
! 1763:
! 1764: a=gcoeff(A,t,j); d=bezout(a,b,&u,&v);
! 1765: if (!is_pm1(d)) { a=divii(a,d); b=divii(b,d); }
! 1766: p1 = (GEN)A[j]; b = negi(b);
! 1767: A[j] = (long)lincomb_integral(u,v, p1,(GEN)A[k]);
! 1768: A[k] = (long)lincomb_integral(a,b, (GEN)A[k],p1);
! 1769: p1 = (GEN)U[j];
! 1770: U[j] = (long)lincomb_integral(u,v, p1,(GEN)U[k]);
! 1771: U[k] = (long)lincomb_integral(a,b, (GEN)U[k],p1);
! 1772: for (j1=1; j1<j; j1++) if (l[j1])
! 1773: {
! 1774: q=truedvmdii(gcoeff(A,t,j1),d,NULL);
! 1775: if (signe(q))
! 1776: {
! 1777: q = negi(q);
! 1778: A[j1] = (long)lincomb_integral(gun,q,(GEN)A[j1],(GEN)A[j]);
! 1779: U[j1] = (long)lincomb_integral(gun,q,(GEN)U[j1],(GEN)U[j]);
! 1780: }
! 1781: }
! 1782: }
! 1783: t=m; while (t && (c[t] || !signe(gcoeff(A,t,k)))) t--;
! 1784: if (t)
! 1785: {
! 1786: p = gcoeff(A,t,k);
! 1787: for (i=t-1; i; i--)
! 1788: {
! 1789: q = gcoeff(A,i,k);
! 1790: if (signe(q) && absi_cmp(p,q) > 0) { p=q; t=i; }
! 1791: }
! 1792: perm[++r]=l[k]=t; c[t]=k;
! 1793: if (signe(p) < 0)
! 1794: {
! 1795: for (i=1; i<=m; i++) coeff(A,i,k)= lnegi(gcoeff(A,i,k));
! 1796: for (i=1; i<=n; i++) coeff(U,i,k)= lnegi(gcoeff(U,i,k));
! 1797: p=gcoeff(A,t,k);
! 1798: }
! 1799: for (j=1; j<k; j++) if (l[j])
! 1800: {
! 1801: q=truedvmdii(gcoeff(A,t,j),p,NULL);
! 1802: if (signe(q))
! 1803: {
! 1804: q = negi(q);
! 1805: A[j]=(long)lincomb_integral(gun,q,(GEN)A[j],(GEN)A[k]);
! 1806: U[j]=(long)lincomb_integral(gun,q,(GEN)U[j],(GEN)U[k]);
! 1807: }
! 1808: }
! 1809: }
! 1810: if (low_stack(lim, stack_lim(av1,1)))
! 1811: {
! 1812: GEN *gptr[2]; gptr[0]=&A; gptr[1]=&U;
! 1813: if (DEBUGMEM>1) err(warnmem,"hnfperm");
! 1814: gerepilemany(av1,gptr,2);
! 1815: }
! 1816: }
! 1817: if (r < m)
! 1818: {
! 1819: for (i=1,k=r; i<=m; i++)
! 1820: if (c[i]==0) perm[++k] = i;
! 1821: }
! 1822:
! 1823: /* We have A0*U=A, U in Gl(n,Z)
! 1824: * basis for Im(A): columns of A s.t l[j]>0 (r cols)
! 1825: * basis for Ker(A): columns of U s.t l[j]=0 (n-r cols)
! 1826: */
! 1827: tetpil=avma; y=cgetg(4,t_VEC);
! 1828: p=cgetg(r+1,t_MAT); u=cgetg(n+1,t_MAT);
! 1829: for (t=1,k=r,j=1; j<=n; j++)
! 1830: if (l[j])
! 1831: {
! 1832: q=cgetg(m+1,t_COL); p[k]=(long)q;
! 1833: for (i=1; i<=m; i++) q[i]=lcopy(gcoeff(A,perm[m-i+1],j));
! 1834: u[k+n-r]=lcopy((GEN)U[j]);
! 1835: k--;
! 1836: }
! 1837: else u[t++]=lcopy((GEN)U[j]);
! 1838: y[1]=(long)p; y[2]=(long)u;
! 1839: q = cgetg(m+1,t_VEC); y[3]=(long)q;
! 1840: for (i=1; i<=m; i++) q[m-i+1]=lstoi(perm[i]);
! 1841: return gerepile(av,tetpil,y);
! 1842: }
! 1843:
! 1844: GEN
! 1845: colint_copy(GEN x)
! 1846: {
! 1847: long i, lx = lg(x);
! 1848: GEN y = cgetg(lx, t_COL);
! 1849: for (i=1; i<lx; i++) y[i] = signe(x[i])? licopy((GEN)x[i]): zero;
! 1850: return y;
! 1851: }
! 1852:
! 1853: GEN
! 1854: matint_copy(GEN x)
! 1855: {
! 1856: long i, lx = lg(x);
! 1857: GEN y = cgetg(lx, t_MAT);
! 1858:
! 1859: for (i=1; i<lx; i++)
! 1860: y[i] = (long)colint_copy((GEN)x[i]);
! 1861: return y;
! 1862: }
! 1863:
! 1864: /*====================================================================
! 1865: * Forme Normale d'Hermite (Version par colonnes 31/01/94)
! 1866: *====================================================================*/
! 1867: GEN
! 1868: hnfall0(GEN A, long remove)
! 1869: {
! 1870: GEN U,c,h,x,y,u,v,p,q,d,a,b,p1;
! 1871: long m,n,r,i,j,j1,k,li,z,av=avma,av1,tetpil,lim;
! 1872:
! 1873: if (typ(A)!=t_MAT) err(typeer,"hnfall");
! 1874: n=lg(A)-1;
! 1875: if (!n)
! 1876: {
! 1877: y=cgetg(3,t_VEC);
! 1878: y[1]=lgetg(1,t_MAT);
! 1879: y[2]=lgetg(1,t_MAT); return y;
! 1880: }
! 1881: m=lg(A[1])-1;
! 1882: c=new_chunk(m+1); for (i=1; i<=m; i++) c[i]=0;
! 1883: h=new_chunk(n+1); for (j=1; j<=n; j++) h[j]=m;
! 1884: av1=avma; lim=stack_lim(av1,1);
! 1885: A=dummycopy(A); U=idmat(n); r=n+1;
! 1886: for (li=m; li; li--)
! 1887: {
! 1888: for (j=1; j<r; j++)
! 1889: {
! 1890: for (i=h[j]; i>li; i--)
! 1891: {
! 1892: b = gcoeff(A,i,j);
! 1893: if (signe(b))
! 1894: {
! 1895: k=c[i]; a=gcoeff(A,i,k); /* annuler bij A l'aide de p=bik */
! 1896: d=bezout(a,b,&u,&v);
! 1897: if (DEBUGLEVEL>5)
! 1898: { fprintferr("(u,v) = (%Z, %Z); ",u,v); flusherr(); }
! 1899: if (!is_pm1(d)) { a=divii(a,d); b =divii(b,d); }
! 1900: p1 = (GEN)A[k]; b = negi(b);
! 1901: A[k] = (long)lincomb_integral(u,v, p1,(GEN)A[j]);
! 1902: A[j] = (long)lincomb_integral(a,b, (GEN)A[j],p1);
! 1903: p1 = (GEN)U[k];
! 1904: U[k] = (long)lincomb_integral(u,v, p1,(GEN)U[j]);
! 1905: U[j] = (long)lincomb_integral(a,b, (GEN)U[j],p1);
! 1906: for (j1=k+1; j1<=n; j1++)
! 1907: {
! 1908: q=truedvmdii(gcoeff(A,i,j1),d,NULL);
! 1909: if (signe(q))
! 1910: {
! 1911: q = negi(q);
! 1912: A[j1]=(long)lincomb_integral(gun,q,(GEN)A[j1],(GEN)A[k]);
! 1913: U[j1]=(long)lincomb_integral(gun,q,(GEN)U[j1],(GEN)U[k]);
! 1914: }
! 1915: }
! 1916: if (low_stack(lim, stack_lim(av1,1)))
! 1917: {
! 1918: GEN *gptr[2]; tetpil = avma;
! 1919: A = matint_copy(A); gptr[0]=&A;
! 1920: U = matint_copy(U); gptr[1]=&U;
! 1921: if (DEBUGMEM>1) err(warnmem,"hnfall[1], li = %ld", li);
! 1922: gerepilemanysp(av1,tetpil,gptr,2);
! 1923: }
! 1924: }
! 1925: }
! 1926: x=gcoeff(A,li,j);
! 1927: if (signe(x))
! 1928: {
! 1929: r--;
! 1930: if (j<r)
! 1931: {
! 1932: z=A[j]; A[j]=A[r]; A[r]=z;
! 1933: z=U[j]; U[j]=U[r]; U[r]=z;
! 1934: h[j]=h[r]; h[r]=li; c[li]=r;
! 1935: }
! 1936: if (signe(gcoeff(A,li,r))<0)
! 1937: {
! 1938: p1=(GEN)A[r]; for (i=1; i<=li; i++) p1[i]=lnegi((GEN)p1[i]);
! 1939: p1=(GEN)U[r]; for (i=1; i<=n ; i++) p1[i]=lnegi((GEN)p1[i]);
! 1940: }
! 1941: p=gcoeff(A,li,r);
! 1942: for (j=r+1; j<=n; j++)
! 1943: {
! 1944: q = truedvmdii(gcoeff(A,li,j),p,NULL);
! 1945: if (signe(q))
! 1946: {
! 1947: q = negi(q);
! 1948: A[j]=(long)lincomb_integral(gun,q,(GEN)A[j],(GEN)A[r]);
! 1949: U[j]=(long)lincomb_integral(gun,q,(GEN)U[j],(GEN)U[r]);
! 1950: }
! 1951: }
! 1952: if (low_stack(lim, stack_lim(av1,1)))
! 1953: {
! 1954: GEN *gptr[2]; gptr[0]=&A; gptr[1]=&U;
! 1955: if (DEBUGMEM>1) err(warnmem,"hnfall[2], li = %ld", li);
! 1956: gerepilemany(av1,gptr,2);
! 1957: }
! 1958: break;
! 1959: }
! 1960: h[j]=li-1;
! 1961: }
! 1962: }
! 1963: if (DEBUGLEVEL>5) fprintferr("\nhnfall, final phase: ");
! 1964: r--; /* first r cols are in the image the n-r (independent) last ones */
! 1965: for (j=1; j<=r; j++)
! 1966: for (i=h[j]; i; i--)
! 1967: if (signe(b=gcoeff(A,i,j)))
! 1968: {
! 1969: k=c[i]; a=gcoeff(A,i,k);
! 1970: d=bezout(a,b,&u,&v);
! 1971: if (!is_pm1(d)) { a=divii(a,d); b=divii(b,d); }
! 1972: if (DEBUGLEVEL>5)
! 1973: { fprintferr("(u,v) = (%Z, %Z); ",u,v); flusherr(); }
! 1974: p1 = (GEN)A[k]; b = negi(b);
! 1975: A[k] = (long)lincomb_integral(u,v, p1,(GEN)A[j]);
! 1976: A[j] = (long)lincomb_integral(a,b, (GEN)A[j],p1);
! 1977: p1 = (GEN)U[k];
! 1978: U[k] = (long)lincomb_integral(u,v, p1,(GEN)U[j]);
! 1979: U[j] = (long)lincomb_integral(a,b, (GEN)U[j],p1);
! 1980: for (j1=k+1; j1<=n; j1++)
! 1981: {
! 1982: q=truedvmdii(gcoeff(A,i,j1),d,NULL);
! 1983: if (signe(q))
! 1984: {
! 1985: q = negi(q);
! 1986: A[j1] = (long)lincomb_integral(gun,q,(GEN)A[j1],(GEN)A[k]);
! 1987: U[j1] = (long)lincomb_integral(gun,q,(GEN)U[j1],(GEN)U[k]);
! 1988: }
! 1989: }
! 1990: if (low_stack(lim, stack_lim(av1,1)))
! 1991: {
! 1992: GEN *gptr[2]; tetpil = avma;
! 1993: A = matint_copy(A); gptr[0]=&A;
! 1994: U = matint_copy(U); gptr[1]=&U;
! 1995: if (DEBUGMEM>1) err(warnmem,"hnfall[3], j = %ld", j);
! 1996: gerepilemanysp(av1,tetpil,gptr,2);
! 1997: }
! 1998: }
! 1999: if (DEBUGLEVEL>5) fprintferr("\n");
! 2000: tetpil=avma; y=cgetg(3,t_VEC);
! 2001: if (remove)
! 2002: { /* remove the first r columns */
! 2003: A += r; A[0] = evaltyp(t_MAT) | evallg(n-r+1);
! 2004: }
! 2005: y[1]=lcopy(A); y[2]=lcopy(U);
! 2006: return gerepile(av,tetpil,y);
! 2007: }
! 2008:
! 2009: GEN
! 2010: hnfall(GEN x) {return hnfall0(x,1);}
! 2011:
! 2012: /***************************************************************/
! 2013: /** **/
! 2014: /** SMITH NORMAL FORM REDUCTION **/
! 2015: /** **/
! 2016: /***************************************************************/
! 2017:
! 2018: static GEN
! 2019: col_mul(GEN x, GEN c)
! 2020: {
! 2021: long s = signe(x);
! 2022: GEN xc = NULL;
! 2023: if (s)
! 2024: {
! 2025: if (!is_pm1(x)) xc = gmul(x,c);
! 2026: else xc = (s>0)? c: gneg_i(c);
! 2027: }
! 2028: return xc;
! 2029: }
! 2030:
! 2031: static void
! 2032: do_zero(GEN x)
! 2033: {
! 2034: long i, lx = lg(x);
! 2035: for (i=1; i<lx; i++) x[i] = zero;
! 2036: }
! 2037:
! 2038: /* c1 <-- u.c1 + v.c2; c2 <-- a.c2 - b.c1 */
! 2039: static void
! 2040: update(GEN u, GEN v, GEN a, GEN b, GEN *c1, GEN *c2)
! 2041: {
! 2042: GEN p1,p2;
! 2043:
! 2044: u = col_mul(u,*c1);
! 2045: v = col_mul(v,*c2);
! 2046: if (u) p1 = v? gadd(u,v): u;
! 2047: else p1 = v? v: (GEN)NULL;
! 2048:
! 2049: a = col_mul(a,*c2);
! 2050: b = col_mul(gneg_i(b),*c1);
! 2051: if (a) p2 = b? gadd(a,b): a;
! 2052: else p2 = b? b: (GEN)NULL;
! 2053:
! 2054: if (!p1) do_zero(*c1); else *c1 = p1;
! 2055: if (!p2) do_zero(*c2); else *c2 = p2;
! 2056: }
! 2057:
! 2058: static GEN
! 2059: trivsmith(long all)
! 2060: {
! 2061: GEN z;
! 2062: if (!all) return cgetg(1,t_VEC);
! 2063: z=cgetg(4,t_VEC);
! 2064: z[1]=lgetg(1,t_MAT);
! 2065: z[2]=lgetg(1,t_MAT);
! 2066: z[3]=lgetg(1,t_VEC); return z;
! 2067: }
! 2068:
! 2069: /* Return the smith normal form d of matrix x. If all != 0 return [d,u,v],
! 2070: * where d = u.x.v
! 2071: */
! 2072: static GEN
! 2073: smithall(GEN x, long all)
! 2074: {
! 2075: long av,tetpil,i,j,k,l,c,fl,n,s1,s2,lim;
! 2076: GEN p1,p2,p3,p4,z,b,u,v,d,ml,mr,mun,mdet,ys;
! 2077:
! 2078: if (typ(x)!=t_MAT) err(typeer,"smithall");
! 2079: if (DEBUGLEVEL>=9) outerr(x);
! 2080: n=lg(x)-1;
! 2081: if (!n) return trivsmith(all);
! 2082: if (lg(x[1]) != n+1) err(mattype1,"smithall");
! 2083: for (i=1; i<=n; i++)
! 2084: for (j=1; j<=n; j++)
! 2085: if (typ(coeff(x,i,j)) != t_INT)
! 2086: err(talker,"non integral matrix in smithall");
! 2087:
! 2088: av = avma; lim = stack_lim(av,1);
! 2089: x = dummycopy(x); mdet = detint(x);
! 2090: if (ishnfall(x)) { if (all) { ml=idmat(n); mr=idmat(n); } }
! 2091: else
! 2092: {
! 2093: if (signe(mdet))
! 2094: {
! 2095: p1=hnfmod(x,mdet);
! 2096: if (all) { ml=idmat(n); mr=gauss(x,p1); }
! 2097: }
! 2098: else
! 2099: {
! 2100: if (all)
! 2101: {
! 2102: p1 = hnfall0(x,0);
! 2103: ml = idmat(n); mr = (GEN)p1[2]; p1 = (GEN)p1[1];
! 2104: }
! 2105: else
! 2106: p1 = hnf0(x,0);
! 2107: }
! 2108: x = p1;
! 2109: }
! 2110: p1=cgetg(n+1,t_VEC); for (i=1; i<=n; i++) p1[i]=lnegi(gcoeff(x,i,i));
! 2111: p2=sindexsort(p1); ys=cgetg(n+1,t_MAT);
! 2112: for (j=1; j<=n; j++)
! 2113: {
! 2114: p1=cgetg(n+1,t_COL); ys[j]=(long)p1;
! 2115: for (i=1; i<=n; i++) p1[i]=coeff(x,p2[i],p2[j]);
! 2116: }
! 2117: x = ys;
! 2118: if (all)
! 2119: {
! 2120: p3=cgetg(n+1,t_MAT); p4=cgetg(n+1,t_MAT);
! 2121: for (j=1; j<=n; j++) { p3[j]=ml[p2[j]]; p4[j]=mr[p2[j]]; }
! 2122: ml=p3; mr=p4;
! 2123: }
! 2124: if (signe(mdet))
! 2125: {
! 2126: p1 = hnfmod(x,mdet);
! 2127: if (all) mr=gmul(mr,gauss(x,p1));
! 2128: }
! 2129: else
! 2130: {
! 2131: if (all)
! 2132: {
! 2133: p1 = hnfall0(x,0);
! 2134: mr = gmul(mr,(GEN)p1[2]); p1 = (GEN)p1[1];
! 2135: }
! 2136: else
! 2137: p1 = hnf0(x,0);
! 2138: }
! 2139: x=p1; mun = negi(gun);
! 2140:
! 2141: if (DEBUGLEVEL>7) {fprintferr("starting SNF loop");flusherr();}
! 2142: for (i=n; i>=2; i--)
! 2143: {
! 2144: if (DEBUGLEVEL>7) {fprintferr("\ni = %ld: ",i);flusherr();}
! 2145: for(;;)
! 2146: {
! 2147: c = 0;
! 2148: for (j=i-1; j>=1; j--)
! 2149: {
! 2150: p1=gcoeff(x,i,j); s1 = signe(p1);
! 2151: if (s1)
! 2152: {
! 2153: p2=gcoeff(x,i,i);
! 2154: if (!absi_cmp(p1,p2))
! 2155: {
! 2156: s2=signe(p2);
! 2157: if (s1 == s2) { d=p1; u=gun; p4=gun; }
! 2158: else
! 2159: {
! 2160: if (s2>0) { u = gun; p4 = mun; }
! 2161: else { u = mun; p4 = gun; }
! 2162: d=(s1>0)? p1: absi(p1);
! 2163: }
! 2164: v = gzero; p3 = u;
! 2165: }
! 2166: else { d=bezout(p2,p1,&u,&v); p3=divii(p2,d); p4=divii(p1,d); }
! 2167: for (k=1; k<=i; k++)
! 2168: {
! 2169: b=addii(mulii(u,gcoeff(x,k,i)),mulii(v,gcoeff(x,k,j)));
! 2170: coeff(x,k,j)=lsubii(mulii(p3,gcoeff(x,k,j)),
! 2171: mulii(p4,gcoeff(x,k,i)));
! 2172: coeff(x,k,i)=(long)b;
! 2173: }
! 2174: if (all) update(u,v,p3,p4,(GEN*)(mr+i),(GEN*)(mr+j));
! 2175: if (low_stack(lim, stack_lim(av,1)))
! 2176: {
! 2177: if (DEBUGMEM>1) err(warnmem,"[1]: smithall");
! 2178: if (all)
! 2179: {
! 2180: GEN *gptr[3]; gptr[0]=&x; gptr[1]=&ml; gptr[2]=&mr;
! 2181: gerepilemany(av,gptr,3);
! 2182: }
! 2183: else x=gerepileupto(av,gcopy(x));
! 2184: }
! 2185: }
! 2186: }
! 2187: if (DEBUGLEVEL>=8) {fprintferr("; ");flusherr();}
! 2188: for (j=i-1; j>=1; j--)
! 2189: {
! 2190: p1=gcoeff(x,j,i); s1 = signe(p1);
! 2191: if (s1)
! 2192: {
! 2193: p2=gcoeff(x,i,i);
! 2194: if (!absi_cmp(p1,p2))
! 2195: {
! 2196: s2 = signe(p2);
! 2197: if (s1 == s2) { d=p1; u=gun; p4=gun; }
! 2198: else
! 2199: {
! 2200: if (s2>0) { u = gun; p4 = mun; }
! 2201: else { u = mun; p4 = gun; }
! 2202: d=(s1>0)? p1: absi(p1);
! 2203: }
! 2204: v = gzero; p3 = u;
! 2205: }
! 2206: else { d=bezout(p2,p1,&u,&v); p3=divii(p2,d); p4=divii(p1,d); }
! 2207: for (k=1; k<=i; k++)
! 2208: {
! 2209: b=addii(mulii(u,gcoeff(x,i,k)),mulii(v,gcoeff(x,j,k)));
! 2210: coeff(x,j,k)=lsubii(mulii(p3,gcoeff(x,j,k)),
! 2211: mulii(p4,gcoeff(x,i,k)));
! 2212: coeff(x,i,k)=(long)b;
! 2213: }
! 2214: if (all) update(u,v,p3,p4,(GEN*)(ml+i),(GEN*)(ml+j));
! 2215: c = 1;
! 2216: }
! 2217: }
! 2218: if (!c)
! 2219: {
! 2220: b=gcoeff(x,i,i); fl=1;
! 2221: if (signe(b))
! 2222: {
! 2223: for (k=1; k<i && fl; k++)
! 2224: for (l=1; l<i && fl; l++)
! 2225: fl = (int)!signe(resii(gcoeff(x,k,l),b));
! 2226: /* cast to (int) necessary for gcc-2.95 on sparcv9-64 (IS) */
! 2227: if (!fl)
! 2228: {
! 2229: k--;
! 2230: for (l=1; l<=i; l++)
! 2231: coeff(x,i,l)=laddii(gcoeff(x,i,l),gcoeff(x,k,l));
! 2232: if (all) ml[i]=ladd((GEN)ml[i],(GEN)ml[k]);
! 2233: }
! 2234: }
! 2235: if (fl) break;
! 2236: }
! 2237: if (low_stack(lim, stack_lim(av,1)))
! 2238: {
! 2239: if (DEBUGMEM>1) err(warnmem,"[2]: smithall");
! 2240: if (all)
! 2241: {
! 2242: GEN *gptr[3]; gptr[0]=&x; gptr[1]=&ml; gptr[2]=&mr;
! 2243: gerepilemany(av,gptr,3);
! 2244: }
! 2245: else x=gerepileupto(av,gcopy(x));
! 2246: }
! 2247: }
! 2248: }
! 2249: if (DEBUGLEVEL>7) {fprintferr("\n");flusherr();}
! 2250: if (all)
! 2251: {
! 2252: for (k=1; k<=n; k++)
! 2253: if (signe(gcoeff(x,k,k))<0)
! 2254: { mr[k]=lneg((GEN)mr[k]); coeff(x,k,k)=lnegi(gcoeff(x,k,k)); }
! 2255: tetpil=avma; z=cgetg(4,t_VEC);
! 2256: z[1]=ltrans(ml); z[2]=lcopy(mr); z[3]=lcopy(x);
! 2257: return gerepile(av,tetpil,z);
! 2258: }
! 2259: tetpil=avma; z=cgetg(n+1,t_VEC); j=n;
! 2260: for (k=n; k; k--)
! 2261: if (signe(gcoeff(x,k,k))) z[j--]=labsi(gcoeff(x,k,k));
! 2262: for ( ; j; j--) z[j]=zero;
! 2263: return gerepile(av,tetpil,z);
! 2264: }
! 2265:
! 2266: GEN
! 2267: smith(GEN x) { return smithall(x,0); }
! 2268:
! 2269: GEN
! 2270: smith2(GEN x) { return smithall(x,1); }
! 2271:
! 2272: /* Assume z was computed by [g]smithall(). Remove the 1s on the diagonal */
! 2273: GEN
! 2274: smithclean(GEN z)
! 2275: {
! 2276: long i,j,l,c;
! 2277: GEN u,v,y,d,p1;
! 2278:
! 2279: if (typ(z) != t_VEC) err(typeer,"smithclean");
! 2280: l = lg(z); if (l == 1) return cgetg(1,t_VEC);
! 2281: u=(GEN)z[1];
! 2282: if (l != 4 || typ(u) != t_MAT)
! 2283: {
! 2284: if (typ(u) != t_INT) err(typeer,"smithclean");
! 2285: for (c=1; c<l; c++)
! 2286: if (gcmp1((GEN)z[c])) break;
! 2287: return gcopy_i(z, c);
! 2288: }
! 2289: v=(GEN)z[2]; d=(GEN)z[3]; l = lg(d);
! 2290: for (c=1; c<l; c++)
! 2291: if (gcmp1(gcoeff(d,c,c))) break;
! 2292:
! 2293: y=cgetg(4,t_VEC);
! 2294: y[1]=(long)(p1 = cgetg(l,t_MAT));
! 2295: for (i=1; i<l; i++) p1[i] = (long)gcopy_i((GEN)u[i], c);
! 2296: y[2]=(long)gcopy_i(v, c);
! 2297: y[3]=(long)(p1 = cgetg(c,t_MAT));
! 2298: for (i=1; i<c; i++)
! 2299: {
! 2300: GEN p2 = cgetg(c,t_COL); p1[i] = (long)p2;
! 2301: for (j=1; j<c; j++) p2[j] = i==j? lcopy(gcoeff(d,i,i)): zero;
! 2302: }
! 2303: return y;
! 2304: }
! 2305:
! 2306: static GEN
! 2307: gsmithall(GEN x,long all)
! 2308: {
! 2309: long av,tetpil,i,j,k,l,c,fl,n, lim;
! 2310: GEN p1,p2,p3,p4,z,b,u,v,d,ml,mr;
! 2311:
! 2312: if (typ(x)!=t_MAT) err(typeer,"gsmithall");
! 2313: n=lg(x)-1;
! 2314: if (!n) return trivsmith(all);
! 2315: if (lg(x[1]) != n+1) err(mattype1,"gsmithall");
! 2316: av = avma; lim = stack_lim(av,1);
! 2317: x = dummycopy(x);
! 2318: if (all) { ml=idmat(n); mr=idmat(n); }
! 2319: for (i=n; i>=2; i--)
! 2320: {
! 2321: do
! 2322: {
! 2323: c=0;
! 2324: for (j=i-1; j>=1; j--)
! 2325: {
! 2326: p1=gcoeff(x,i,j);
! 2327: if (signe(p1))
! 2328: {
! 2329: p2=gcoeff(x,i,i); v=gdiventres(p1,p2);
! 2330: if (gcmp0((GEN)v[2])) { d=p2; p4=(GEN)v[1]; v=gzero; p3=gun; u=gun; }
! 2331: else { d=gbezout(p2,p1,&u,&v); p3=gdiv(p2,d); p4=gdiv(p1,d); }
! 2332: for (k=1; k<=i; k++)
! 2333: {
! 2334: b=gadd(gmul(u,gcoeff(x,k,i)),gmul(v,gcoeff(x,k,j)));
! 2335: coeff(x,k,j)=lsub(gmul(p3,gcoeff(x,k,j)),gmul(p4,gcoeff(x,k,i)));
! 2336: coeff(x,k,i)=(long)b;
! 2337: }
! 2338: if (all) update(u,v,p3,p4,(GEN*)(mr+i),(GEN*)(mr+j));
! 2339: }
! 2340: }
! 2341: for (j=i-1; j>=1; j--)
! 2342: {
! 2343: p1=gcoeff(x,j,i);
! 2344: if (signe(p1))
! 2345: {
! 2346: p2=gcoeff(x,i,i); v=gdiventres(p1,p2);
! 2347: if (gcmp0((GEN)v[2])) { d=p2; p4=(GEN)v[1]; v=gzero; p3=gun; u=gun; }
! 2348: else { d=gbezout(p2,p1,&u,&v); p3=gdiv(p2,d); p4=gdiv(p1,d); }
! 2349: for (k=1; k<=i; k++)
! 2350: {
! 2351: b=gadd(gmul(u,gcoeff(x,i,k)),gmul(v,gcoeff(x,j,k)));
! 2352: coeff(x,j,k)=lsub(gmul(p3,gcoeff(x,j,k)),gmul(p4,gcoeff(x,i,k)));
! 2353: coeff(x,i,k)=(long)b;
! 2354: }
! 2355: if (all) update(u,v,p3,p4,(GEN*)(ml+i),(GEN*)(ml+j));
! 2356: c = 1;
! 2357: }
! 2358: }
! 2359: if (!c)
! 2360: {
! 2361: b=gcoeff(x,i,i); fl=1;
! 2362: if (signe(b))
! 2363: {
! 2364: for (k=1; (k<i)&&fl; k++)
! 2365: for (l=1; (l<i)&&fl; l++)
! 2366: fl= !signe(gmod(gcoeff(x,k,l),b));
! 2367: if (!fl)
! 2368: {
! 2369: k--;
! 2370: for (l=1; l<=i; l++)
! 2371: coeff(x,i,l)=ladd(gcoeff(x,i,l),gcoeff(x,k,l));
! 2372: if (all) ml[i]=ladd((GEN)ml[i],(GEN)ml[k]);
! 2373: }
! 2374: }
! 2375: }
! 2376: if (low_stack(lim, stack_lim(av,1)))
! 2377: {
! 2378: if (DEBUGMEM>1) err(warnmem,"[5]: smithall");
! 2379: tetpil=avma;
! 2380: if (all)
! 2381: {
! 2382: GEN *gptr[3]; gptr[0]=&x; gptr[1]=&ml; gptr[2]=&mr;
! 2383: gerepilemany(av,gptr,3);
! 2384: }
! 2385: else x=gerepile(av,tetpil,gcopy(x));
! 2386: }
! 2387: }
! 2388: while (c || !fl);
! 2389: }
! 2390: if (all)
! 2391: {
! 2392: for (k=1; k<=n; k++)
! 2393: if (signe(gcoeff(x,k,k))<0)
! 2394: { mr[k]=lneg((GEN)mr[k]); coeff(x,k,k)=lneg(gcoeff(x,k,k)); }
! 2395: tetpil=avma; z=cgetg(4,t_VEC);
! 2396: z[1]=ltrans(ml); z[2]=lcopy(mr); z[3]=lcopy(x);
! 2397: }
! 2398: else
! 2399: {
! 2400: tetpil=avma; z=cgetg(n+1,t_VEC);
! 2401: for (j=0,k=1; k<=n; k++) if (!signe(gcoeff(x,k,k))) z[++j]=zero;
! 2402: for (k=1; k<=n; k++)
! 2403: if (signe(p1=gcoeff(x,k,k))) z[++j]=(long)gabs(p1,0);
! 2404: }
! 2405: return gerepile(av,tetpil,z);
! 2406: }
! 2407:
! 2408: GEN
! 2409: matsnf0(GEN x,long flag)
! 2410: {
! 2411: long av = avma;
! 2412: if (flag > 7) err(flagerr,"matsnf");
! 2413: if (typ(x) == t_VEC && flag & 4) return smithclean(x);
! 2414: if (flag & 2) x = gsmithall(x,flag & 1);
! 2415: else x = smithall(x, flag & 1);
! 2416: if (flag & 4) x = smithclean(x);
! 2417: return gerepileupto(av, x);
! 2418: }
! 2419:
! 2420: GEN
! 2421: gsmith(GEN x) { return gsmithall(x,0); }
! 2422:
! 2423: GEN
! 2424: gsmith2(GEN x) { return gsmithall(x,1); }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>