[BACK]Return to alglin2.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / basemath

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 non­0 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>