[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

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>