Annotation of OpenXM_contrib/pari-2.2/src/basemath/alglin2.c, Revision 1.1.1.1
1.1 noro 1: /* $Id: alglin2.c,v 1.32 2001/10/01 12:11:28 karim Exp $
2:
3: Copyright (C) 2000 The PARI group.
4:
5: This file is part of the PARI/GP package.
6:
7: PARI/GP is free software; you can redistribute it and/or modify it under the
8: terms of the GNU General Public License as published by the Free Software
9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
10: ANY WARRANTY WHATSOEVER.
11:
12: Check the License for details. You should have received a copy of it, along
13: with the package; see the file 'COPYING'. If not, write to the Free Software
14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
15:
16: /********************************************************************/
17: /** **/
18: /** LINEAR ALGEBRA **/
19: /** (second part) **/
20: /** **/
21: /********************************************************************/
22: #include "pari.h"
23:
24: /*******************************************************************/
25: /* */
26: /* CHARACTERISTIC POLYNOMIAL */
27: /* */
28: /*******************************************************************/
29:
30: GEN
31: charpoly0(GEN x, int v, long flag)
32: {
33: if (v<0) v = 0;
34: switch(flag)
35: {
36: case 0: return caradj(x,v,0);
37: case 1: return caract(x,v);
38: case 2: return carhess(x,v);
39: }
40: err(flagerr,"charpoly"); return NULL; /* not reached */
41: }
42:
43: static GEN
44: caract2_i(GEN p, GEN x, int v, GEN (subres_f)(GEN,GEN,GEN*))
45: {
46: long av = avma, d;
47: GEN p1, p2 = leading_term(p);
48:
49: if (!signe(x)) return gpowgs(polx[v], degpol(p));
50: if (typ(x) != t_POL) x = scalarpol(x,v);
51: x = gneg_i(x); x[2] = ladd((GEN)x[2], polx[MAXVARN]);
52: p1=subres_f(p, x, NULL);
53: if (typ(p1) == t_POL && varn(p1)==MAXVARN)
54: setvarn(p1,v);
55: else
56: p1 = gsubst(p1,MAXVARN,polx[v]);
57:
58: if (!gcmp1(p2) && (d=degpol(x)) > 0) p1 = gdiv(p1, gpuigs(p2,d));
59: return gerepileupto(av,p1);
60: }
61:
62: /* return caract(Mod(x,p)) in variable v */
63: GEN
64: caract2(GEN p, GEN x, int v)
65: {
66: return caract2_i(p,x,v, subresall);
67: }
68: GEN
69: caractducos(GEN p, GEN x, int v)
70: {
71: return caract2_i(p,x,v, (GEN (*)(GEN,GEN,GEN*))resultantducos);
72: }
73:
74: /* characteristic pol. Easy cases. Return NULL in case it's not so easy. */
75: static GEN
76: easychar(GEN x, int v, GEN *py)
77: {
78: long l,tetpil,lx;
79: GEN p1,p2;
80:
81: switch(typ(x))
82: {
83: case t_INT: case t_REAL: case t_INTMOD:
84: case t_FRAC: case t_FRACN: case t_PADIC:
85: p1=cgetg(4,t_POL);
86: p1[1]=evalsigne(1) | evallgef(4) | evalvarn(v);
87: p1[2]=lneg(x); p1[3]=un;
88: if (py)
89: {
90: p2=cgetg(2,t_MAT);
91: p2[1]=lgetg(2,t_COL);
92: coeff(p2,1,1)=lcopy(x);
93: *py=p2;
94: }
95: return p1;
96:
97: case t_COMPLEX: case t_QUAD:
98: if (py) err(typeer,"easychar");
99: p1=cgetg(5,t_POL);
100: p1[1]=evalsigne(1) | evallgef(5) | evalvarn(v);
101: p1[2]=lnorm(x); l=avma; p2=gtrace(x); tetpil=avma;
102: p1[3]=lpile(l,tetpil,gneg(p2));
103: p1[4]=un; return p1;
104:
105: case t_POLMOD:
106: if (py) err(typeer,"easychar");
107: return caract2((GEN)x[1], (GEN)x[2], v);
108:
109: case t_MAT:
110: lx=lg(x);
111: if (lx==1)
112: {
113: if (py) *py = cgetg(1,t_MAT);
114: return polun[v];
115: }
116: if (lg(x[1]) != lx) break;
117: return NULL;
118: }
119: err(mattype1,"easychar");
120: return NULL; /* not reached */
121: }
122:
123: GEN
124: caract(GEN x, int v)
125: {
126: long n,k,l=avma,tetpil;
127: GEN p1,p2,p3,p4,p5,p6;
128:
129: if ((p1 = easychar(x,v,NULL))) return p1;
130:
131: p1=gzero; p2=gun;
132: n=lg(x)-1; if (n&1) p2=gneg_i(p2);
133: p4=cgetg(3,t_RFRACN); p5=dummycopy(polx[v]); p4[2]=(long)p5;
134: p6=cgeti(3); p6[1] = evalsigne(-1) | evallgefint(3);
135: for (k=0; k<=n; k++)
136: {
137: p3=det(gsub(gscalmat(stoi(k),n), x));
138: p4[1]=lmul(p3,p2); p6[2]=k;
139: p1=gadd(p4,p1); p5[2]=(long)p6;
140: if (k!=n) p2=gdivgs(gmulsg(k-n,p2),k+1);
141: }
142: p2=mpfact(n); tetpil=avma;
143: return gerepile(l,tetpil,gdiv((GEN) p1[1],p2));
144: }
145:
146: GEN
147: caradj0(GEN x, long v)
148: {
149: return caradj(x,v,NULL);
150: }
151:
152: /* Using traces: return the characteristic polynomial of x (in variable v).
153: * If py != NULL, the adjoint matrix is put there.
154: */
155: GEN
156: caradj(GEN x, long v, GEN *py)
157: {
158: long i,j,k,l,av,tetpil;
159: GEN p,y,t,*gptr[2];
160:
161: if ((p = easychar(x,v,py))) return p;
162:
163: l=lg(x);
164: if (l==1) { p=polun[v]; if (py) *py=gcopy(x); return p; }
165: if (l==2) { p=gsub(polx[v],gtrace(x)); if (py) *py=idmat(1); return p; }
166:
167: p=cgetg(l+2,t_POL); p[1]=evalsigne(1) | evallgef(l+2) | evalvarn(v);
168: av=avma; t=gtrace(x); tetpil=avma;
169: t=gerepile(av,tetpil,gneg(t));
170: p[l]=(long)t; p[l+1]=un;
171:
172: av=avma; y=cgetg(l,t_MAT);
173: for (j=1; j<l; j++)
174: {
175: y[j]=lgetg(l,t_COL);
176: for (i=1; i<l; i++)
177: coeff(y,i,j) = (i==j) ? ladd(gcoeff(x,i,j),t) : coeff(x,i,j);
178: }
179:
180: for (k=2; k<l-1; k++)
181: {
182: GEN z=gmul(x,y);
183:
184: t=gtrace(z); tetpil=avma;
185: t=gdivgs(t,-k); y=cgetg(l,t_MAT);
186: for (j=1; j<l; j++)
187: {
188: y[j]=lgetg(l,t_COL);
189: for (i=1;i<l;i++)
190: coeff(y,i,j) = (i==j)? ladd(gcoeff(z,i,i),t): lcopy(gcoeff(z,i,j));
191: }
192: gptr[0]=&y; gptr[1]=&t;
193: gerepilemanysp(av,tetpil,gptr,2);
194: p[l-k+1]=(long)t; av=avma;
195: }
196:
197: t=gzero;
198: for (i=1; i<l; i++)
199: t=gadd(t,gmul(gcoeff(x,1,i),gcoeff(y,i,1)));
200: tetpil=avma; t=gneg(t);
201:
202: if (py)
203: {
204: *py = (l&1) ? gneg(y) : gcopy(y);
205: gptr[0] = &t; gptr[1] = py;
206: gerepilemanysp(av,tetpil,gptr,2);
207: p[2]=(long)t;
208: }
209: else p[2]=lpile(av,tetpil,t);
210: i = gvar2(p);
211: if (i == v) err(talker,"incorrect variable in caradj");
212: if (i < v) p = poleval(p, polx[v]);
213: return p;
214: }
215:
216: GEN
217: adj(GEN x)
218: {
219: GEN y;
220: caradj(x,MAXVARN,&y); return y;
221: }
222:
223: /*******************************************************************/
224: /* */
225: /* HESSENBERG FORM */
226: /* */
227: /*******************************************************************/
228: #define swap(x,y) { long _t=x; x=y; y=_t; }
229: #define gswap(x,y) { GEN _t=x; x=y; y=_t; }
230:
231: GEN
232: hess(GEN x)
233: {
234: ulong av = avma;
235: long lx=lg(x),m,i,j;
236: GEN p,p1,p2;
237:
238: if (typ(x) != t_MAT) err(mattype1,"hess");
239: if (lx==1) return cgetg(1,t_MAT);
240: if (lg(x[1])!=lx) err(mattype1,"hess");
241: x = dummycopy(x);
242:
243: for (m=2; m<lx-1; m++)
244: for (i=m+1; i<lx; i++)
245: {
246: p = gcoeff(x,i,m-1);
247: if (gcmp0(p)) continue;
248:
249: for (j=m-1; j<lx; j++) swap(coeff(x,i,j), coeff(x,m,j));
250: swap(x[i], x[m]); p = ginv(p);
251: for (i=m+1; i<lx; i++)
252: {
253: p1 = gcoeff(x,i,m-1);
254: if (gcmp0(p1)) continue;
255:
256: p1 = gmul(p1,p); p2 = gneg_i(p1);
257: coeff(x,i,m-1) = zero;
258: for (j=m; j<lx; j++)
259: coeff(x,i,j) = ladd(gcoeff(x,i,j), gmul(p2,gcoeff(x,m,j)));
260: for (j=1; j<lx; j++)
261: coeff(x,j,m) = ladd(gcoeff(x,j,m), gmul(p1,gcoeff(x,j,i)));
262: }
263: break;
264: }
265: return gerepilecopy(av,x);
266: }
267:
268: GEN
269: carhess(GEN x, long v)
270: {
271: long av,tetpil,lx,r,i;
272: GEN *y,p1,p2,p3,p4;
273:
274: if ((p1 = easychar(x,v,NULL))) return p1;
275:
276: lx=lg(x); av=avma; y = (GEN*) new_chunk(lx);
277: y[0]=polun[v]; p1=hess(x); p2=polx[v];
278: tetpil=avma;
279: for (r=1; r<lx; r++)
280: {
281: y[r]=gmul(y[r-1], gsub(p2,gcoeff(p1,r,r)));
282: p3=gun; p4=gzero;
283: for (i=r-1; i; i--)
284: {
285: p3=gmul(p3,gcoeff(p1,i+1,i));
286: p4=gadd(p4,gmul(gmul(p3,gcoeff(p1,i,r)),y[i-1]));
287: }
288: tetpil=avma; y[r]=gsub(y[r],p4);
289: }
290: return gerepile(av,tetpil,y[lx-1]);
291: }
292:
293: /*******************************************************************/
294: /* */
295: /* NORM */
296: /* */
297: /*******************************************************************/
298:
299: GEN
300: gnorm(GEN x)
301: {
302: long l,lx,i,tetpil, tx=typ(x);
303: GEN p1,p2,y;
304:
305: switch(tx)
306: {
307: case t_INT:
308: return sqri(x);
309:
310: case t_REAL:
311: return mulrr(x,x);
312:
313: case t_FRAC: case t_FRACN:
314: return gsqr(x);
315:
316: case t_COMPLEX:
317: l=avma; p1=gsqr((GEN) x[1]); p2=gsqr((GEN) x[2]);
318: tetpil=avma; return gerepile(l,tetpil,gadd(p1,p2));
319:
320: case t_QUAD:
321: l=avma; p1=(GEN)x[1];
322: p2=gmul((GEN) p1[2], gsqr((GEN) x[3]));
323: p1 = gcmp0((GEN) p1[3])? gsqr((GEN) x[2])
324: : gmul((GEN) x[2], gadd((GEN) x[2],(GEN) x[3]));
325: tetpil=avma; return gerepile(l,tetpil,gadd(p1,p2));
326:
327: case t_POL: case t_SER: case t_RFRAC: case t_RFRACN:
328: l=avma; p1=gmul(gconj(x),x); tetpil=avma;
329: return gerepile(l,tetpil,greal(p1));
330:
331: case t_POLMOD:
332: p1=(GEN)x[1]; p2=leading_term(p1);
333: if (gcmp1(p2) || gcmp0((GEN) x[2])) return subres(p1,(GEN) x[2]);
334: l=avma; y=subres(p1,(GEN)x[2]); p1=gpuigs(p2,degpol(x[2]));
335: tetpil=avma; return gerepile(l,tetpil,gdiv(y,p1));
336:
337: case t_VEC: case t_COL: case t_MAT:
338: lx=lg(x); y=cgetg(lx,tx);
339: for (i=1; i<lx; i++) y[i]=lnorm((GEN) x[i]);
340: return y;
341: }
342: err(typeer,"gnorm");
343: return NULL; /* not reached */
344: }
345:
346: GEN
347: gnorml2(GEN x)
348: {
349: GEN y;
350: long i,tx=typ(x),lx,av,lim;
351:
352: if (! is_matvec_t(tx)) return gnorm(x);
353: lx=lg(x); if (lx==1) return gzero;
354:
355: av=avma; lim = stack_lim(av,1); y = gnorml2((GEN) x[1]);
356: for (i=2; i<lx; i++)
357: {
358: y = gadd(y, gnorml2((GEN) x[i]));
359: if (low_stack(lim, stack_lim(av,1)))
360: {
361: if (DEBUGMEM>1) err(warnmem,"gnorml2");
362: y = gerepileupto(av, y);
363: }
364: }
365: return gerepileupto(av,y);
366: }
367:
368: GEN
369: QuickNormL2(GEN x, long prec)
370: {
371: long av = avma;
372: GEN y = gmul(x, realun(prec));
373: if (typ(x) == t_POL)
374: *++y = evaltyp(t_VEC) | evallg(lgef(x)-1);
375: return gerepileupto(av, gnorml2(y));
376: }
377:
378: GEN
379: gnorml1(GEN x,long prec)
380: {
381: ulong av = avma;
382: long lx,i;
383: GEN s;
384: switch(typ(x))
385: {
386: case t_INT: case t_REAL: case t_COMPLEX: case t_FRAC:
387: case t_FRACN: case t_QUAD:
388: return gabs(x,prec);
389:
390: case t_POL:
391: lx = lgef(x); s = gzero;
392: for (i=2; i<lx; i++) s = gadd(s, gabs((GEN)x[i],prec));
393: break;
394:
395: case t_VEC: case t_COL: case t_MAT:
396: lx = lg(x); s = gzero;
397: for (i=1; i<lx; i++) s = gadd(s, gabs((GEN)x[i],prec));
398: break;
399:
400: default: err(typeer,"gnorml1");
401: return NULL; /* not reached */
402: }
403: return gerepileupto(av, s);
404: }
405:
406: GEN
407: QuickNormL1(GEN x,long prec)
408: {
409: ulong av = avma;
410: long lx,i;
411: GEN p1,p2,s;
412: switch(typ(x))
413: {
414: case t_INT: case t_REAL: case t_FRAC: case t_FRACN:
415: return gabs(x,prec);
416:
417: case t_INTMOD: case t_PADIC: case t_POLMOD:
418: case t_SER: case t_RFRAC: case t_RFRACN:
419: return gcopy(x);
420:
421: case t_COMPLEX:
422: p1=gabs((GEN)x[1],prec); p2=gabs((GEN)x[2],prec);
423: return gerepileupto(av, gadd(p1,p2));
424:
425: case t_QUAD:
426: p1=gabs((GEN)x[2],prec); p2=gabs((GEN)x[3],prec);
427: return gerepileupto(av, gadd(p1,p2));
428:
429: case t_POL:
430: lx=lg(x); s=gzero;
431: for (i=2; i<lx; i++) s=gadd(s,QuickNormL1((GEN)x[i],prec));
432: return gerepileupto(av, s);
433:
434: case t_VEC: case t_COL: case t_MAT:
435: lx=lg(x); s=gzero;
436: for (i=1; i<lx; i++) s=gadd(s,QuickNormL1((GEN)x[i],prec));
437: return gerepileupto(av, s);
438: }
439: err(typeer,"QuickNormL1");
440: return NULL; /* not reached */
441: }
442:
443: /*******************************************************************/
444: /* */
445: /* CONJUGATION */
446: /* */
447: /*******************************************************************/
448:
449: GEN
450: gconj(GEN x)
451: {
452: long lx,i,tx=typ(x);
453: GEN z;
454:
455: switch(tx)
456: {
457: case t_INT: case t_REAL: case t_INTMOD:
458: case t_FRAC: case t_FRACN: case t_PADIC:
459: return gcopy(x);
460:
461: case t_COMPLEX:
462: z=cgetg(3,t_COMPLEX);
463: z[1]=lcopy((GEN) x[1]);
464: z[2]=lneg((GEN) x[2]);
465: break;
466:
467: case t_QUAD:
468: z=cgetg(4,t_QUAD);
469: copyifstack(x[1],z[1]);
470: z[2]=gcmp0(gmael(x,1,3))? lcopy((GEN) x[2])
471: : ladd((GEN) x[2],(GEN) x[3]);
472: z[3]=lneg((GEN) x[3]);
473: break;
474:
475: case t_POL:
476: lx=lgef(x); z=cgetg(lx,tx); z[1]=x[1];
477: for (i=2; i<lx; i++) z[i]=lconj((GEN) x[i]);
478: break;
479:
480: case t_SER:
481: lx=lg(x); z=cgetg(lx,tx); z[1]=x[1];
482: for (i=2; i<lx; i++) z[i]=lconj((GEN) x[i]);
483: break;
484:
485: case t_RFRAC: case t_RFRACN: case t_VEC: case t_COL: case t_MAT:
486: lx=lg(x); z=cgetg(lx,tx);
487: for (i=1; i<lx; i++) z[i]=lconj((GEN) x[i]);
488: break;
489:
490: default:
491: err(typeer,"gconj");
492: return NULL; /* not reached */
493: }
494: return z;
495: }
496:
497: GEN
498: conjvec(GEN x,long prec)
499: {
500: long lx,s,av,tetpil,i,tx=typ(x);
501: GEN z,y,p1,p2,p;
502:
503: switch(tx)
504: {
505: case t_INT: case t_INTMOD: case t_FRAC: case t_FRACN:
506: z=cgetg(2,t_COL); z[1]=lcopy(x); break;
507:
508: case t_COMPLEX: case t_QUAD:
509: z=cgetg(3,t_COL); z[1]=lcopy(x); z[2]=lconj(x); break;
510:
511: case t_VEC: case t_COL:
512: lx=lg(x); z=cgetg(lx,t_MAT);
513: for (i=1; i<lx; i++) z[i]=(long)conjvec((GEN)x[i],prec);
514: s=lg(z[1]);
515: for (i=2; i<lx; i++)
516: if (lg(z[i])!=s) err(talker,"incompatible field degrees in conjvec");
517: break;
518:
519: case t_POLMOD:
520: y=(GEN)x[1]; lx=lgef(y);
521: if (lx<=3) return cgetg(1,t_COL);
522: av=avma; p=NULL;
523: for (i=2; i<lx; i++)
524: {
525: tx=typ(y[i]);
526: if (tx==t_INTMOD) p=gmael(y,i,1);
527: else
528: if (tx != t_INT && ! is_frac_t(tx))
529: err(polrationer,"conjvec");
530: }
531: if (!p)
532: {
533: p1=roots(y,prec); x = (GEN)x[2]; tetpil=avma;
534: z=cgetg(lx-2,t_COL);
535: for (i=1; i<=lx-3; i++)
536: {
537: p2=(GEN)p1[i]; if (gcmp0((GEN)p2[2])) p2 = (GEN)p2[1];
538: z[i] = (long)poleval(x, p2);
539: }
540: return gerepile(av,tetpil,z);
541: }
542: z=cgetg(lx-2,t_COL); z[1]=lcopy(x);
543: for (i=2; i<=lx-3; i++) z[i] = lpui((GEN) z[i-1],p,prec);
544: break;
545:
546: default:
547: err(typeer,"conjvec");
548: return NULL; /* not reached */
549: }
550: return z;
551: }
552:
553: /*******************************************************************/
554: /* */
555: /* TRACES */
556: /* */
557: /*******************************************************************/
558:
559: GEN
560: assmat(GEN x)
561: {
562: long lx,i,j;
563: GEN y,p1,p2;
564:
565: if (typ(x)!=t_POL) err(notpoler,"assmat");
566: if (gcmp0(x)) err(zeropoler,"assmat");
567:
568: lx=lgef(x)-2; y=cgetg(lx,t_MAT);
569: for (i=1; i<lx-1; i++)
570: {
571: p1=cgetg(lx,t_COL); y[i]=(long)p1;
572: for (j=1; j<lx; j++)
573: p1[j] = (j==(i+1))? un: zero;
574: }
575: p1=cgetg(lx,t_COL); y[i]=(long)p1;
576: if (gcmp1((GEN) x[lx+1]))
577: for (j=1; j<lx; j++)
578: p1[j] = lneg((GEN)x[j+1]);
579: else
580: {
581: p2 = (GEN)x[lx+1]; gnegz(p2,p2);
582: for (j=1; j<lx; j++)
583: p1[j] = ldiv((GEN)x[j+1],p2);
584: gnegz(p2,p2);
585: }
586: return y;
587: }
588:
589: GEN
590: gtrace(GEN x)
591: {
592: long i,l,n,tx=typ(x),lx,tetpil;
593: GEN y,p1,p2;
594:
595: switch(tx)
596: {
597: case t_INT: case t_REAL: case t_FRAC: case t_FRACN:
598: return gmul2n(x,1);
599:
600: case t_COMPLEX:
601: return gmul2n((GEN)x[1],1);
602:
603: case t_QUAD:
604: p1=(GEN)x[1];
605: if (!gcmp0((GEN) p1[3]))
606: {
607: l=avma; p2=gmul2n((GEN)x[2],1);
608: tetpil=avma; return gerepile(l,tetpil,gadd((GEN)x[3],p2));
609: }
610: return gmul2n((GEN)x[2],1);
611:
612: case t_POL:
613: lx=lgef(x); y=cgetg(lx,tx); y[1]=x[1];
614: for (i=2; i<lx; i++) y[i]=ltrace((GEN)x[i]);
615: return y;
616:
617: case t_SER:
618: lx=lg(x); y=cgetg(lx,tx); y[1]=x[1];
619: for (i=2; i<lx; i++) y[i]=ltrace((GEN)x[i]);
620: return y;
621:
622: case t_POLMOD:
623: l=avma; n=(lgef(x[1])-4);
624: p1=polsym((GEN)x[1],n); p2=gzero;
625: for (i=0; i<=n; i++)
626: p2=gadd(p2,gmul(truecoeff((GEN)x[2],i),(GEN)p1[i+1]));
627: return gerepileupto(l,p2);
628:
629: case t_RFRAC: case t_RFRACN:
630: return gadd(x,gconj(x));
631:
632: case t_VEC: case t_COL:
633: lx=lg(x); y=cgetg(lx,tx);
634: for (i=1; i<lx; i++) y[i]=ltrace((GEN)x[i]);
635: return y;
636:
637: case t_MAT:
638: lx=lg(x); if (lx==1) return gzero;/*now lx>=2*/
639: if (lx!=lg(x[1])) err(mattype1,"gtrace");
640: l=avma; p1=gcoeff(x,1,1); if (lx==2) return gcopy(p1);
641: for (i=2; i<lx-1; i++)
642: p1=gadd(p1,gcoeff(x,i,i));
643: tetpil=avma; return gerepile(l,tetpil,gadd(p1,gcoeff(x,i,i)));
644:
645: }
646: err(typeer,"gtrace");
647: return NULL; /* not reached */
648: }
649:
650: /* Gauss reduction for positive definite matrix a
651: * If a is not positive definite:
652: * if flag is zero: raise an error
653: * else: return NULL.
654: */
655: GEN
656: sqred1intern(GEN a,long flag)
657: {
658: GEN b,p;
659: long i,j,k, n = lg(a);
660: ulong av = avma, lim=stack_lim(av,1);
661:
662: if (typ(a)!=t_MAT) err(typeer,"sqred1");
663: if (n == 1) return cgetg(1, t_MAT);
664: if (lg(a[1])!=n) err(mattype1,"sqred1");
665: b=cgetg(n,t_MAT);
666: for (j=1; j<n; j++)
667: {
668: GEN p1=cgetg(n,t_COL), p2=(GEN)a[j];
669:
670: b[j]=(long)p1;
671: for (i=1; i<=j; i++) p1[i] = p2[i];
672: for ( ; i<n ; i++) p1[i] = zero;
673: }
674: for (k=1; k<n; k++)
675: {
676: p = gcoeff(b,k,k);
677: if (gsigne(p)<=0) /* not positive definite */
678: {
679: if (flag) { avma=av; return NULL; }
680: err(talker,"not a positive definite matrix in sqred1");
681: }
682: p = ginv(p);
683: for (i=k+1; i<n; i++)
684: for (j=i; j<n; j++)
685: coeff(b,i,j)=lsub(gcoeff(b,i,j),
686: gmul(gmul(gcoeff(b,k,i),gcoeff(b,k,j)), p));
687: for (j=k+1; j<n; j++)
688: coeff(b,k,j)=lmul(gcoeff(b,k,j), p);
689: if (low_stack(lim, stack_lim(av,1)))
690: {
691: if (DEBUGMEM>1) err(warnmem,"sqred1");
692: b=gerepilecopy(av,b);
693: }
694: }
695: return gerepilecopy(av,b);
696: }
697:
698: GEN
699: sqred1(GEN a)
700: {
701: return sqred1intern(a,0);
702: }
703:
704: GEN
705: sqred3(GEN a)
706: {
707: ulong av = avma, lim = stack_lim(av,1);
708: long i,j,k,l, n = lg(a);
709: GEN p1,b;
710:
711: if (typ(a)!=t_MAT) err(typeer,"sqred3");
712: if (lg(a[1])!=n) err(mattype1,"sqred3");
713: av=avma; b=cgetg(n,t_MAT);
714: for (j=1; j<n; j++)
715: {
716: p1=cgetg(n,t_COL); b[j]=(long)p1;
717: for (i=1; i<n; i++) p1[i]=zero;
718: }
719: for (i=1; i<n; i++)
720: {
721: for (k=1; k<i; k++)
722: {
723: p1=gzero;
724: for (l=1; l<k; l++)
725: p1=gadd(p1, gmul(gmul(gcoeff(b,l,l),gcoeff(b,k,l)), gcoeff(b,i,l)));
726: coeff(b,i,k)=ldiv(gsub(gcoeff(a,i,k),p1),gcoeff(b,k,k));
727: }
728: p1=gzero;
729: for (l=1; l<i; l++)
730: p1=gadd(p1, gmul(gcoeff(b,l,l), gsqr(gcoeff(b,i,l))));
731: coeff(b,i,k)=lsub(gcoeff(a,i,i),p1);
732: if (low_stack(lim, stack_lim(av,1)))
733: {
734: if (DEBUGMEM>1) err(warnmem,"sqred3");
735: b=gerepilecopy(av,b);
736: }
737: }
738: return gerepilecopy(av,b);
739: }
740:
741: /* Gauss reduction (arbitrary symetric matrix, only the part above the
742: * diagonal is considered). If no_signature is zero, return only the
743: * signature
744: */
745: static GEN
746: sqred2(GEN a, long no_signature)
747: {
748: GEN r,p,mun;
749: ulong av,av1,lim;
750: long n,i,j,k,l,sp,sn,t;
751:
752: if (typ(a)!=t_MAT) err(typeer,"sqred2");
753: n=lg(a); if (lg(a[1]) != n) err(mattype1,"sqred2");
754:
755: av=avma; mun=negi(gun); r=new_chunk(n);
756: for (i=1; i<n; i++) r[i]=1;
757: av1=avma; lim=stack_lim(av1,1); a=dummycopy(a);
758: n--; t=n; sp=sn=0;
759: while (t)
760: {
761: k=1; while (k<=n && (gcmp0(gcoeff(a,k,k)) || !r[k])) k++;
762: if (k<=n)
763: {
764: p=gcoeff(a,k,k); if (gsigne(p)>0) sp++; else sn++;
765: r[k]=0; t--;
766: for (j=1; j<=n; j++)
767: coeff(a,k,j)=r[j] ? ldiv(gcoeff(a,k,j),p) : zero;
768:
769: for (i=1; i<=n; i++) if (r[i])
770: for (j=1; j<=n; j++)
771: coeff(a,i,j) = r[j] ? lsub(gcoeff(a,i,j),
772: gmul(gmul(gcoeff(a,k,i),gcoeff(a,k,j)),p))
773: : zero;
774: coeff(a,k,k)=(long)p;
775: }
776: else
777: {
778: for (k=1; k<=n; k++) if (r[k])
779: {
780: l=k+1; while (l<=n && (gcmp0(gcoeff(a,k,l)) || !r[l])) l++;
781: if (l<=n)
782: {
783: p=gcoeff(a,k,l); r[k]=r[l]=0; sp++; sn++; t-=2;
784: for (i=1; i<=n; i++) if (r[i])
785: {
786: for (j=1; j<=n; j++)
787: coeff(a,i,j) =
788: r[j]? lsub(gcoeff(a,i,j),
789: gdiv(gadd(gmul(gcoeff(a,k,i),gcoeff(a,l,j)),
790: gmul(gcoeff(a,k,j),gcoeff(a,l,i))),
791: p))
792: : zero;
793: coeff(a,k,i)=ldiv(gadd(gcoeff(a,k,i),gcoeff(a,l,i)),p);
794: coeff(a,l,i)=ldiv(gsub(gcoeff(a,k,i),gcoeff(a,l,i)),p);
795: }
796: coeff(a,k,l)=un; coeff(a,l,k)=(long)mun;
797: coeff(a,k,k)=lmul2n(p,-1); coeff(a,l,l)=lneg(gcoeff(a,k,k));
798: if (low_stack(lim, stack_lim(av1,1)))
799: {
800: if(DEBUGMEM>1) err(warnmem,"sqred2");
801: a=gerepilecopy(av1,a);
802: }
803: break;
804: }
805: }
806: if (k>n) break;
807: }
808: }
809: if (no_signature) return gerepilecopy(av,a);
810: avma=av;
811: a=cgetg(3,t_VEC); a[1]=lstoi(sp); a[2]=lstoi(sn); return a;
812: }
813:
814: GEN
815: sqred(GEN a) { return sqred2(a,1); }
816:
817: GEN
818: signat(GEN a) { return sqred2(a,0); }
819:
820: /* Diagonalization of a REAL symetric matrix. Return a 2-component vector:
821: * 1st comp = vector of eigenvalues
822: * 2nd comp = matrix of eigenvectors
823: */
824: GEN
825: jacobi(GEN a, long prec)
826: {
827: long de,e,e1,e2,l,n,i,j,p,q,av1,av2;
828: GEN c,s,t,u,ja,lambda,r,unr,x,y,x1,y1;
829:
830: if (typ(a)!=t_MAT) err(mattype1,"jacobi");
831: ja=cgetg(3,t_VEC); l=lg(a); n=l-1;
832: e1=HIGHEXPOBIT-1;
833: lambda=cgetg(l,t_COL); ja[1]=(long)lambda;
834: for (j=1; j<=n; j++)
835: {
836: lambda[j]=lgetr(prec);
837: gaffect(gcoeff(a,j,j), (GEN)lambda[j]);
838: e=expo(lambda[j]); if (e<e1) e1=e;
839: }
840: r=cgetg(l,t_MAT); ja[2]=(long)r;
841: for (j=1; j<=n; j++)
842: {
843: r[j]=lgetg(l,t_COL);
844: for (i=1; i<=n; i++)
845: affsr(i==j, (GEN)(coeff(r,i,j)=lgetr(prec)));
846: }
847: av1=avma;
848:
849: e2=-HIGHEXPOBIT;p=q=1;
850: c=cgetg(l,t_MAT);
851: for (j=1; j<=n; j++)
852: {
853: c[j]=lgetg(j,t_COL);
854: for (i=1; i<j; i++)
855: {
856: gaffect(gcoeff(a,i,j), (GEN)(coeff(c,i,j)=lgetr(prec)));
857: e=expo(gcoeff(c,i,j)); if (e>e2) { e2=e; p=i; q=j; }
858: }
859: }
860: a=c; unr = realun(prec);
861: de=bit_accuracy(prec);
862:
863: /* e1 = min des expo des coeff diagonaux
864: * e2 = max des expo des coeff extra-diagonaux
865: * Test d'arret: e2 < e1-precision
866: */
867: while (e1-e2<de)
868: {
869: /*calcul de la rotation associee dans le plan
870: des p et q-iemes vecteurs de base */
871: av2=avma;
872: x=divrr(subrr((GEN)lambda[q],(GEN)lambda[p]),shiftr(gcoeff(a,p,q),1));
873: y=mpsqrt(addrr(unr,mulrr(x,x)));
874: t=(gsigne(x)>0)? divrr(unr,addrr(x,y)) : divrr(unr,subrr(x,y));
875: c=divrr(unr,mpsqrt(addrr(unr,mulrr(t,t))));
876: s=mulrr(t,c); u=divrr(s,addrr(unr,c));
877:
878: /* Recalcul des transformees successives de a et de la matrice
879: cumulee (r) des rotations : */
880:
881: for (i=1; i<p; i++)
882: {
883: x=gcoeff(a,i,p); y=gcoeff(a,i,q);
884: x1=subrr(x,mulrr(s,addrr(y,mulrr(u,x))));
885: y1=addrr(y,mulrr(s,subrr(x,mulrr(u,y))));
886: affrr(x1,gcoeff(a,i,p)); affrr(y1,gcoeff(a,i,q));
887: }
888: for (i=p+1; i<q; i++)
889: {
890: x=gcoeff(a,p,i); y=gcoeff(a,i,q);
891: x1=subrr(x,mulrr(s,addrr(y,mulrr(u,x))));
892: y1=addrr(y,mulrr(s,subrr(x,mulrr(u,y))));
893: affrr(x1,gcoeff(a,p,i)); affrr(y1,gcoeff(a,i,q));
894: }
895: for (i=q+1; i<=n; i++)
896: {
897: x=gcoeff(a,p,i); y=gcoeff(a,q,i);
898: x1=subrr(x,mulrr(s,addrr(y,mulrr(u,x))));
899: y1=addrr(y,mulrr(s,subrr(x,mulrr(u,y))));
900: affrr(x1,gcoeff(a,p,i)); affrr(y1,gcoeff(a,q,i));
901: }
902: x=(GEN)lambda[p]; y=gcoeff(a,p,q); subrrz(x,mulrr(t,y),(GEN)lambda[p]);
903: x=y; y=(GEN)lambda[q]; addrrz(y,mulrr(t,x),y);
904: setexpo(x,expo(x)-de-1);
905:
906: for (i=1; i<=n; i++)
907: {
908: x=gcoeff(r,i,p); y=gcoeff(r,i,q);
909: x1=subrr(x,mulrr(s,addrr(y,mulrr(u,x))));
910: y1=addrr(y,mulrr(s,subrr(x,mulrr(u,y))));
911: affrr(x1,gcoeff(r,i,p)); affrr(y1,gcoeff(r,i,q));
912: }
913:
914: e2=expo(gcoeff(a,1,2)); p=1; q=2;
915: for (j=1; j<=n; j++)
916: {
917: for (i=1; i<j; i++)
918: if ((e=expo(gcoeff(a,i,j))) > e2) { e2=e; p=i; q=j; }
919: for (i=j+1; i<=n; i++)
920: if ((e=expo(gcoeff(a,j,i))) > e2) { e2=e; p=j; q=i; }
921: }
922: avma=av2;
923: }
924: avma=av1; return ja;
925: }
926:
927: /*************************************************************************/
928: /** **/
929: /** MATRICE RATIONNELLE --> ENTIERE **/
930: /** **/
931: /*************************************************************************/
932:
933: GEN
934: matrixqz0(GEN x,GEN p)
935: {
936: if (typ(p)!=t_INT) err(typeer,"matrixqz0");
937: if (signe(p)>=0) return matrixqz(x,p);
938: if (!cmpsi(-1,p)) return matrixqz2(x);
939: if (!cmpsi(-2,p)) return matrixqz3(x);
940: err(flagerr,"matrixqz"); return NULL; /* not reached */
941: }
942:
943: GEN
944: matrixqz(GEN x, GEN p)
945: {
946: ulong av = avma, av1, lim;
947: long i,j,j1,m,n,t,nfact;
948: GEN p1,p2,p3,unmodp;
949:
950: if (typ(x)!=t_MAT) err(typeer,"matrixqz");
951: n=lg(x)-1; if (!n) return gcopy(x);
952: m=lg(x[1])-1;
953: if (n > m) err(talker,"more rows than columns in matrixqz");
954: if (n==m)
955: {
956: p1=det(x);
957: if (gcmp0(p1)) err(talker,"matrix of non-maximal rank in matrixqz");
958: avma=av; return idmat(n);
959: }
960: p1=cgetg(n+1,t_MAT);
961: for (j=1; j<=n; j++)
962: {
963: p2=gun; p3=(GEN)x[j];
964: for (i=1; i<=m; i++)
965: {
966: t=typ(p3[i]);
967: if (t != t_INT && !is_frac_t(t))
968: err(talker,"not a rational or integral matrix in matrixqz");
969: p2=ggcd(p2,(GEN)p3[i]);
970: }
971: p1[j]=ldiv(p3,p2);
972: }
973: x=p1; unmodp=cgetg(3,t_INTMOD); unmodp[2]=un;
974:
975: if (gcmp0(p))
976: {
977: p1=cgetg(n+1,t_MAT); p2=gtrans(x);
978: for (j=1; j<=n; j++) p1[j]=p2[j];
979: p3=det(p1); p1[n]=p2[n+1]; p3=ggcd(p3,det(p1));
980: if (!signe(p3))
981: err(impl,"matrixqz when the first 2 dets are zero");
982: if (gcmp1(p3)) return gerepilecopy(av,x);
983:
984: p3=factor(p3); p1=(GEN)p3[1]; nfact=lg(p1)-1;
985: }
986: else
987: {
988: p1=cgetg(2,t_VEC); p1[1]=(long)p; nfact=1;
989: }
990: av1=avma; lim=stack_lim(av1,1);
991: for (i=1; i<=nfact; i++)
992: {
993: p=(GEN)p1[i]; unmodp[1]=(long)p;
994: for(;;)
995: {
996: p2=ker(gmul(unmodp,x));
997: if (lg(p2)==1) break;
998:
999: p2=centerlift(p2); p3=gdiv(gmul(x,p2),p);
1000: for (j=1; j<lg(p2); j++)
1001: {
1002: j1=n; while (gcmp0(gcoeff(p2,j1,j))) j1--;
1003: x[j1] = p3[j];
1004: }
1005: if (low_stack(lim, stack_lim(av1,1)))
1006: {
1007: if (DEBUGMEM>1) err(warnmem,"matrixqz");
1008: x=gerepilecopy(av1,x);
1009: }
1010: }
1011: }
1012: return gerepilecopy(av,x);
1013: }
1014:
1015: static GEN
1016: matrixqz_aux(GEN x, long m, long n)
1017: {
1018: ulong av = avma, lim = stack_lim(av,1);
1019: long i,j,k,in[2];
1020: GEN p1;
1021:
1022: for (i=1; i<=m; i++)
1023: {
1024: for(;;)
1025: {
1026: long fl=0;
1027:
1028: for (j=1; j<=n; j++)
1029: if (!gcmp0(gcoeff(x,i,j)))
1030: { in[fl]=j; fl++; if (fl==2) break; }
1031: if (j>n) break;
1032:
1033: j=(gcmp(gabs(gcoeff(x,i,in[0]),DEFAULTPREC),
1034: gabs(gcoeff(x,i,in[1]),DEFAULTPREC)) > 0)? in[1]: in[0];
1035: p1=gcoeff(x,i,j);
1036: for (k=1; k<=n; k++)
1037: if (k!=j)
1038: x[k]=lsub((GEN)x[k],gmul(ground(gdiv(gcoeff(x,i,k),p1)),(GEN)x[j]));
1039: }
1040:
1041: j=1; while (j<=n && gcmp0(gcoeff(x,i,j))) j++;
1042: if (j<=n)
1043: {
1044: p1=denom(gcoeff(x,i,j));
1045: if (!gcmp1(p1)) x[j]=lmul(p1,(GEN)x[j]);
1046: }
1047: if (low_stack(lim, stack_lim(av,1)))
1048: {
1049: if(DEBUGMEM>1) err(warnmem,"matrixqz_aux");
1050: x=gerepilecopy(av,x);
1051: }
1052: }
1053: return hnf(x);
1054: }
1055:
1056: GEN
1057: matrixqz2(GEN x)
1058: {
1059: long av = avma,m,n;
1060:
1061: if (typ(x)!=t_MAT) err(typeer,"matrixqz2");
1062: n=lg(x)-1; if (!n) return gcopy(x);
1063: m=lg(x[1])-1; x=dummycopy(x);
1064: return gerepileupto(av, matrixqz_aux(x,m,n));
1065: }
1066:
1067: GEN
1068: matrixqz3(GEN x)
1069: {
1070: long av=avma,av1,j,j1,k,m,n,lim;
1071: GEN c;
1072:
1073: if (typ(x)!=t_MAT) err(typeer,"matrixqz3");
1074: n=lg(x)-1; if (!n) return gcopy(x);
1075: m=lg(x[1])-1; x=dummycopy(x); c=new_chunk(n+1);
1076: for (j=1; j<=n; j++) c[j]=0;
1077: av1=avma; lim=stack_lim(av1,1);
1078: for (k=1; k<=m; k++)
1079: {
1080: j=1; while (j<=n && (c[j] || gcmp0(gcoeff(x,k,j)))) j++;
1081: if (j<=n)
1082: {
1083: c[j]=k; x[j]=ldiv((GEN)x[j],gcoeff(x,k,j));
1084: for (j1=1; j1<=n; j1++)
1085: if (j1!=j) x[j1]=lsub((GEN)x[j1],gmul(gcoeff(x,k,j1),(GEN)x[j]));
1086: if (low_stack(lim, stack_lim(av1,1)))
1087: {
1088: if(DEBUGMEM>1) err(warnmem,"matrixqz3");
1089: x=gerepilecopy(av1,x);
1090: }
1091: }
1092: }
1093: return gerepileupto(av, matrixqz_aux(x,m,n));
1094: }
1095:
1096: GEN
1097: intersect(GEN x, GEN y)
1098: {
1099: long av,tetpil,j, lx = lg(x);
1100: GEN z;
1101:
1102: if (typ(x)!=t_MAT || typ(y)!=t_MAT) err(typeer,"intersect");
1103: if (lx==1 || lg(y)==1) return cgetg(1,t_MAT);
1104:
1105: av=avma; z=ker(concatsp(x,y));
1106: for (j=lg(z)-1; j; j--) setlg(z[j],lx);
1107: tetpil=avma; return gerepile(av,tetpil,gmul(x,z));
1108: }
1109:
1110: /**************************************************************/
1111: /** **/
1112: /** HERMITE NORMAL FORM REDUCTION **/
1113: /** **/
1114: /**************************************************************/
1115:
1116: GEN
1117: mathnf0(GEN x, long flag)
1118: {
1119: switch(flag)
1120: {
1121: case 0: return hnf(x);
1122: case 1: return hnfall(x);
1123: case 3: return hnfperm(x);
1124: case 4: return hnflll(x);
1125: default: err(flagerr,"mathnf");
1126: }
1127: return NULL; /* not reached */
1128: }
1129:
1130: static GEN
1131: init_hnf(GEN x, GEN *denx, long *co, long *li, long *av)
1132: {
1133: if (typ(x) != t_MAT) err(typeer,"mathnf");
1134: *co=lg(x); if (*co==1) return NULL; /* empty matrix */
1135: *li=lg(x[1]); *denx=denom(x); *av=avma;
1136:
1137: if (gcmp1(*denx)) /* no denominator */
1138: { *denx = NULL; return dummycopy(x); }
1139: return gmul(x,*denx);
1140: }
1141:
1142: GEN
1143: ZV_copy(GEN x)
1144: {
1145: long i, lx = lg(x);
1146: GEN y = cgetg(lx, t_COL);
1147: for (i=1; i<lx; i++) y[i] = signe(x[i])? licopy((GEN)x[i]): zero;
1148: return y;
1149: }
1150:
1151: GEN
1152: ZM_copy(GEN x)
1153: {
1154: long i, lx = lg(x);
1155: GEN y = cgetg(lx, t_MAT);
1156:
1157: for (i=1; i<lx; i++)
1158: y[i] = (long)ZV_copy((GEN)x[i]);
1159: return y;
1160: }
1161:
1162: /* return c * X. Not memory clean if c = 1 */
1163: GEN
1164: ZV_Z_mul(GEN c, GEN X)
1165: {
1166: long i,m = lg(X);
1167: GEN A = new_chunk(m);
1168: if (is_pm1(c))
1169: {
1170: if (signe(c) > 0)
1171: { for (i=1; i<m; i++) A[i] = X[i]; }
1172: else
1173: { for (i=1; i<m; i++) A[i] = lnegi((GEN)X[i]); }
1174: }
1175: else /* c = 0 should be exceedingly rare */
1176: { for (i=1; i<m; i++) A[i] = lmulii(c,(GEN)X[i]); }
1177: A[0] = X[0]; return A;
1178: }
1179:
1180: /* X,Y columns; u,v scalars; everybody is integral. return A = u*X + v*Y
1181: * Not memory clean if (u,v) = (1,0) or (0,1) */
1182: GEN
1183: ZV_lincomb(GEN u, GEN v, GEN X, GEN Y)
1184: {
1185: long av,i,lx,m;
1186: GEN p1,p2,A;
1187:
1188: if (!signe(u)) return ZV_Z_mul(v,Y);
1189: if (!signe(v)) return ZV_Z_mul(u,X);
1190: lx = lg(X); A = cgetg(lx,t_COL); m = lgefint(u)+lgefint(v)+4;
1191: if (is_pm1(v)) { gswap(u,v); gswap(X,Y); }
1192: if (is_pm1(u))
1193: {
1194: if (signe(u) > 0)
1195: {
1196: for (i=1; i<lx; i++)
1197: {
1198: p1=(GEN)X[i]; p2=(GEN)Y[i];
1199: if (!signe(p1)) A[i] = lmulii(v,p2);
1200: else if (!signe(p2)) A[i] = licopy(p1);
1201: else
1202: {
1203: av = avma; (void)new_chunk(m+lgefint(p1)+lgefint(p2)); /* HACK */
1204: p2 = mulii(v,p2);
1205: avma = av; A[i] = laddii(p1,p2);
1206: }
1207: }
1208: }
1209: else
1210: {
1211: for (i=1; i<lx; i++)
1212: {
1213: p1=(GEN)X[i]; p2=(GEN)Y[i];
1214: if (!signe(p1)) A[i] = lmulii(v,p2);
1215: else if (!signe(p2)) A[i] = lnegi(p1);
1216: else
1217: {
1218: av = avma; (void)new_chunk(m+lgefint(p1)+lgefint(p2)); /* HACK */
1219: p2 = mulii(v,p2);
1220: avma = av; A[i] = lsubii(p2,p1);
1221: }
1222: }
1223: }
1224: }
1225: else
1226: for (i=1; i<lx; i++)
1227: {
1228: p1=(GEN)X[i]; p2=(GEN)Y[i];
1229: if (!signe(p1)) A[i] = lmulii(v,p2);
1230: else if (!signe(p2)) A[i] = lmulii(u,p1);
1231: else
1232: {
1233: av = avma; (void)new_chunk(m+lgefint(p1)+lgefint(p2)); /* HACK */
1234: p1 = mulii(u,p1);
1235: p2 = mulii(v,p2);
1236: avma = av; A[i] = laddii(p1,p2);
1237: }
1238: }
1239: return A;
1240: }
1241:
1242: /* x = [A,U], nbcol(A) = nbcol(U), A integral. Return [AV, UV], with AV HNF */
1243: GEN
1244: hnf_special(GEN x, long remove)
1245: {
1246: long av0, s,li,co,av,tetpil,i,j,k,def,ldef,lim;
1247: GEN p1,u,v,d,denx,a,b, x2,res;
1248:
1249: if (typ(x) != t_VEC || lg(x) !=3) err(typeer,"hnf_special");
1250: res = cgetg(3,t_VEC);
1251: av0 = avma;
1252: x2 = (GEN)x[2];
1253: x = (GEN)x[1];
1254: x = init_hnf(x,&denx,&co,&li,&av);
1255: if (!x) return cgetg(1,t_MAT);
1256:
1257: lim = stack_lim(av,1);
1258: def=co-1; ldef=(li>co)? li-co: 0;
1259: if (lg(x2) != co) err(talker,"incompatible matrices in hnf_special");
1260: x2 = dummycopy(x2);
1261: for (i=li-1; i>ldef; i--)
1262: {
1263: for (j=def-1; j; j--)
1264: {
1265: a = gcoeff(x,i,j);
1266: if (!signe(a)) continue;
1267:
1268: k = (j==1)? def: j-1;
1269: b = gcoeff(x,i,k); d = bezout(a,b,&u,&v);
1270: if (!is_pm1(d)) { a = divii(a,d); b = divii(b,d); }
1271: p1 = (GEN)x[j]; b = negi(b);
1272: x[j] = (long)ZV_lincomb(a,b, (GEN)x[k], p1);
1273: x[k] = (long)ZV_lincomb(u,v, p1, (GEN)x[k]);
1274: p1 = (GEN)x2[j];
1275: x2[j]= ladd(gmul(a, (GEN)x2[k]), gmul(b,p1));
1276: x2[k] = ladd(gmul(u,p1), gmul(v, (GEN)x2[k]));
1277: if (low_stack(lim, stack_lim(av,1)))
1278: {
1279: GEN *gptr[2]; gptr[0]=&x; gptr[1]=&x2;
1280: if (DEBUGMEM>1) err(warnmem,"hnf_special[1]. i=%ld",i);
1281: gerepilemany(av,gptr,2);
1282: }
1283: }
1284: p1 = gcoeff(x,i,def); s = signe(p1);
1285: if (s)
1286: {
1287: if (s < 0)
1288: {
1289: x[def] = lneg((GEN)x[def]); p1 = gcoeff(x,i,def);
1290: x2[def]= lneg((GEN)x2[def]);
1291: }
1292: for (j=def+1; j<co; j++)
1293: {
1294: b = negi(gdivent(gcoeff(x,i,j),p1));
1295: x[j] = (long)ZV_lincomb(gun,b, (GEN)x[j], (GEN)x[def]);
1296: x2[j]= ladd((GEN)x2[j], gmul(b, (GEN)x2[def]));
1297: }
1298: def--;
1299: }
1300: else
1301: if (ldef && i==ldef+1) ldef--;
1302: if (low_stack(lim, stack_lim(av,1)))
1303: {
1304: GEN *gptr[2]; gptr[0]=&x; gptr[1]=&x2;
1305: if (DEBUGMEM>1) err(warnmem,"hnf_special[2]. i=%ld",i);
1306: gerepilemany(av,gptr,2);
1307: }
1308: }
1309: if (remove)
1310: { /* remove null columns */
1311: for (i=1,j=1; j<co; j++)
1312: if (!gcmp0((GEN)x[j]))
1313: {
1314: x[i] = x[j];
1315: x2[i] = x2[j]; i++;
1316: }
1317: setlg(x,i);
1318: setlg(x2,i);
1319: }
1320: tetpil=avma;
1321: x = denx? gdiv(x,denx): ZM_copy(x);
1322: x2 = gcopy(x2);
1323: {
1324: GEN *gptr[2]; gptr[0]=&x; gptr[1]=&x2;
1325: gerepilemanysp(av0,tetpil,gptr,2);
1326: }
1327: res[1] = (long)x;
1328: res[2] = (long)x2;
1329: return res;
1330: }
1331:
1332: /*******************************************************************/
1333: /* */
1334: /* SPECIAL HNF (FOR INTERNAL USE !!!) */
1335: /* */
1336: /*******************************************************************/
1337: extern GEN imagecomplspec(GEN x, long *nlze);
1338:
1339: static int
1340: count(long **mat, long row, long len, long *firstnonzero)
1341: {
1342: int j, n=0;
1343:
1344: for (j=1; j<=len; j++)
1345: {
1346: long p = mat[j][row];
1347: if (p)
1348: {
1349: if (labs(p)!=1) return -1;
1350: n++; *firstnonzero=j;
1351: }
1352: }
1353: return n;
1354: }
1355:
1356: static int
1357: count2(long **mat, long row, long len)
1358: {
1359: int j;
1360: for (j=len; j; j--)
1361: if (labs(mat[j][row]) == 1) return j;
1362: return 0;
1363: }
1364:
1365: static GEN
1366: hnffinal(GEN matgen,GEN perm,GEN* ptdep,GEN* ptB,GEN* ptC)
1367: {
1368: GEN p1,p2,U,H,Hnew,Bnew,Cnew,diagH1;
1369: GEN B = *ptB, C = *ptC, dep = *ptdep, depnew;
1370: long av,i,j,k,s,i1,j1,lim,zc;
1371: long co = lg(C);
1372: long col = lg(matgen)-1;
1373: long lnz, nlze, lig;
1374:
1375: if (col == 0) return matgen;
1376: lnz = lg(matgen[1])-1; /* was called lnz-1 - nr in hnfspec */
1377: nlze = lg(dep[1])-1;
1378: lig = nlze + lnz;
1379: if (DEBUGLEVEL>5)
1380: {
1381: fprintferr("Entering hnffinal:\n");
1382: if (DEBUGLEVEL>6)
1383: {
1384: if (nlze) fprintferr("dep = %Z\n",dep);
1385: fprintferr("mit = %Z\n",matgen);
1386: fprintferr("B = %Z\n",B);
1387: }
1388: }
1389: p1 = hnflll(matgen);
1390: H = (GEN)p1[1]; /* lnz x lnz */
1391: U = (GEN)p1[2]; /* col x col */
1392: /* Only keep the part above the H (above the 0s is 0 since the dep rows
1393: * are dependant from the ones in matgen) */
1394: zc = col - lnz; /* # of 0 columns, correspond to units */
1395: if (nlze) { dep = gmul(dep,U); dep += zc; }
1396:
1397: diagH1 = new_chunk(lnz+1); /* diagH1[i] = 0 iff H[i,i] != 1 (set later) */
1398:
1399: av = avma; lim = stack_lim(av,1);
1400: Cnew = cgetg(co,t_MAT);
1401: setlg(C, col+1); p1 = gmul(C,U);
1402: for (j=1; j<=col; j++) Cnew[j] = p1[j];
1403: for ( ; j<co ; j++) Cnew[j] = C[j];
1404: if (DEBUGLEVEL>5) fprintferr(" hnflll done\n");
1405:
1406: /* Clean up B using new H */
1407: for (s=0,i=lnz; i; i--)
1408: {
1409: GEN h = gcoeff(H,i,i);
1410: if ( (diagH1[i] = gcmp1(h)) ) { h = NULL; s++; }
1411: for (j=col+1; j<co; j++)
1412: {
1413: GEN z = (GEN)B[j-col];
1414: p1 = (GEN)z[i+nlze]; if (h) p1 = gdivent(p1,h);
1415: for (k=1; k<=nlze; k++)
1416: z[k] = lsubii((GEN)z[k], mulii(p1, gcoeff(dep,k,i)));
1417: for ( ; k<=lig; k++)
1418: z[k] = lsubii((GEN)z[k], mulii(p1, gcoeff(H,k-nlze,i)));
1419: Cnew[j] = lsub((GEN)Cnew[j], gmul(p1, (GEN)Cnew[i+zc]));
1420: }
1421: if (low_stack(lim, stack_lim(av,1)))
1422: {
1423: GEN *gptr[2]; gptr[0]=&Cnew; gptr[1]=&B;
1424: if(DEBUGMEM>1) err(warnmem,"hnffinal, i = %ld",i);
1425: gerepilemany(av,gptr,2);
1426: }
1427: }
1428: p1 = cgetg(lnz+1,t_VEC); p2 = perm + nlze;
1429: for (i1=0, j1=lnz-s, i=1; i<=lnz; i++) /* push the 1 rows down */
1430: if (diagH1[i])
1431: p1[++j1] = p2[i];
1432: else
1433: p2[++i1] = p2[i];
1434: for (i=i1+1; i<=lnz; i++) p2[i] = p1[i];
1435: if (DEBUGLEVEL>5) fprintferr(" first pass in hnffinal done\n");
1436:
1437: /* s = # extra redundant generators taken from H
1438: * zc col-s co zc = col lnz
1439: * [ 0 |dep | ] i = lnze + lnz - s = lig - s
1440: * nlze [--------| B' ]
1441: * [ 0 | H' | ] H' = H minus the s rows with a 1 on diagonal
1442: * i [--------|-----] lig-s (= "1-rows")
1443: * [ 0 | Id ]
1444: * [ | ] li */
1445: lig -= s; col -= s; lnz -= s;
1446: Hnew = cgetg(lnz+1,t_MAT);
1447: depnew = cgetg(lnz+1,t_MAT); /* only used if nlze > 0 */
1448: Bnew = cgetg(co-col,t_MAT);
1449: C = dummycopy(Cnew);
1450: for (j=1,i1=j1=0; j<=lnz+s; j++)
1451: {
1452: GEN z = (GEN)H[j];
1453: if (diagH1[j])
1454: { /* hit exactly s times */
1455: i1++; p1 = cgetg(lig+1,t_COL); Bnew[i1] = (long)p1;
1456: C[i1+col] = Cnew[j+zc];
1457: for (i=1; i<=nlze; i++) p1[i] = coeff(dep,i,j);
1458: p1 += nlze;
1459: }
1460: else
1461: {
1462: j1++; p1 = cgetg(lnz+1,t_COL); Hnew[j1] = (long)p1;
1463: C[j1+zc] = Cnew[j+zc];
1464: if (nlze) depnew[j1] = dep[j];
1465: }
1466: for (i=k=1; k<=lnz; i++)
1467: if (!diagH1[i]) p1[k++] = z[i];
1468: }
1469: for (j=s+1; j<co-col; j++)
1470: {
1471: GEN z = (GEN)B[j-s];
1472: p1 = cgetg(lig+1,t_COL); Bnew[j] = (long)p1;
1473: for (i=1; i<=nlze; i++) p1[i] = z[i];
1474: z += nlze; p1 += nlze;
1475: for (i=k=1; k<=lnz; i++)
1476: if (!diagH1[i]) p1[k++] = z[i];
1477: }
1478: if (DEBUGLEVEL>5)
1479: {
1480: fprintferr("Leaving hnffinal\n");
1481: if (DEBUGLEVEL>6)
1482: {
1483: if (nlze) fprintferr("dep = %Z\n",depnew);
1484: fprintferr("mit = %Z\nB = %Z\nC = %Z\n", Hnew, Bnew, C);
1485: }
1486: }
1487: if (nlze) *ptdep = depnew;
1488: *ptC = C;
1489: *ptB = Bnew; return Hnew;
1490: }
1491:
1492: /* for debugging */
1493: static void
1494: p_mat(long **mat, long *perm, long k0)
1495: {
1496: long av=avma, i,j;
1497: GEN p1, matj, matgen;
1498: long co = lg(mat);
1499: long li = lg(perm);
1500:
1501: fprintferr("Permutation: %Z\n",perm);
1502: matgen = cgetg(co,t_MAT);
1503: for (j=1; j<co; j++)
1504: {
1505: p1 = cgetg(li-k0,t_COL); matgen[j]=(long)p1;
1506: p1 -= k0; matj = mat[j];
1507: for (i=k0+1; i<li; i++) p1[i] = lstoi(matj[perm[i]]);
1508: }
1509: if (DEBUGLEVEL > 6) fprintferr("matgen = %Z\n",matgen);
1510: avma=av;
1511: }
1512:
1513: static GEN
1514: col_dup(long n, GEN col)
1515: {
1516: GEN c = new_chunk(n+1);
1517: memcpy(c,col,(n+1)*sizeof(long));
1518: return c;
1519: }
1520:
1521: /* HNF reduce a relation matrix (column operations + row permutation)
1522: ** Input:
1523: ** mat = (li-1) x (co-1) matrix of long
1524: ** C = r x (co-1) matrix of GEN
1525: ** perm= permutation vector (length li-1), indexing the rows of mat: easier
1526: ** to maintain perm than to copy rows. For columns we can do it directly
1527: ** using e.g. swap(mat[i], mat[j])
1528: ** k0 = integer. The k0 first lines of mat are dense, the others are sparse.
1529: ** Also if k0=0, mat is modified in place [from mathnfspec], otherwise
1530: ** it is left alone [from buchall]
1531: ** Output: cf ASCII art in the function body
1532: **
1533: ** row permutations applied to perm
1534: ** column operations applied to C.
1535: **/
1536: GEN
1537: hnfspec(long** mat0, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, long k0)
1538: {
1539: long av=avma,av2,*p,i,j,k,lk0,col,lig,*matj, **mat;
1540: long n,s,t,lim,nlze,lnz,nr;
1541: GEN p1,p2,matb,matbnew,vmax,matt,T,extramat;
1542: GEN B,H,dep,permpro;
1543: GEN *gptr[4];
1544: long co = lg(mat0);
1545: long li = lg(perm); /* = lg(mat0[1]) */
1546: int updateT = 1;
1547:
1548: if (!k0) mat = mat0; /* in place */
1549: else
1550: { /* keep original mat0 safe, modify a copy */
1551: mat = (long**)new_chunk(co); mat[0] = mat0[0];
1552: for (j=1; j<co; j++) mat[j] = col_dup(li,mat0[j]);
1553: }
1554:
1555: if (DEBUGLEVEL>5)
1556: {
1557: fprintferr("Entering hnfspec\n");
1558: p_mat(mat,perm,0);
1559: }
1560: matt = cgetg(co,t_MAT); /* dense part of mat (top) */
1561: for (j=1; j<co; j++)
1562: {
1563: p1=cgetg(k0+1,t_COL); matt[j]=(long)p1; matj = mat[j];
1564: for (i=1; i<=k0; i++) p1[i] = lstoi(matj[perm[i]]);
1565: }
1566: vmax = cgetg(co,t_VECSMALL);
1567: av2 = avma; lim = stack_lim(av2,1);
1568:
1569: i=lig=li-1; col=co-1; lk0=k0;
1570: if (k0 || (lg(*ptC) > 1 && lg((*ptC)[1]) > 1)) T = idmat(col);
1571: else
1572: { /* dummy ! */
1573: GEN z = cgetg(1,t_COL);
1574: T = cgetg(co, t_MAT); updateT = 0;
1575: for (j=1; j<co; j++) T[j] = (long)z;
1576: }
1577: /* Look for lines with a single non0 entry, equal to ±1 */
1578: while (i > lk0)
1579: switch( count(mat,perm[i],col,&n) )
1580: {
1581: case 0: /* move zero lines between k0+1 and lk0 */
1582: lk0++; swap(perm[i], perm[lk0]);
1583: i=lig; continue;
1584:
1585: case 1: /* move trivial generator between lig+1 and li */
1586: swap(perm[i], perm[lig]);
1587: swap(T[n], T[col]);
1588: gswap(mat[n], mat[col]); p = mat[col];
1589: if (p[perm[lig]] < 0) /* = -1 */
1590: { /* convert relation -g = 0 to g = 0 */
1591: for (i=lk0+1; i<lig; i++) p[perm[i]] = -p[perm[i]];
1592: if (updateT)
1593: {
1594: p1 = (GEN)T[col];
1595: for (i=1; ; i++)
1596: if (signe((GEN)p1[i])) { p1[i] = lnegi((GEN)p1[i]); break; }
1597: }
1598: }
1599: lig--; col--; i=lig; continue;
1600:
1601: default: i--;
1602: }
1603: if (DEBUGLEVEL>5)
1604: {
1605: fprintferr(" after phase1:\n");
1606: p_mat(mat,perm,0);
1607: }
1608:
1609: #define absmax(s,z) {long _z; _z = labs(z); if (_z > s) s = _z;}
1610:
1611: #if 0 /* TODO: check, and put back in */
1612: /* Get rid of all lines containing only 0 and ± 1, keeping track of column
1613: * operations in T. Leave the rows 1..lk0 alone [up to k0, coeff
1614: * explosion, between k0+1 and lk0, row is 0]
1615: */
1616: s = 0;
1617: while (lig > lk0 && s < (HIGHBIT>>1))
1618: {
1619: for (i=lig; i>lk0; i--)
1620: if (count(mat,perm[i],col,&n) >= 0) break;
1621: if (i == lk0) break;
1622:
1623: /* only 0, ±1 entries, at least 2 of them non-zero */
1624: swap(perm[i], perm[lig]);
1625: swap(T[n], T[col]); p1 = (GEN)T[col];
1626: gswap(mat[n], mat[col]); p = mat[col];
1627: if (p[perm[lig]] < 0)
1628: {
1629: for (i=lk0+1; i<=lig; i++) p[perm[i]] = -p[perm[i]];
1630: T[col] = lneg(p1);
1631: }
1632: for (j=1; j<n; j++)
1633: {
1634: matj = mat[j];
1635: if (! (t = matj[perm[lig]]) ) continue;
1636: if (t == 1)
1637: { /* t = 1 */
1638: for (i=lk0+1; i<=lig; i++)
1639: absmax(s, matj[perm[i]] -= p[perm[i]]);
1640: T[j] = lsub((GEN)T[j], p1);
1641: }
1642: else
1643: { /* t = -1 */
1644: for (i=lk0+1; i<=lig; i++)
1645: absmax(s, matj[perm[i]] += p[perm[i]]);
1646: T[j] = ladd((GEN)T[j], p1);
1647: }
1648: }
1649: lig--; col--;
1650: if (low_stack(lim, stack_lim(av2,1)))
1651: {
1652: if(DEBUGMEM>1) err(warnmem,"hnfspec[1]");
1653: T = gerepilecopy(av2, T);
1654: }
1655: }
1656: #endif
1657: /* As above with lines containing a ±1 (no other assumption).
1658: * Stop when single precision becomes dangerous */
1659: for (j=1; j<=col; j++)
1660: {
1661: matj = mat[j];
1662: for (s=0, i=lk0+1; i<=lig; i++) absmax(s, matj[i]);
1663: vmax[j] = s;
1664: }
1665: while (lig > lk0)
1666: {
1667: for (i=lig; i>lk0; i--)
1668: if ( (n = count2(mat,perm[i],col)) ) break;
1669: if (i == lk0) break;
1670:
1671: swap(perm[i], perm[lig]);
1672: swap(vmax[n], vmax[col]);
1673: gswap(mat[n], mat[col]); p = mat[col];
1674: swap(T[n], T[col]); p1 = (GEN)T[col];
1675: if (p[perm[lig]] < 0)
1676: {
1677: for (i=lk0+1; i<=lig; i++) p[perm[i]] = -p[perm[i]];
1678: p1 = gneg(p1); T[col] = (long)p1;
1679: }
1680: for (j=1; j<col; j++)
1681: {
1682: matj = mat[j];
1683: if (! (t = matj[perm[lig]]) ) continue;
1684: if (vmax[col] && (ulong)labs(t) >= (HIGHBIT-vmax[j]) / vmax[col])
1685: goto END2;
1686:
1687: for (s=0, i=lk0+1; i<=lig; i++)
1688: absmax(s, matj[perm[i]] -= t*p[perm[i]]);
1689: vmax[j] = s;
1690: T[j] = (long)ZV_lincomb(gun,stoi(-t), (GEN)T[j],p1);
1691: }
1692: lig--; col--;
1693: if (low_stack(lim, stack_lim(av2,1)))
1694: {
1695: if(DEBUGMEM>1) err(warnmem,"hnfspec[2]");
1696: T = gerepilecopy(av2,T);
1697: }
1698: }
1699:
1700: END2: /* clean up mat: remove everything to the right of the 1s on diagonal */
1701: /* go multiprecision first */
1702: matb = cgetg(co,t_MAT); /* bottom part (complement of matt) */
1703: for (j=1; j<co; j++)
1704: {
1705: p1 = cgetg(li-k0,t_COL); matb[j] = (long)p1;
1706: p1 -= k0; matj = mat[j];
1707: for (i=k0+1; i<li; i++) p1[i] = lstoi(matj[perm[i]]);
1708: }
1709: if (DEBUGLEVEL>5)
1710: {
1711: fprintferr(" after phase2:\n");
1712: p_mat(mat,perm,k0);
1713: }
1714: for (i=li-2; i>lig; i--)
1715: {
1716: long i1, i0 = i - k0, k = i + co-li;
1717: GEN Bk = (GEN)matb[k];
1718: GEN Tk = (GEN)T[k];
1719: for (j=k+1; j<co; j++)
1720: {
1721: p1=(GEN)matb[j]; p2=(GEN)p1[i0];
1722: if (! (s=signe(p2)) ) continue;
1723:
1724: p1[i0] = zero;
1725: if (is_pm1(p2))
1726: {
1727: if (s > 0)
1728: { /* p2 = 1 */
1729: for (i1=1; i1<i0; i1++)
1730: p1[i1] = lsubii((GEN)p1[i1], (GEN)Bk[i1]);
1731: T[j] = lsub((GEN)T[j], Tk);
1732: }
1733: else
1734: { /* p2 = -1 */
1735: for (i1=1; i1<i0; i1++)
1736: p1[i1] = laddii((GEN)p1[i1], (GEN)Bk[i1]);
1737: T[j] = ladd((GEN)T[j], Tk);
1738: }
1739: }
1740: else
1741: {
1742: for (i1=1; i1<i0; i1++)
1743: p1[i1] = lsubii((GEN)p1[i1], mulii(p2,(GEN) Bk[i1]));
1744: T[j] = (long)ZV_lincomb(gun,negi(p2), (GEN)T[j],Tk);
1745: }
1746: }
1747: if (low_stack(lim, stack_lim(av2,1)))
1748: {
1749: if(DEBUGMEM>1) err(warnmem,"hnfspec[3], i = %ld", i);
1750: for (j=1; j<co; j++) setlg(matb[j], i0+1); /* bottom can be forgotten */
1751: gptr[0]=&T; gptr[1]=&matb; gerepilemany(av2,gptr,2);
1752: }
1753: }
1754: gptr[0]=&T; gptr[1]=&matb; gerepilemany(av2,gptr,2);
1755: if (DEBUGLEVEL>5)
1756: {
1757: fprintferr(" matb cleaned up (using Id block)\n");
1758: if (DEBUGLEVEL>6) outerr(matb);
1759: }
1760:
1761: nlze = lk0 - k0; /* # of 0 rows */
1762: lnz = lig-nlze+1; /* 1 + # of non-0 rows (!= 0...0 1 0 ... 0) */
1763: if (updateT) matt = gmul(matt,T); /* update top rows */
1764: extramat = cgetg(col+1,t_MAT); /* = new C minus the 0 rows */
1765: for (j=1; j<=col; j++)
1766: {
1767: GEN z = (GEN)matt[j];
1768: GEN t = ((GEN)matb[j]) + nlze - k0;
1769: p2=cgetg(lnz,t_COL); extramat[j]=(long)p2;
1770: for (i=1; i<=k0; i++) p2[i] = z[i]; /* top k0 rows */
1771: for ( ; i<lnz; i++) p2[i] = t[i]; /* other non-0 rows */
1772: }
1773: permpro = imagecomplspec(extramat, &nr); /* lnz = lg(permpro) */
1774:
1775: if (nlze)
1776: { /* put the nlze 0 rows (trivial generators) at the top */
1777: p1 = new_chunk(lk0+1);
1778: for (i=1; i<=nlze; i++) p1[i] = perm[i + k0];
1779: for ( ; i<=lk0; i++) p1[i] = perm[i - nlze];
1780: for (i=1; i<=lk0; i++) perm[i] = p1[i];
1781: }
1782: /* sort other rows according to permpro (nr redundant generators first) */
1783: p1 = new_chunk(lnz); p2 = perm + nlze;
1784: for (i=1; i<lnz; i++) p1[i] = p2[permpro[i]];
1785: for (i=1; i<lnz; i++) p2[i] = p1[i];
1786: /* perm indexes the rows of mat
1787: * |_0__|__redund__|__dense__|__too big__|_____done______|
1788: * 0 nlze lig li
1789: * \___nr___/ \___k0__/
1790: * \____________lnz ______________/
1791: *
1792: * col co
1793: * [dep | ]
1794: * i0 [--------| B ] (i0 = nlze + nr)
1795: * [matbnew | ] matbnew has maximal rank = lnz-1 - nr
1796: * mat = [--------|-----] lig
1797: * [ 0 | Id ]
1798: * [ | ] li */
1799:
1800: matbnew = cgetg(col+1,t_MAT); /* dense+toobig, maximal rank. For hnffinal */
1801: dep = cgetg(col+1,t_MAT); /* rows dependant from the ones in matbnew */
1802: for (j=1; j<=col; j++)
1803: {
1804: GEN z = (GEN)extramat[j];
1805: p1 = cgetg(nlze+nr+1,t_COL); dep[j]=(long)p1;
1806: p2 = cgetg(lnz-nr,t_COL); matbnew[j]=(long)p2;
1807: for (i=1; i<=nlze; i++) p1[i]=zero;
1808: p1 += nlze; for (i=1; i<=nr; i++) p1[i] = z[permpro[i]];
1809: p2 -= nr; for ( ; i<lnz; i++) p2[i] = z[permpro[i]];
1810: }
1811:
1812: /* redundant generators in terms of the genuine generators
1813: * (x_i) = - (g_i) B */
1814: B = cgetg(co-col,t_MAT);
1815: for (j=col+1; j<co; j++)
1816: {
1817: GEN y = (GEN)matt[j];
1818: GEN z = (GEN)matb[j];
1819: p1=cgetg(lig+1,t_COL); B[j-col]=(long)p1;
1820: for (i=1; i<=nlze; i++) p1[i] = z[i];
1821: p1 += nlze; z += nlze-k0;
1822: for (k=1; k<lnz; k++)
1823: {
1824: i = permpro[k];
1825: p1[k] = (i <= k0)? y[i]: z[i];
1826: }
1827: }
1828: if (updateT) *ptC = gmul(*ptC,T);
1829: *ptdep = dep;
1830: *ptB = B;
1831: H = hnffinal(matbnew,perm,ptdep,ptB,ptC);
1832: gptr[0]=ptC;
1833: gptr[1]=ptdep;
1834: gptr[2]=ptB;
1835: gptr[3]=&H; gerepilemany(av,gptr,4);
1836: if (DEBUGLEVEL)
1837: msgtimer("hnfspec [%ld x %ld] --> [%ld x %ld]",li-1,co-1, lig-1,col-1);
1838: return H;
1839: }
1840:
1841: /* HNF reduce x, apply same transforms to C */
1842: GEN
1843: mathnfspec(GEN x, GEN *ptperm, GEN *ptdep, GEN *ptB, GEN *ptC)
1844: {
1845: long i,j,k,ly,lx = lg(x);
1846: GEN p1,p2,z,perm;
1847: if (lx == 1) return gcopy(x);
1848: ly = lg(x[1]);
1849: z = cgetg(lx,t_MAT);
1850: perm = cgetg(ly,t_VECSMALL); *ptperm = perm;
1851: for (i=1; i<ly; i++) perm[i] = i;
1852: for (i=1; i<lx; i++)
1853: {
1854: p1 = cgetg(ly,t_COL); z[i] = (long)p1;
1855: p2 = (GEN)x[i];
1856: for (j=1; j<ly; j++)
1857: {
1858: if (is_bigint(p2[j])) goto TOOLARGE;
1859: p1[j] = itos((GEN)p2[j]);
1860: }
1861: }
1862: /* [ dep | ]
1863: * [-----| B ]
1864: * [ H | ]
1865: * [-----|-----]
1866: * [ 0 | Id ] */
1867: return hnfspec((long**)z,perm, ptdep, ptB, ptC, 0);
1868:
1869: TOOLARGE:
1870: if (lg(*ptC) > 1 && lg((*ptC)[1]) > 1)
1871: err(impl,"mathnfspec with large entries");
1872: x = hnf(x); lx = lg(x); j = ly; k = 0;
1873: for (i=1; i<ly; i++)
1874: {
1875: if (gcmp1(gcoeff(x,i,i + lx-ly)))
1876: perm[--j] = i;
1877: else
1878: perm[++k] = i;
1879: }
1880: setlg(perm,k+1);
1881: x = rowextract_p(x, perm); /* upper part */
1882: setlg(perm,ly);
1883: *ptB = vecextract_i(x, j+lx-ly, lx-1);
1884: setlg(x, j);
1885: *ptdep = rowextract_i(x, 1, lx-ly);
1886: return rowextract_i(x, lx-ly+1, k); /* H */
1887: }
1888:
1889: /* add new relations to a matrix treated by hnfspec (extramat / extraC) */
1890: GEN
1891: hnfadd(GEN H, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, /* cf hnfspec */
1892: GEN extramat,GEN extraC)
1893: {
1894: GEN p1,p2,p3,matb,extratop,Cnew,permpro;
1895: GEN B=*ptB, C=*ptC, dep=*ptdep, *gptr[4];
1896: long av = avma, i,j,lextra,colnew;
1897: long li = lg(perm);
1898: long co = lg(C);
1899: long lB = lg(B);
1900: long lig = li - lB;
1901: long col = co - lB;
1902: long lH = lg(H)-1;
1903: long nlze = lH? lg(dep[1])-1: lg(B[1])-1;
1904:
1905: if (DEBUGLEVEL>5)
1906: {
1907: fprintferr("Entering hnfadd:\n");
1908: if (DEBUGLEVEL>6) fprintferr("extramat = %Z\n",extramat);
1909: }
1910: /* col co
1911: * [ 0 |dep | ]
1912: * nlze [--------| B ]
1913: * [ 0 | H | ]
1914: * [--------|-----] lig
1915: * [ 0 | Id ]
1916: * [ | ] li */
1917: lextra = lg(extramat)-1;
1918: extratop = cgetg(lextra+1,t_MAT); /* [1..lig] part (top) */
1919: p2 = cgetg(lextra+1,t_MAT); /* bottom */
1920: for (j=1; j<=lextra; j++)
1921: {
1922: GEN z = (GEN)extramat[j];
1923: p1=cgetg(lig+1,t_COL); extratop[j] = (long)p1;
1924: for (i=1; i<=lig; i++) p1[i] = z[i];
1925: p1=cgetg(lB,t_COL); p2[j] = (long)p1;
1926: p1 -= lig;
1927: for ( ; i<li; i++) p1[i] = z[i];
1928: }
1929: if (li-1 != lig)
1930: { /* zero out bottom part, using the Id block */
1931: GEN A = cgetg(lB,t_MAT);
1932: for (j=1; j<lB; j++) A[j] = C[j+col];
1933: extraC = gsub(extraC, gmul(A,p2));
1934: extratop = gsub(extratop,gmul(B,p2));
1935: }
1936:
1937: colnew = lH + lextra;
1938: extramat = cgetg(colnew+1,t_MAT);
1939: Cnew = cgetg(lB+colnew,t_MAT);
1940: for (j=1; j<=lextra; j++)
1941: {
1942: extramat[j] = extratop[j];
1943: Cnew[j] = extraC[j];
1944: }
1945: for ( ; j<=colnew; j++)
1946: {
1947: p1 = cgetg(lig+1,t_COL); extramat[j] = (long)p1;
1948: p2 = (GEN)dep[j-lextra]; for (i=1; i<=nlze; i++) p1[i] = p2[i];
1949: p2 = (GEN) H[j-lextra]; for ( ; i<=lig ; i++) p1[i] = p2[i-nlze];
1950: }
1951: for (j=lextra+1; j<lB+colnew; j++)
1952: Cnew[j] = C[j-lextra+col-lH];
1953: if (DEBUGLEVEL>5)
1954: {
1955: fprintferr(" 1st phase done\n");
1956: if (DEBUGLEVEL>6) fprintferr("extramat = %Z\n",extramat);
1957: }
1958: permpro = imagecomplspec(extramat, &nlze);
1959: p1 = new_chunk(lig+1);
1960: for (i=1; i<=lig; i++) p1[i] = perm[permpro[i]];
1961: for (i=1; i<=lig; i++) perm[i] = p1[i];
1962:
1963: matb = cgetg(colnew+1,t_MAT);
1964: dep = cgetg(colnew+1,t_MAT);
1965: for (j=1; j<=colnew; j++)
1966: {
1967: GEN z = (GEN)extramat[j];
1968: p1=cgetg(nlze+1,t_COL); dep[j]=(long)p1;
1969: p2=cgetg(lig+1-nlze,t_COL); matb[j]=(long)p2;
1970: p2 -= nlze;
1971: for (i=1; i<=nlze; i++) p1[i] = z[permpro[i]];
1972: for ( ; i<= lig; i++) p2[i] = z[permpro[i]];
1973: }
1974: p3 = cgetg(lB,t_MAT);
1975: for (j=1; j<lB; j++)
1976: {
1977: p2 = (GEN)B[j];
1978: p1 = cgetg(lig+1,t_COL); p3[j] = (long)p1;
1979: for (i=1; i<=lig; i++) p1[i] = p2[permpro[i]];
1980: }
1981: B = p3;
1982: if (DEBUGLEVEL>5) fprintferr(" 2nd phase done\n");
1983: *ptdep = dep;
1984: *ptB = B;
1985: H = hnffinal(matb,perm,ptdep,ptB,&Cnew);
1986: p1 = cgetg(co+lextra,t_MAT);
1987: for (j=1; j <= col-lH; j++) p1[j] = C[j];
1988: C = Cnew - (col-lH);
1989: for ( ; j < co+lextra; j++) p1[j] = C[j];
1990:
1991: gptr[0]=ptC; *ptC=p1;
1992: gptr[1]=ptdep;
1993: gptr[2]=ptB;
1994: gptr[3]=&H; gerepilemany(av,gptr,4);
1995: if (DEBUGLEVEL)
1996: {
1997: if (DEBUGLEVEL>7) fprintferr("mit = %Z\nC = %Z\n",H,*ptC);
1998: msgtimer("hnfadd (%ld)",lextra);
1999: }
2000: return H;
2001: }
2002:
2003: static void
2004: ZV_neg(GEN x)
2005: {
2006: long i, lx = lg(x);
2007: for (i=1; i<lx ; i++) x[i]=lnegi((GEN)x[i]);
2008: }
2009:
2010: /* zero aj = Aij (!= 0) using ak = Aik (maybe 0), via linear combination of
2011: * A[j] and A[k] of determinant 1. If U != NULL, likewise update its columns */
2012: static void
2013: ZV_elem(GEN aj, GEN ak, GEN A, GEN U, long j, long k)
2014: {
2015: GEN p1,u,v,d;
2016:
2017: if (!signe(ak)) { swap(A[j],A[k]); if (U) swap(U[j],U[k]); return; }
2018: d = bezout(aj,ak,&u,&v);
2019: /* frequent special case (u,v) = (1,0) or (0,1) */
2020: if (!signe(u))
2021: { /* ak | aj */
2022: p1 = negi(divii(aj,ak));
2023: A[j] = (long)ZV_lincomb(gun, p1, (GEN)A[j], (GEN)A[k]);
2024: if (U)
2025: U[j] = (long)ZV_lincomb(gun, p1, (GEN)U[j], (GEN)U[k]);
2026: return;
2027: }
2028: if (!signe(v))
2029: { /* aj | ak */
2030: p1 = negi(divii(ak,aj));
2031: A[k] = (long)ZV_lincomb(gun, p1, (GEN)A[k], (GEN)A[j]);
2032: swap(A[j], A[k]);
2033: if (U) {
2034: U[k] = (long)ZV_lincomb(gun, p1, (GEN)U[k], (GEN)U[j]);
2035: swap(U[j], U[k]);
2036: }
2037: return;
2038: }
2039:
2040: if (!is_pm1(d)) { aj = divii(aj,d); ak = divii(ak,d); }
2041: p1 = (GEN)A[k]; aj = negi(aj);
2042: A[k] = (long)ZV_lincomb(u,v, (GEN)A[j],p1);
2043: A[j] = (long)ZV_lincomb(aj,ak, p1,(GEN)A[j]);
2044: if (U)
2045: {
2046: p1 = (GEN)U[k];
2047: U[k] = (long)ZV_lincomb(u,v, (GEN)U[j],p1);
2048: U[j] = (long)ZV_lincomb(aj,ak, p1,(GEN)U[j]);
2049: }
2050: }
2051:
2052: /* reduce A[i,j] mod A[i,j0] for j=j0+1... via column operations */
2053: static void
2054: ZM_reduce(GEN A, GEN U, long i, long j0)
2055: {
2056: long j, lA = lg(A);
2057: GEN d = gcoeff(A,i,j0);
2058: if (signe(d) < 0)
2059: {
2060: ZV_neg((GEN)A[j0]);
2061: if (U) ZV_neg((GEN)U[j0]);
2062: d = gcoeff(A,i,j0);
2063: }
2064: for (j=j0+1; j<lA; j++)
2065: {
2066: GEN q = truedvmdii(gcoeff(A,i,j), d, NULL);
2067: if (!signe(q)) continue;
2068:
2069: q = negi(q);
2070: A[j] = (long)ZV_lincomb(gun,q, (GEN)A[j], (GEN)A[j0]);
2071: if (U)
2072: U[j] = (long)ZV_lincomb(gun,q,(GEN)U[j],(GEN)U[j0]);
2073: }
2074: }
2075:
2076: /* remove: throw away lin.dep.columns */
2077: GEN
2078: hnf0(GEN A, int remove)
2079: {
2080: long av0 = avma, s,li,co,av,tetpil,i,j,k,def,ldef,lim;
2081: GEN denx,a,p1;
2082:
2083: if (typ(A) == t_VEC) return hnf_special(A,remove);
2084: A = init_hnf(A,&denx,&co,&li,&av);
2085: if (!A) return cgetg(1,t_MAT);
2086:
2087: lim = stack_lim(av,1);
2088: def=co-1; ldef=(li>co)? li-co: 0;
2089: for (i=li-1; i>ldef; i--)
2090: {
2091: for (j=def-1; j; j--)
2092: {
2093: a = gcoeff(A,i,j);
2094: if (!signe(a)) continue;
2095:
2096: /* zero a = Aij using b = Aik */
2097: k = (j==1)? def: j-1;
2098: ZV_elem(a,gcoeff(A,i,k), A,NULL, j,k);
2099:
2100: if (low_stack(lim, stack_lim(av,1)))
2101: {
2102: if (DEBUGMEM>1) err(warnmem,"hnf[1]. i=%ld",i);
2103: tetpil=avma; A=gerepile(av,tetpil,ZM_copy(A));
2104: }
2105: }
2106: p1 = gcoeff(A,i,def); s = signe(p1);
2107: if (s)
2108: {
2109: if (s < 0) ZV_neg((GEN)A[def]);
2110: ZM_reduce(A, NULL, i,def);
2111: def--;
2112: }
2113: else
2114: if (ldef) ldef--;
2115: if (low_stack(lim, stack_lim(av,1)))
2116: {
2117: if (DEBUGMEM>1) err(warnmem,"hnf[2]. i=%ld",i);
2118: tetpil=avma; A=gerepile(av,tetpil,ZM_copy(A));
2119: }
2120: }
2121: if (remove)
2122: { /* remove null columns */
2123: for (i=1,j=1; j<co; j++)
2124: if (!gcmp0((GEN)A[j])) A[i++] = A[j];
2125: setlg(A,i);
2126: }
2127: tetpil=avma;
2128: A = denx? gdiv(A,denx): ZM_copy(A);
2129: return gerepile(av0,tetpil,A);
2130: }
2131:
2132: GEN
2133: hnf(GEN x) { return hnf0(x,1); }
2134:
2135: /* dm = multiple of diag element (usually detint(x)) */
2136: /* flag: don't/do append dm*matid. */
2137: static GEN
2138: allhnfmod(GEN x,GEN dm,int flag)
2139: {
2140: ulong av,tetpil,lim;
2141: long li,co,i,j,k,def,ldef,ldm;
2142: GEN a,b,w,p1,p2,d,u,v;
2143:
2144: if (typ(dm)!=t_INT) err(typeer,"allhnfmod");
2145: if (!signe(dm)) return hnf(x);
2146: if (typ(x)!=t_MAT) err(typeer,"allhnfmod");
2147:
2148: co=lg(x); if (co==1) return cgetg(1,t_MAT);
2149: li=lg(x[1]);
2150: av = avma; lim = stack_lim(av,1);
2151: x = dummycopy(x);
2152:
2153: if (flag)
2154: {
2155: if (li > co) err(talker,"nb lines > nb columns in hnfmod");
2156: }
2157: else
2158: { /* concatenate dm * Id to x */
2159: x = concatsp(x, idmat_intern(li-1,dm,gzero));
2160: co += li-1;
2161: }
2162: /* Avoid wasteful divisions. we only want to prevent coeff explosion, so
2163: * only reduce mod dm when lg(coeff) > ldm */
2164: ldm = lgefint(dm);
2165: def = co-1; ldef = 0;
2166: for (i=li-1; i>ldef; i--,def--)
2167: for (j=def-1; j; j--)
2168: {
2169: coeff(x,i,j) = lresii(gcoeff(x,i,j), dm);
2170: a = gcoeff(x,i,j);
2171: if (!signe(a)) continue;
2172:
2173: k = (j==1)? def: j-1;
2174: /* do not reduce the appended dm [hnfmodid] */
2175: if (flag || j != 1) coeff(x,i,k) = lresii(gcoeff(x,i,k), dm);
2176: ZV_elem(a,gcoeff(x,i,k), x,NULL, j,k);
2177: p1 = (GEN)x[j];
2178: p2 = (GEN)x[k];
2179: for (k=1; k<i; k++)
2180: {
2181: if (lgefint(p1[k]) > ldm) p1[k] = lresii((GEN)p1[k], dm);
2182: if (lgefint(p2[k]) > ldm) p2[k] = lresii((GEN)p2[k], dm);
2183: }
2184: if (low_stack(lim, stack_lim(av,1)))
2185: {
2186: if (DEBUGMEM>1) err(warnmem,"allhnfmod[1]. i=%ld",i);
2187: tetpil=avma; x=gerepile(av,tetpil,ZM_copy(x));
2188: }
2189: }
2190: w = cgetg(li,t_MAT); b = dm;
2191: for (i=li-1; i>=1; i--)
2192: {
2193: d = bezout(gcoeff(x,i,i+def),b,&u,&v);
2194: w[i] = lmod(gmul(u,(GEN)x[i+def]), b);
2195: if (!signe(gcoeff(w,i,i))) coeff(w,i,i) = (long)d;
2196: if (flag && i > 1) b = diviiexact(b,d);
2197: }
2198: if (flag)
2199: { /* compute optimal value for dm */
2200: dm = gcoeff(w,1,1);
2201: for (i=2; i<li; i++) dm = mpppcm(dm, gcoeff(w,i,i));
2202: ldm = lgefint(dm);
2203: }
2204: for (i=li-2; i>=1; i--)
2205: {
2206: GEN diag = gcoeff(w,i,i);
2207: for (j=i+1; j<li; j++)
2208: {
2209: b = negi(truedvmdii(gcoeff(w,i,j), diag, NULL));
2210: p1 = ZV_lincomb(gun,b, (GEN)w[j], (GEN)w[i]);
2211: w[j] = (long)p1;
2212: for (k=1; k<i; k++)
2213: if (lgefint(p1[k]) > ldm) p1[k] = lresii((GEN)p1[k], dm);
2214: if (low_stack(lim, stack_lim(av,1)))
2215: {
2216: if (DEBUGMEM>1) err(warnmem,"allhnfmod[2]. i=%ld", i);
2217: tetpil=avma; w=gerepile(av,tetpil,ZM_copy(w));
2218: diag = gcoeff(w,i,i);
2219: }
2220: }
2221: }
2222: tetpil=avma; return gerepile(av,tetpil,ZM_copy(w));
2223: }
2224:
2225: GEN
2226: hnfmod(GEN x, GEN detmat) { return allhnfmod(x,detmat,1); }
2227:
2228: GEN
2229: hnfmodid(GEN x, GEN p) { return allhnfmod(x,p,0); }
2230:
2231: /***********************************************************************/
2232: /* */
2233: /* HNFLLL (Havas, Majewski, Mathews) */
2234: /* */
2235: /***********************************************************************/
2236:
2237: /* negate in place, except universal constants */
2238: static GEN
2239: mynegi(GEN x)
2240: {
2241: static long mun[]={evaltyp(t_INT)|m_evallg(3),evalsigne(-1)|evallgefint(3),1};
2242: long s = signe(x);
2243:
2244: if (!s) return gzero;
2245: if (is_pm1(x))
2246: return (s>0)? mun: gun;
2247: setsigne(x,-s); return x;
2248: }
2249:
2250: /* We assume y > 0 */
2251: static GEN
2252: divnearest(GEN x, GEN y)
2253: {
2254: GEN r, q = dvmdii(x,y,&r);
2255: long av = avma, s=signe(r), t;
2256:
2257: if (!s) { cgiv(r); return q; }
2258: if (s<0) r = mynegi(r);
2259:
2260: y = shifti(y,-1); t = cmpii(r,y);
2261: avma=av; cgiv(r);
2262: if (t < 0 || (t == 0 && s > 0)) return q;
2263: return addsi(s,q);
2264: }
2265:
2266: static void
2267: Minus(long j, GEN **lambda)
2268: {
2269: long k, n = lg(lambda);
2270:
2271: for (k=1 ; k<j; k++) lambda[j][k] = mynegi(lambda[j][k]);
2272: for (k=j+1; k<n; k++) lambda[k][j] = mynegi(lambda[k][j]);
2273: }
2274:
2275: static void
2276: neg_col(GEN M)
2277: {
2278: long i;
2279: for (i = lg(M)-1; i; i--)
2280: M[i] = (long)mynegi((GEN)M[i]);
2281: }
2282:
2283: /* M_k = M_k + q M_i (col operations) */
2284: static void
2285: elt_col(GEN Mk, GEN Mi, GEN q)
2286: {
2287: long j;
2288: if (is_pm1(q))
2289: {
2290: if (signe(q) > 0)
2291: {
2292: for (j = lg(Mk)-1; j; j--)
2293: if (signe(Mi[j])) Mk[j] = laddii((GEN)Mk[j], (GEN)Mi[j]);
2294: }
2295: else
2296: {
2297: for (j = lg(Mk)-1; j; j--)
2298: if (signe(Mi[j])) Mk[j] = lsubii((GEN)Mk[j], (GEN)Mi[j]);
2299: }
2300: }
2301: else
2302: for (j = lg(Mk)-1; j; j--)
2303: if (signe(Mi[j])) Mk[j] = laddii((GEN)Mk[j], mulii(q, (GEN)Mi[j]));
2304: }
2305:
2306: /* index of first non-zero entry */
2307: static long
2308: findi(GEN M)
2309: {
2310: long i, n = lg(M);
2311: for (i=1; i<n; i++)
2312: if (signe(M[i])) return i;
2313: return 0;
2314: }
2315:
2316: static void
2317: reduce2(GEN A, GEN B, long k, long j, long *row, GEN **lambda, GEN *D)
2318: {
2319: GEN q;
2320: long i, row0, row1;
2321:
2322: row0 = findi((GEN)A[j]);
2323: if (row0 && signe(gcoeff(A,row0,j)) < 0)
2324: {
2325: neg_col((GEN)A[j]);
2326: if (B) neg_col((GEN)B[j]);
2327: Minus(j,lambda);
2328: }
2329:
2330: row1 = findi((GEN)A[k]);
2331: if (row1 && signe(gcoeff(A,row1,k)) < 0)
2332: {
2333: neg_col((GEN)A[k]);
2334: if (B) neg_col((GEN)B[k]);
2335: Minus(k,lambda);
2336: }
2337:
2338: row[0]=row0; row[1]=row1;
2339: if (row0)
2340: q = truedvmdii(gcoeff(A,row0,k), gcoeff(A,row0,j), NULL);
2341: else if (absi_cmp(shifti(lambda[k][j], 1), D[j]) > 0)
2342: q = divnearest(lambda[k][j], D[j]);
2343: else
2344: return;
2345:
2346: if (signe(q))
2347: {
2348: GEN *Lk = lambda[k], *Lj = lambda[j];
2349: q = mynegi(q);
2350: if (row0) elt_col((GEN)A[k],(GEN)A[j],q);
2351: if (B) elt_col((GEN)B[k],(GEN)B[j],q);
2352: Lk[j] = addii(Lk[j], mulii(q,D[j]));
2353: if (is_pm1(q))
2354: {
2355: if (signe(q) > 0)
2356: {
2357: for (i=1; i<j; i++)
2358: if (signe(Lj[i])) Lk[i] = addii(Lk[i], Lj[i]);
2359: }
2360: else
2361: {
2362: for (i=1; i<j; i++)
2363: if (signe(Lj[i])) Lk[i] = subii(Lk[i], Lj[i]);
2364: }
2365: }
2366: else
2367: {
2368: for (i=1; i<j; i++)
2369: if (signe(Lj[i])) Lk[i] = addii(Lk[i], mulii(q,Lj[i]));
2370: }
2371: }
2372: }
2373:
2374: #define SWAP(x,y) {GEN _t=y; y=x; x=_t;}
2375:
2376: static void
2377: hnfswap(GEN A, GEN B, long k, GEN **lambda, GEN *D)
2378: {
2379: GEN t,p1,p2;
2380: long i,j,n = lg(A);
2381:
2382: swap(A[k],A[k-1]);
2383: if (B) swap(B[k],B[k-1]);
2384: for (j=k-2; j; j--) SWAP(lambda[k-1][j], lambda[k][j]);
2385: for (i=k+1; i<n; i++)
2386: {
2387: p1 = mulii(lambda[i][k-1], D[k]);
2388: p2 = mulii(lambda[i][k], lambda[k][k-1]);
2389: t = subii(p1,p2);
2390:
2391: p1 = mulii(lambda[i][k], D[k-2]);
2392: p2 = mulii(lambda[i][k-1], lambda[k][k-1]);
2393: lambda[i][k-1] = divii(addii(p1,p2), D[k-1]);
2394:
2395: lambda[i][k] = divii(t, D[k-1]);
2396: }
2397: p1 = mulii(D[k-2],D[k]);
2398: p2 = sqri(lambda[k][k-1]);
2399: D[k-1] = divii(addii(p1,p2), D[k-1]);
2400: }
2401:
2402: /* A[k] = 0, A[nz] != 0, k > nz, A[j] = 0 for all j < nz.
2403: * "Deep insert" A[k] at nz */
2404: static void
2405: trivswap(GEN *A, long nz, long k, GEN **lambda, GEN *D)
2406: {
2407: GEN p1;
2408: long i,j,n = lg(A);
2409:
2410: p1 = A[nz]; /* cycle A */
2411: for (j = nz; j < k; j++) SWAP(A[j+1], p1);
2412: A[nz] = p1; /* = [0...0] */
2413:
2414: p1 = D[nz]; /* cycle D */
2415: for (j = nz; j < k; j++) SWAP(D[j+1], p1);
2416: D[nz] = gun;
2417:
2418: for (j=k-1; j>=nz; j--) /* cycle lambda */
2419: for (i=k-1; i>=nz; i--) lambda[i+1][j+1] = lambda[i][j];
2420: for (j=n-1; j>k; j--)
2421: for (i=k-1; i>=nz; i--)
2422: {
2423: lambda[i+1][j] = lambda[i][j];
2424: lambda[j][i+1] = lambda[j][i];
2425: }
2426: for (i=1; i<n; i++) lambda[nz][i] = lambda[i][nz] = gzero;
2427: }
2428:
2429: static GEN
2430: fix_rows(GEN A)
2431: {
2432: long i,j, h,n = lg(A);
2433: GEN cB,cA,B = cgetg(n,t_MAT);
2434: if (n == 1) return B;
2435: h = lg(A[1]);
2436: for (j=1; j<n; j++)
2437: {
2438: cB = cgetg(h, t_COL);
2439: cA = (GEN)A[j]; B[j] = (long)cB;
2440: for (i=h>>1; i; i--) { cB[h-i] = cA[i]; cB[i] = cA[h-i]; }
2441: }
2442: return B;
2443: }
2444:
2445: GEN
2446: hnflll_i(GEN A, GEN *ptB)
2447: {
2448: ulong av = avma, lim = stack_lim(av,3);
2449: long m1 = 1, n1 = 1; /* alpha = m1/n1. Maybe 3/4 here ? */
2450: long row[2], do_swap,i,n,k;
2451: long nzcol = 1; /* index of 1st (maybe) non-0 col [only updated when !B] */
2452: GEN z,B, **lambda, *D;
2453: GEN *gptr[4];
2454:
2455: if (typ(A) != t_MAT) err(typeer,"hnflll");
2456: n = lg(A);
2457: A = ZM_copy(fix_rows(A));
2458: B = ptB? idmat(n-1): NULL;
2459: D = (GEN*) cgetg(n+1, t_VEC); D++; /* hack: need a "sentinel" D[0] */
2460: if (n == 2) /* handle trivial case: return negative diag coeff otherwise */
2461: {
2462: i = findi((GEN)A[1]);
2463: if (i && signe(gcoeff(A,i,1)) < 0)
2464: {
2465: neg_col((GEN)A[1]);
2466: if (B) neg_col((GEN)B[1]);
2467: }
2468: }
2469: lambda = (GEN**) cgetg(n,t_MAT);
2470: for (i=1; i<n; i++) { D[i] = gun; lambda[i] = (GEN*)zerocol(n-1); }
2471: D[0] = gun; k = 2;
2472: while (k < n)
2473: {
2474: reduce2(A,B,k,k-1,row,lambda,D);
2475: if (!B)
2476: { /* not interested in B. Eliminate 0 cols */
2477: if (!row[0] || !row[1])
2478: {
2479: while (!findi((GEN)A[nzcol]) && nzcol < n) nzcol++;
2480: /* A[nzcol] != 0, A[i] = 0 for i < nzcol */
2481: if (!row[0] && k-1 > nzcol)
2482: {trivswap((GEN*)A,nzcol,k-1, lambda,D); nzcol++;}
2483: if (!row[1] && k > nzcol)
2484: {trivswap((GEN*)A,nzcol,k , lambda,D); nzcol++;}
2485: if (k <= nzcol) k = nzcol+1;
2486: continue;
2487: }
2488: do_swap = (row[0] && row[0] <= row[1]);
2489: }
2490: else
2491: {
2492: if (row[0])
2493: do_swap = (!row[1] || row[0] <= row[1]);
2494: else if (row[1])
2495: do_swap = 0;
2496: else
2497: { /* row[0] == row[1] == 0 */
2498: ulong av1 = avma;
2499: z = addii(mulii(D[k-2],D[k]), sqri(lambda[k][k-1]));
2500: do_swap = (cmpii(mulsi(n1,z), mulsi(m1,sqri(D[k-1]))) < 0);
2501: avma = av1;
2502: }
2503: }
2504: if (do_swap)
2505: {
2506: hnfswap(A,B,k,lambda,D);
2507: if (k > nzcol+1) k--;
2508: }
2509: else
2510: {
2511: for (i=k-2; i>=nzcol; i--) reduce2(A,B,k,i,row,lambda,D);
2512: k++;
2513: }
2514: if (low_stack(lim, stack_lim(av,3)))
2515: {
2516: GEN a = (GEN)lambda, b = (GEN)(D-1); /* gcc -Wall */
2517: gptr[0]=&A; gptr[1]=&a; gptr[2]=&b; gptr[3]=&B;
2518: if (DEBUGMEM) err(warnmem,"hnflll, k = %ld / %ld",k,n);
2519: gerepilemany(av,gptr,B? 4: 3); lambda = (GEN**)a; D = (GEN*)(b+1);
2520: }
2521: }
2522: for (i=nzcol; i<n; i++)
2523: if (findi((GEN)A[i])) break;
2524: i--; A += i; A[0] = evaltyp(t_MAT)|evallg(n-i);
2525: A = fix_rows(A);
2526: gptr[0] = &A; gptr[1] = &B;
2527: gerepilemany(av, gptr, B? 2: 1);
2528: if (B) *ptB = B;
2529: return A;
2530: }
2531:
2532: GEN
2533: hnflll(GEN A)
2534: {
2535: GEN B, z = cgetg(3, t_VEC);
2536: z[1] = (long)hnflll_i(A, &B);
2537: z[2] = (long)B; return z;
2538: }
2539:
2540: /* Variation on HNFLLL: Extended GCD */
2541:
2542: static void
2543: reduce1(GEN A, GEN B, long k, long j, GEN **lambda, GEN *D)
2544: {
2545: GEN q;
2546: long i;
2547:
2548: if (signe(A[j]))
2549: q = divnearest((GEN)A[k],(GEN)A[j]);
2550: else if (absi_cmp(shifti(lambda[k][j], 1), D[j]) > 0)
2551: q = divnearest(lambda[k][j], D[j]);
2552: else
2553: return;
2554:
2555: if (! gcmp0(q))
2556: {
2557: q = mynegi(q);
2558: A[k] = laddii((GEN)A[k], mulii(q,(GEN)A[j]));
2559: elt_col((GEN)B[k],(GEN)B[j],q);
2560: lambda[k][j] = addii(lambda[k][j], mulii(q,D[j]));
2561: for (i=1; i<j; i++)
2562: if (signe(lambda[j][i]))
2563: lambda[k][i] = addii(lambda[k][i], mulii(q,lambda[j][i]));
2564: }
2565: }
2566:
2567: GEN
2568: extendedgcd(GEN A)
2569: {
2570: long m1 = 1, n1 = 1; /* alpha = m1/n1. Maybe 3/4 here ? */
2571: long av = avma, tetpil, do_swap,i,j,n,k;
2572: GEN p1,p2,B, **lambda, *D;
2573:
2574: n = lg(A); B = idmat(n-1); A = ZM_copy(A);
2575: D = (GEN*) cgeti(n); lambda = (GEN**) cgetg(n,t_MAT);
2576: for (i=0; i<n; i++) D[i] = gun;
2577: for (i=1; i<n; i++)
2578: {
2579: lambda[i] = (GEN*) cgetg(n,t_COL);
2580: for(j=1;j<n;j++) lambda[i][j] = gzero;
2581: }
2582: k = 2;
2583: while (k < n)
2584: {
2585: reduce1(A,B,k,k-1,lambda,D);
2586: if (signe(A[k-1])) do_swap = 1;
2587: else if (!signe(A[k]))
2588: {
2589: long av1=avma;
2590: p1 = addii(mulii(D[k-2],D[k]), sqri(lambda[k][k-1]));
2591: p1 = mulsi(n1,p1);
2592: p2 = mulsi(m1,sqri(D[k-1]));
2593: do_swap = (cmpii(p1,p2) < 0);
2594: avma=av1;
2595: }
2596: else do_swap = 0;
2597:
2598: if (do_swap)
2599: {
2600: hnfswap(A,B,k,lambda,D);
2601: if (k>2) k--;
2602: }
2603: else
2604: {
2605: for (i=k-2; i; i--) reduce1(A,B,k,i,lambda,D);
2606: k++;
2607: }
2608: }
2609: if (signe(A[n-1])<0)
2610: {
2611: A[n-1] = (long)mynegi((GEN)A[n-1]);
2612: neg_col((GEN)B[n-1]);
2613: }
2614: tetpil = avma;
2615: p1 = cgetg(3,t_VEC);
2616: p1[1]=lcopy((GEN)A[n-1]);
2617: p1[2]=lcopy(B);
2618: return gerepile(av,tetpil,p1);
2619: }
2620:
2621: /* HNF with permutation. TODO: obsolete, replace with hnflll. */
2622: GEN
2623: hnfperm(GEN A)
2624: {
2625: GEN U,c,l,perm,d,u,p,q,y,b;
2626: long r,t,i,j,j1,k,m,n,av=avma,av1,tetpil,lim;
2627:
2628: if (typ(A) != t_MAT) err(typeer,"hnfperm");
2629: n = lg(A)-1;
2630: if (!n)
2631: {
2632: y = cgetg(4,t_VEC);
2633: y[1] = lgetg(1,t_MAT);
2634: y[2] = lgetg(1,t_MAT);
2635: y[3] = lgetg(1,t_VEC); return y;
2636: }
2637: m = lg(A[1])-1;
2638: c = cgetg(m+1,t_VECSMALL); for (i=1; i<=m; i++) c[i]=0;
2639: l = cgetg(n+1,t_VECSMALL); for (j=1; j<=n; j++) l[j]=0;
2640: perm = cgetg(m+1, t_VECSMALL);
2641: av1 = avma; lim = stack_lim(av1,1);
2642: U = idmat(n); A = dummycopy(A); /* U base change matrix : A0*U=A all along */
2643: for (r=0,k=1; k<=n; k++)
2644: {
2645: for (j=1; j<k; j++)
2646: {
2647: if (!l[j]) continue;
2648: t=l[j]; b=gcoeff(A,t,k);
2649: if (!signe(b)) continue;
2650:
2651: ZV_elem(b,gcoeff(A,t,j), A,U,k,j);
2652: d = gcoeff(A,t,j);
2653: if (signe(d) < 0)
2654: {
2655: ZV_neg((GEN)A[j]);
2656: ZV_neg((GEN)U[j]);
2657: d = gcoeff(A,t,j);
2658: }
2659: for (j1=1; j1<j; j1++)
2660: {
2661: if (!l[j1]) continue;
2662: q = truedvmdii(gcoeff(A,t,j1),d,NULL);
2663: if (!signe(q)) continue;
2664:
2665: q = negi(q);
2666: A[j1] = (long)ZV_lincomb(gun,q,(GEN)A[j1],(GEN)A[j]);
2667: U[j1] = (long)ZV_lincomb(gun,q,(GEN)U[j1],(GEN)U[j]);
2668: }
2669: }
2670: t=m; while (t && (c[t] || !signe(gcoeff(A,t,k)))) t--;
2671: if (t)
2672: {
2673: p = gcoeff(A,t,k);
2674: for (i=t-1; i; i--)
2675: {
2676: q = gcoeff(A,i,k);
2677: if (signe(q) && absi_cmp(p,q) > 0) { p=q; t=i; }
2678: }
2679: perm[++r]=l[k]=t; c[t]=k;
2680: if (signe(p) < 0)
2681: {
2682: ZV_neg((GEN)A[k]);
2683: ZV_neg((GEN)U[k]);
2684: p = gcoeff(A,t,k);
2685: }
2686: for (j=1; j<k; j++)
2687: {
2688: if (!l[j]) continue;
2689: q = truedvmdii(gcoeff(A,t,j),p,NULL);
2690: if (!signe(q)) continue;
2691:
2692: q = negi(q);
2693: A[j] = (long)ZV_lincomb(gun,q,(GEN)A[j],(GEN)A[k]);
2694: U[j] = (long)ZV_lincomb(gun,q,(GEN)U[j],(GEN)U[k]);
2695: }
2696: }
2697: if (low_stack(lim, stack_lim(av1,1)))
2698: {
2699: GEN *gptr[2]; gptr[0]=&A; gptr[1]=&U;
2700: if (DEBUGMEM>1) err(warnmem,"hnfperm");
2701: gerepilemany(av1,gptr,2);
2702: }
2703: }
2704: if (r < m)
2705: {
2706: for (i=1,k=r; i<=m; i++)
2707: if (c[i]==0) perm[++k] = i;
2708: }
2709:
2710: /* We have A0*U=A, U in Gl(n,Z)
2711: * basis for Im(A): columns of A s.t l[j]>0 (r cols)
2712: * basis for Ker(A): columns of U s.t l[j]=0 (n-r cols)
2713: */
2714: tetpil=avma; y=cgetg(4,t_VEC);
2715: p=cgetg(r+1,t_MAT); u=cgetg(n+1,t_MAT);
2716: for (t=1,k=r,j=1; j<=n; j++)
2717: if (l[j])
2718: {
2719: q=cgetg(m+1,t_COL); p[k]=(long)q;
2720: for (i=1; i<=m; i++) q[i]=lcopy(gcoeff(A,perm[m-i+1],j));
2721: u[k+n-r]=lcopy((GEN)U[j]);
2722: k--;
2723: }
2724: else u[t++]=lcopy((GEN)U[j]);
2725: y[1]=(long)p; y[2]=(long)u;
2726: q = cgetg(m+1,t_VEC); y[3]=(long)q;
2727: for (i=1; i<=m; i++) q[m-i+1]=lstoi(perm[i]);
2728: return gerepile(av,tetpil,y);
2729: }
2730:
2731: /*====================================================================
2732: * Forme Normale d'Hermite (Version par colonnes 31/01/94)
2733: *====================================================================*/
2734: GEN
2735: hnfall_i(GEN A, GEN *ptB, long remove)
2736: {
2737: GEN B,c,h,x,p,a;
2738: long m,n,r,i,j,k,li,av=avma,av1,tetpil,lim;
2739: GEN *gptr[2];
2740:
2741: if (typ(A)!=t_MAT) err(typeer,"hnfall");
2742: n=lg(A)-1;
2743: if (!n)
2744: {
2745: if (ptB) *ptB = cgetg(1,t_MAT);
2746: return cgetg(1,t_MAT);
2747: }
2748: m = lg(A[1])-1;
2749: c = cgetg(m+1,t_VECSMALL); for (i=1; i<=m; i++) c[i]=0;
2750: h = cgetg(n+1,t_VECSMALL); for (j=1; j<=n; j++) h[j]=m;
2751: av1 = avma; lim = stack_lim(av1,1);
2752: A = dummycopy(A);
2753: B = ptB? idmat(n): NULL;
2754: r = n+1;
2755: for (li=m; li; li--)
2756: {
2757: for (j=1; j<r; j++)
2758: {
2759: for (i=h[j]; i>li; i--)
2760: {
2761: a = gcoeff(A,i,j);
2762: if (!signe(a)) continue;
2763:
2764: k = c[i]; /* zero a = Aij using Aik */
2765: ZV_elem(a,gcoeff(A,i,k), A,B,j,k);
2766: ZM_reduce(A,B, i,k);
2767: if (low_stack(lim, stack_lim(av1,1)))
2768: {
2769: tetpil = avma;
2770: A = ZM_copy(A); gptr[0]=&A;
2771: if (B) { B = ZM_copy(B); gptr[1]=&B; }
2772: if (DEBUGMEM>1) err(warnmem,"hnfall[1], li = %ld", li);
2773: gerepilemanysp(av1,tetpil,gptr,B? 2: 1);
2774: }
2775: }
2776: x = gcoeff(A,li,j); if (signe(x)) break;
2777: h[j] = li-1;
2778: }
2779: if (j == r) continue;
2780: r--;
2781: if (j < r) /* A[j] != 0 */
2782: {
2783: swap(A[j], A[r]);
2784: if (B) swap(B[j], B[r]);
2785: h[j]=h[r]; h[r]=li; c[li]=r;
2786: }
2787: p = gcoeff(A,li,r);
2788: if (signe(p) < 0)
2789: {
2790: ZV_neg((GEN)A[r]);
2791: if (B) ZV_neg((GEN)B[r]);
2792: p = gcoeff(A,li,r);
2793: }
2794: ZM_reduce(A,B, li,r);
2795: if (low_stack(lim, stack_lim(av1,1)))
2796: {
2797: GEN *gptr[2]; gptr[0]=&A; gptr[1]=&B;
2798: if (DEBUGMEM>1) err(warnmem,"hnfall[2], li = %ld", li);
2799: gerepilemany(av1,gptr,B? 2: 1);
2800: }
2801: }
2802: if (DEBUGLEVEL>5) fprintferr("\nhnfall, final phase: ");
2803: r--; /* first r cols are in the image the n-r (independent) last ones */
2804: for (j=1; j<=r; j++)
2805: for (i=h[j]; i; i--)
2806: {
2807: a = gcoeff(A,i,j);
2808: if (!signe(a)) continue;
2809:
2810: k = c[i];
2811: ZV_elem(a,gcoeff(A,i,k), A,B, j,k);
2812: ZM_reduce(A,B, i,k);
2813: if (low_stack(lim, stack_lim(av1,1)))
2814: {
2815: tetpil = avma;
2816: A = ZM_copy(A); gptr[0]=&A;
2817: if (B) { B = ZM_copy(B); gptr[1]=&B; }
2818: if (DEBUGMEM>1) err(warnmem,"hnfall[3], j = %ld", j);
2819: gerepilemanysp(av1,tetpil,gptr, B? 2: 1);
2820: }
2821: }
2822: if (DEBUGLEVEL>5) fprintferr("\n");
2823: /* remove the first r columns */
2824: if (remove) { A += r; A[0] = evaltyp(t_MAT) | evallg(n-r+1); }
2825: gptr[0] = &A; gptr[1] = &B;
2826: gerepilemany(av, gptr, B? 2: 1);
2827: if (B) *ptB = B;
2828: return A;
2829: }
2830:
2831: GEN
2832: hnfall0(GEN A, long remove)
2833: {
2834: GEN B, z = cgetg(3, t_VEC);
2835: z[1] = (long)hnfall_i(A, &B, remove);
2836: z[2] = (long)B; return z;
2837: }
2838:
2839: GEN
2840: hnfall(GEN x) {return hnfall0(x,1);}
2841:
2842: /***************************************************************/
2843: /** **/
2844: /** SMITH NORMAL FORM REDUCTION **/
2845: /** **/
2846: /***************************************************************/
2847:
2848: static GEN
2849: col_mul(GEN x, GEN c)
2850: {
2851: long s = signe(x);
2852: GEN xc = NULL;
2853: if (s)
2854: {
2855: if (!is_pm1(x)) xc = gmul(x,c);
2856: else xc = (s>0)? c: gneg_i(c);
2857: }
2858: return xc;
2859: }
2860:
2861: static void
2862: do_zero(GEN x)
2863: {
2864: long i, lx = lg(x);
2865: for (i=1; i<lx; i++) x[i] = zero;
2866: }
2867:
2868: /* c1 <-- u.c1 + v.c2; c2 <-- a.c2 - b.c1 */
2869: static void
2870: update(GEN u, GEN v, GEN a, GEN b, GEN *c1, GEN *c2)
2871: {
2872: GEN p1,p2;
2873:
2874: u = col_mul(u,*c1);
2875: v = col_mul(v,*c2);
2876: if (u) p1 = v? gadd(u,v): u;
2877: else p1 = v? v: (GEN)NULL;
2878:
2879: a = col_mul(a,*c2);
2880: b = col_mul(gneg_i(b),*c1);
2881: if (a) p2 = b? gadd(a,b): a;
2882: else p2 = b? b: (GEN)NULL;
2883:
2884: if (!p1) do_zero(*c1); else *c1 = p1;
2885: if (!p2) do_zero(*c2); else *c2 = p2;
2886: }
2887:
2888: static GEN
2889: trivsmith(long all)
2890: {
2891: GEN z;
2892: if (!all) return cgetg(1,t_VEC);
2893: z=cgetg(4,t_VEC);
2894: z[1]=lgetg(1,t_MAT);
2895: z[2]=lgetg(1,t_MAT);
2896: z[3]=lgetg(1,t_MAT); return z;
2897: }
2898:
2899: /* Return the smith normal form d of matrix x. If all != 0 return [d,u,v],
2900: * where d = u.x.v
2901: */
2902: static GEN
2903: smithall(GEN x, long all)
2904: {
2905: long av,tetpil,i,j,k,l,c,fl,n,s1,s2,lim;
2906: GEN p1,p2,p3,p4,z,b,u,v,d,ml,mr,mun,mdet,ys;
2907:
2908: if (typ(x)!=t_MAT) err(typeer,"smithall");
2909: if (DEBUGLEVEL>=9) outerr(x);
2910: n=lg(x)-1;
2911: if (!n) return trivsmith(all);
2912: if (lg(x[1]) != n+1) err(mattype1,"smithall");
2913: for (i=1; i<=n; i++)
2914: for (j=1; j<=n; j++)
2915: if (typ(coeff(x,i,j)) != t_INT)
2916: err(talker,"non integral matrix in smithall");
2917:
2918: av = avma; lim = stack_lim(av,1);
2919: x = dummycopy(x); mdet = detint(x);
2920: if (ishnfall(x)) { if (all) { ml=idmat(n); mr=idmat(n); } }
2921: else
2922: {
2923: if (signe(mdet))
2924: {
2925: p1=hnfmod(x,mdet);
2926: if (all) { ml=idmat(n); mr=gauss(x,p1); }
2927: }
2928: else
2929: {
2930: if (all)
2931: {
2932: p1 = hnfall0(x,0);
2933: ml = idmat(n); mr = (GEN)p1[2]; p1 = (GEN)p1[1];
2934: }
2935: else
2936: p1 = hnf0(x,0);
2937: }
2938: x = p1;
2939: }
2940: p1=cgetg(n+1,t_VEC); for (i=1; i<=n; i++) p1[i]=lnegi(gcoeff(x,i,i));
2941: p2=sindexsort(p1); ys=cgetg(n+1,t_MAT);
2942: for (j=1; j<=n; j++)
2943: {
2944: p1=cgetg(n+1,t_COL); ys[j]=(long)p1;
2945: for (i=1; i<=n; i++) p1[i]=coeff(x,p2[i],p2[j]);
2946: }
2947: x = ys;
2948: if (all)
2949: {
2950: p3=cgetg(n+1,t_MAT); p4=cgetg(n+1,t_MAT);
2951: for (j=1; j<=n; j++) { p3[j]=ml[p2[j]]; p4[j]=mr[p2[j]]; }
2952: ml=p3; mr=p4;
2953: }
2954: if (signe(mdet))
2955: {
2956: p1 = hnfmod(x,mdet);
2957: if (all) mr=gmul(mr,gauss(x,p1));
2958: }
2959: else
2960: {
2961: if (all)
2962: {
2963: p1 = hnfall0(x,0);
2964: mr = gmul(mr,(GEN)p1[2]); p1 = (GEN)p1[1];
2965: }
2966: else
2967: p1 = hnf0(x,0);
2968: }
2969: x=p1; mun = negi(gun);
2970:
2971: if (DEBUGLEVEL>7) {fprintferr("starting SNF loop");flusherr();}
2972: for (i=n; i>=2; i--)
2973: {
2974: if (DEBUGLEVEL>7) {fprintferr("\ni = %ld: ",i);flusherr();}
2975: for(;;)
2976: {
2977: c = 0;
2978: for (j=i-1; j>=1; j--)
2979: {
2980: p1=gcoeff(x,i,j); s1 = signe(p1);
2981: if (s1)
2982: {
2983: p2=gcoeff(x,i,i);
2984: if (!absi_cmp(p1,p2))
2985: {
2986: s2=signe(p2);
2987: if (s1 == s2) { d=p1; u=gun; p4=gun; }
2988: else
2989: {
2990: if (s2>0) { u = gun; p4 = mun; }
2991: else { u = mun; p4 = gun; }
2992: d=(s1>0)? p1: absi(p1);
2993: }
2994: v = gzero; p3 = u;
2995: }
2996: else { d=bezout(p2,p1,&u,&v); p3=divii(p2,d); p4=divii(p1,d); }
2997: for (k=1; k<=i; k++)
2998: {
2999: b=addii(mulii(u,gcoeff(x,k,i)),mulii(v,gcoeff(x,k,j)));
3000: coeff(x,k,j)=lsubii(mulii(p3,gcoeff(x,k,j)),
3001: mulii(p4,gcoeff(x,k,i)));
3002: coeff(x,k,i)=(long)b;
3003: }
3004: if (all) update(u,v,p3,p4,(GEN*)(mr+i),(GEN*)(mr+j));
3005: if (low_stack(lim, stack_lim(av,1)))
3006: {
3007: if (DEBUGMEM>1) err(warnmem,"[1]: smithall");
3008: if (all)
3009: {
3010: GEN *gptr[3]; gptr[0]=&x; gptr[1]=&ml; gptr[2]=&mr;
3011: gerepilemany(av,gptr,3);
3012: }
3013: else x=gerepileupto(av, ZM_copy(x));
3014: }
3015: }
3016: }
3017: if (DEBUGLEVEL>=8) {fprintferr("; ");flusherr();}
3018: for (j=i-1; j>=1; j--)
3019: {
3020: p1=gcoeff(x,j,i); s1 = signe(p1);
3021: if (s1)
3022: {
3023: p2=gcoeff(x,i,i);
3024: if (!absi_cmp(p1,p2))
3025: {
3026: s2 = signe(p2);
3027: if (s1 == s2) { d=p1; u=gun; p4=gun; }
3028: else
3029: {
3030: if (s2>0) { u = gun; p4 = mun; }
3031: else { u = mun; p4 = gun; }
3032: d=(s1>0)? p1: absi(p1);
3033: }
3034: v = gzero; p3 = u;
3035: }
3036: else { d=bezout(p2,p1,&u,&v); p3=divii(p2,d); p4=divii(p1,d); }
3037: for (k=1; k<=i; k++)
3038: {
3039: b=addii(mulii(u,gcoeff(x,i,k)),mulii(v,gcoeff(x,j,k)));
3040: coeff(x,j,k)=lsubii(mulii(p3,gcoeff(x,j,k)),
3041: mulii(p4,gcoeff(x,i,k)));
3042: coeff(x,i,k)=(long)b;
3043: }
3044: if (all) update(u,v,p3,p4,(GEN*)(ml+i),(GEN*)(ml+j));
3045: c = 1;
3046: }
3047: }
3048: if (!c)
3049: {
3050: b=gcoeff(x,i,i); fl=1;
3051: if (signe(b))
3052: {
3053: for (k=1; k<i && fl; k++)
3054: for (l=1; l<i && fl; l++)
3055: fl = (int)!signe(resii(gcoeff(x,k,l),b));
3056: /* cast to (int) necessary for gcc-2.95 on sparcv9-64 (IS) */
3057: if (!fl)
3058: {
3059: k--;
3060: for (l=1; l<=i; l++)
3061: coeff(x,i,l)=laddii(gcoeff(x,i,l),gcoeff(x,k,l));
3062: if (all) ml[i]=ladd((GEN)ml[i],(GEN)ml[k]);
3063: }
3064: }
3065: if (fl) break;
3066: }
3067: if (low_stack(lim, stack_lim(av,1)))
3068: {
3069: if (DEBUGMEM>1) err(warnmem,"[2]: smithall");
3070: if (all)
3071: {
3072: GEN *gptr[3]; gptr[0]=&x; gptr[1]=&ml; gptr[2]=&mr;
3073: gerepilemany(av,gptr,3);
3074: }
3075: else x=gerepileupto(av,ZM_copy(x));
3076: }
3077: }
3078: }
3079: if (DEBUGLEVEL>7) {fprintferr("\n");flusherr();}
3080: if (all)
3081: {
3082: for (k=1; k<=n; k++)
3083: if (signe(gcoeff(x,k,k))<0)
3084: { mr[k]=lneg((GEN)mr[k]); coeff(x,k,k)=lnegi(gcoeff(x,k,k)); }
3085: tetpil=avma; z=cgetg(4,t_VEC);
3086: z[1]=ltrans(ml); z[2]=lcopy(mr); z[3]=lcopy(x);
3087: return gerepile(av,tetpil,z);
3088: }
3089: tetpil=avma; z=cgetg(n+1,t_VEC); j=n;
3090: for (k=n; k; k--)
3091: if (signe(gcoeff(x,k,k))) z[j--]=labsi(gcoeff(x,k,k));
3092: for ( ; j; j--) z[j]=zero;
3093: return gerepile(av,tetpil,z);
3094: }
3095:
3096: GEN
3097: smith(GEN x) { return smithall(x,0); }
3098:
3099: GEN
3100: smith2(GEN x) { return smithall(x,1); }
3101:
3102: /* Assume z was computed by [g]smithall(). Remove the 1s on the diagonal */
3103: GEN
3104: smithclean(GEN z)
3105: {
3106: long i,j,l,c;
3107: GEN u,v,y,d,p1;
3108:
3109: if (typ(z) != t_VEC) err(typeer,"smithclean");
3110: l = lg(z); if (l == 1) return cgetg(1,t_VEC);
3111: u=(GEN)z[1];
3112: if (l != 4 || typ(u) != t_MAT)
3113: {
3114: if (typ(u) != t_INT) err(typeer,"smithclean");
3115: for (c=1; c<l; c++)
3116: if (gcmp1((GEN)z[c])) break;
3117: return gcopy_i(z, c);
3118: }
3119: v=(GEN)z[2]; d=(GEN)z[3]; l = lg(d);
3120: for (c=1; c<l; c++)
3121: if (gcmp1(gcoeff(d,c,c))) break;
3122:
3123: y=cgetg(4,t_VEC);
3124: y[1]=(long)(p1 = cgetg(l,t_MAT));
3125: for (i=1; i<l; i++) p1[i] = (long)gcopy_i((GEN)u[i], c);
3126: y[2]=(long)gcopy_i(v, c);
3127: y[3]=(long)(p1 = cgetg(c,t_MAT));
3128: for (i=1; i<c; i++)
3129: {
3130: GEN p2 = cgetg(c,t_COL); p1[i] = (long)p2;
3131: for (j=1; j<c; j++) p2[j] = i==j? lcopy(gcoeff(d,i,i)): zero;
3132: }
3133: return y;
3134: }
3135:
3136: static GEN
3137: gsmithall(GEN x,long all)
3138: {
3139: long av,tetpil,i,j,k,l,c,n, lim;
3140: GEN p1,p2,p3,p4,z,b,u,v,d,ml,mr;
3141:
3142: if (typ(x)!=t_MAT) err(typeer,"gsmithall");
3143: n=lg(x)-1;
3144: if (!n) return trivsmith(all);
3145: if (lg(x[1]) != n+1) err(mattype1,"gsmithall");
3146: av = avma; lim = stack_lim(av,1);
3147: x = dummycopy(x);
3148: if (all) { ml=idmat(n); mr=idmat(n); }
3149: for (i=n; i>=2; i--)
3150: {
3151: do
3152: {
3153: c=0;
3154: for (j=i-1; j>=1; j--)
3155: {
3156: p1=gcoeff(x,i,j);
3157: if (signe(p1))
3158: {
3159: p2=gcoeff(x,i,i);
3160: if (!signe(p2))
3161: {
3162: p3 = gzero; p4 = gun; u = gzero; v = gun;
3163: }
3164: else
3165: {
3166: v = gdiventres(p1,p2);
3167: if (gcmp0((GEN)v[2]))
3168: { d=p2; p4=(GEN)v[1]; v=gzero; p3=gun; u=gun; }
3169: else
3170: { d=gbezout(p2,p1,&u,&v); p3=gdiv(p2,d); p4=gdiv(p1,d); }
3171: }
3172: for (k=1; k<=i; k++)
3173: {
3174: b=gadd(gmul(u,gcoeff(x,k,i)),gmul(v,gcoeff(x,k,j)));
3175: coeff(x,k,j)=lsub(gmul(p3,gcoeff(x,k,j)),gmul(p4,gcoeff(x,k,i)));
3176: coeff(x,k,i)=(long)b;
3177: }
3178: if (all) update(u,v,p3,p4,(GEN*)(mr+i),(GEN*)(mr+j));
3179: }
3180: }
3181: for (j=i-1; j>=1; j--)
3182: {
3183: p1=gcoeff(x,j,i);
3184: if (signe(p1))
3185: {
3186: p2 = gcoeff(x,i,i);
3187: if (!signe(p2))
3188: {
3189: p3 = gzero; p4 = gun; u = gzero; v = gun;
3190: }
3191: else
3192: {
3193: v = gdiventres(p1,p2);
3194: if (gcmp0((GEN)v[2]))
3195: { d=p2; p4=(GEN)v[1]; v=gzero; p3=gun; u=gun; }
3196: else
3197: { d=gbezout(p2,p1,&u,&v); p3=gdiv(p2,d); p4=gdiv(p1,d); }
3198: }
3199: for (k=1; k<=i; k++)
3200: {
3201: b=gadd(gmul(u,gcoeff(x,i,k)),gmul(v,gcoeff(x,j,k)));
3202: coeff(x,j,k)=lsub(gmul(p3,gcoeff(x,j,k)),gmul(p4,gcoeff(x,i,k)));
3203: coeff(x,i,k)=(long)b;
3204: }
3205: if (all) update(u,v,p3,p4,(GEN*)(ml+i),(GEN*)(ml+j));
3206: c = 1;
3207: }
3208: }
3209: if (!c)
3210: {
3211: b = gcoeff(x,i,i);
3212: if (signe(b))
3213: for (k=1; k<i; k++)
3214: for (l=1; l<i; l++)
3215: if (signe(gmod(gcoeff(x,k,l),b)))
3216: {
3217: for (l=1; l<=i; l++)
3218: coeff(x,i,l) = ladd(gcoeff(x,i,l),gcoeff(x,k,l));
3219: if (all) ml[i] = ladd((GEN)ml[i],(GEN)ml[k]);
3220: k = l = i; c = 1;
3221: }
3222: }
3223: if (low_stack(lim, stack_lim(av,1)))
3224: {
3225: if (DEBUGMEM>1) err(warnmem,"[5]: smithall");
3226: if (all)
3227: {
3228: GEN *gptr[3]; gptr[0]=&x; gptr[1]=&ml; gptr[2]=&mr;
3229: gerepilemany(av,gptr,3);
3230: }
3231: else x=gerepilecopy(av,x);
3232: }
3233: }
3234: while (c);
3235: }
3236: if (all)
3237: {
3238: for (k=1; k<=n; k++)
3239: if (signe(gcoeff(x,k,k)) < 0)
3240: { mr[k]=lneg((GEN)mr[k]); coeff(x,k,k)=lneg(gcoeff(x,k,k)); }
3241: tetpil=avma; z=cgetg(4,t_VEC);
3242: z[1]=ltrans(ml); z[2]=lcopy(mr); z[3]=lcopy(x);
3243: }
3244: else
3245: {
3246: tetpil=avma; z=cgetg(n+1,t_VEC);
3247: for (j=0,k=1; k<=n; k++) if (!signe(gcoeff(x,k,k))) z[++j]=zero;
3248: for (k=1; k<=n; k++)
3249: if (signe(p1=gcoeff(x,k,k))) z[++j]=(long)gabs(p1,0);
3250: }
3251: return gerepile(av,tetpil,z);
3252: }
3253:
3254: GEN
3255: matsnf0(GEN x,long flag)
3256: {
3257: long av = avma;
3258: if (flag > 7) err(flagerr,"matsnf");
3259: if (typ(x) == t_VEC && flag & 4) return smithclean(x);
3260: if (flag & 2) x = gsmithall(x,flag & 1);
3261: else x = smithall(x, flag & 1);
3262: if (flag & 4) x = smithclean(x);
3263: return gerepileupto(av, x);
3264: }
3265:
3266: GEN
3267: gsmith(GEN x) { return gsmithall(x,0); }
3268:
3269: GEN
3270: gsmith2(GEN x) { return gsmithall(x,1); }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>