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

Annotation of OpenXM_contrib/pari/src/basemath/alglin2.c, Revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>