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

Annotation of OpenXM_contrib/pari-2.2/src/basemath/alglin1.c, Revision 1.1

1.1     ! noro        1: /* $Id: alglin1.c,v 1.57 2001/10/01 12:11:27 karim Exp $
        !             2:
        !             3: Copyright (C) 2000  The PARI group.
        !             4:
        !             5: This file is part of the PARI/GP package.
        !             6:
        !             7: PARI/GP is free software; you can redistribute it and/or modify it under the
        !             8: terms of the GNU General Public License as published by the Free Software
        !             9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
        !            10: ANY WARRANTY WHATSOEVER.
        !            11:
        !            12: Check the License for details. You should have received a copy of it, along
        !            13: with the package; see the file 'COPYING'. If not, write to the Free Software
        !            14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
        !            15:
        !            16: /********************************************************************/
        !            17: /**                                                                **/
        !            18: /**                         LINEAR ALGEBRA                         **/
        !            19: /**                          (first part)                          **/
        !            20: /**                                                                **/
        !            21: /********************************************************************/
        !            22: #include "pari.h"
        !            23:
        !            24: /* for linear algebra mod p */
        !            25: #ifdef LONG_IS_64BIT
        !            26: #  define MASK (0x7fffffff00000000UL)
        !            27: #else
        !            28: #  define MASK (0x7fff0000UL)
        !            29: #endif
        !            30:
        !            31: /* 2p^2 < 2^BITS_IN_LONG */
        !            32: #ifdef LONG_IS_64BIT
        !            33: #  define u_OK_ULONG(p) ((ulong)p <= 3037000493UL)
        !            34: #else
        !            35: #  define u_OK_ULONG(p) ((ulong)p <= 46337UL)
        !            36: #endif
        !            37: #define OK_ULONG(p) (lgefint(p) == 3 && u_OK_ULONG(p[2]))
        !            38: extern GEN ZM_init_CRT(GEN Hp, ulong p);
        !            39: extern ulong u_invmod(ulong x, ulong p);
        !            40:
        !            41: /*******************************************************************/
        !            42: /*                                                                 */
        !            43: /*                         TRANSPOSE                               */
        !            44: /*                                                                 */
        !            45: /*******************************************************************/
        !            46:
        !            47: /* No copy*/
        !            48: GEN
        !            49: gtrans_i(GEN x)
        !            50: {
        !            51:   long i,j,lx,dx, tx=typ(x);
        !            52:   GEN y,p1;
        !            53:
        !            54:   if (! is_matvec_t(tx)) err(typeer,"gtrans_i");
        !            55:   switch(tx)
        !            56:   {
        !            57:     case t_VEC:
        !            58:       y=dummycopy(x); settyp(y,t_COL); break;
        !            59:
        !            60:     case t_COL:
        !            61:       y=dummycopy(x); settyp(y,t_VEC); break;
        !            62:
        !            63:     case t_MAT:
        !            64:       lx=lg(x); if (lx==1) return cgetg(1,t_MAT);
        !            65:       dx=lg(x[1]); y=cgetg(dx,tx);
        !            66:       for (i=1; i<dx; i++)
        !            67:       {
        !            68:        p1=cgetg(lx,t_COL); y[i]=(long)p1;
        !            69:        for (j=1; j<lx; j++) p1[j]=coeff(x,i,j);
        !            70:       }
        !            71:       break;
        !            72:
        !            73:     default: y=x; break;
        !            74:   }
        !            75:   return y;
        !            76: }
        !            77:
        !            78:
        !            79: GEN
        !            80: gtrans(GEN x)
        !            81: {
        !            82:   long i,j,lx,dx, tx=typ(x);
        !            83:   GEN y,p1;
        !            84:
        !            85:   if (! is_matvec_t(tx)) err(typeer,"gtrans");
        !            86:   switch(tx)
        !            87:   {
        !            88:     case t_VEC:
        !            89:       y=gcopy(x); settyp(y,t_COL); break;
        !            90:
        !            91:     case t_COL:
        !            92:       y=gcopy(x); settyp(y,t_VEC); break;
        !            93:
        !            94:     case t_MAT:
        !            95:       lx=lg(x); if (lx==1) return cgetg(1,t_MAT);
        !            96:       dx=lg(x[1]); y=cgetg(dx,tx);
        !            97:       for (i=1; i<dx; i++)
        !            98:       {
        !            99:        p1=cgetg(lx,t_COL); y[i]=(long)p1;
        !           100:        for (j=1; j<lx; j++) p1[j]=lcopy(gcoeff(x,i,j));
        !           101:       }
        !           102:       break;
        !           103:
        !           104:     default: y=gcopy(x); break;
        !           105:   }
        !           106:   return y;
        !           107: }
        !           108:
        !           109: /*******************************************************************/
        !           110: /*                                                                 */
        !           111: /*                    CONCATENATION & EXTRACTION                   */
        !           112: /*                                                                 */
        !           113: /*******************************************************************/
        !           114:
        !           115: static GEN
        !           116: strconcat(GEN x, GEN y)
        !           117: {
        !           118:   long flx=0,fly=0,l;
        !           119:   char *sx,*sy,*str;
        !           120:
        !           121:   if (typ(x)==t_STR) sx = GSTR(x); else { flx=1; sx = GENtostr(x); }
        !           122:   if (typ(y)==t_STR) sy = GSTR(y); else { fly=1; sy = GENtostr(y); }
        !           123:   l = strlen(sx) + strlen(sy) + 1;
        !           124:   l = (l+BYTES_IN_LONG) >> TWOPOTBYTES_IN_LONG;
        !           125:   x = cgetg(l+1, t_STR); str = GSTR(x);
        !           126:   strcpy(str,sx);
        !           127:   strcat(str,sy);
        !           128:   if (flx) free(sx);
        !           129:   if (fly) free(sy);
        !           130:   return x;
        !           131: }
        !           132:
        !           133: /* concat 3 matrices. Internal */
        !           134: GEN
        !           135: concatsp3(GEN x, GEN y, GEN z)
        !           136: {
        !           137:   long i, lx = lg(x), ly = lg(y), lz = lg(z);
        !           138:   GEN r = cgetg(lx+ly+lz-2, t_MAT), t = r;
        !           139:   for (i=1; i<lx; i++) *++t = *++x;
        !           140:   for (i=1; i<ly; i++) *++t = *++y;
        !           141:   for (i=1; i<lz; i++) *++t = *++z;
        !           142:   return r;
        !           143: }
        !           144:
        !           145: /* concat A and B vertically. Internal */
        !           146: GEN
        !           147: vconcat(GEN A, GEN B)
        !           148: {
        !           149:   long la,ha,hb,hc,i,j;
        !           150:   GEN M,a,b,c;
        !           151:
        !           152:   la = lg(A); if (la==1) return A;
        !           153:   ha = lg(A[1]); M = cgetg(la,t_MAT);
        !           154:   hb = lg(B[1]); hc = ha+hb-1;
        !           155:   for (j=1; j<la; j++)
        !           156:   {
        !           157:     c = cgetg(hc,t_COL); M[j] = (long)c; a = (GEN)A[j]; b = (GEN)B[j];
        !           158:     for (i=1; i<ha; i++) *++c = *++a;
        !           159:     for (i=1; i<hb; i++) *++c = *++b;
        !           160:   }
        !           161:   return M;
        !           162: }
        !           163:
        !           164: GEN
        !           165: _vec(GEN x) { GEN v = cgetg(2, t_VEC); v[1] = (long)x; return v; }
        !           166: GEN
        !           167: _col(GEN x) { GEN v = cgetg(2, t_COL); v[1] = (long)x; return v; }
        !           168:
        !           169: GEN
        !           170: concatsp(GEN x, GEN y)
        !           171: {
        !           172:   long tx=typ(x),ty=typ(y),lx=lg(x),ly=lg(y),i;
        !           173:   GEN z,p1;
        !           174:
        !           175:   if (tx==t_LIST || ty==t_LIST) return listconcat(x,y);
        !           176:   if (tx==t_STR  || ty==t_STR)  return strconcat(x,y);
        !           177:
        !           178:   if (tx==t_MAT && lx==1)
        !           179:   {
        !           180:     if (ty!=t_VEC || ly==1) return gtomat(y);
        !           181:     err(concater);
        !           182:   }
        !           183:   if (ty==t_MAT && ly==1)
        !           184:   {
        !           185:     if (tx!=t_VEC || lx==1) return gtomat(x);
        !           186:     err(concater);
        !           187:   }
        !           188:
        !           189:   if (! is_matvec_t(tx))
        !           190:   {
        !           191:     if (! is_matvec_t(ty))
        !           192:     {
        !           193:       z=cgetg(3,t_VEC); z[1]=(long)x; z[2]=(long)y;
        !           194:       return z;
        !           195:     }
        !           196:     z=cgetg(ly+1,ty);
        !           197:     if (ty != t_MAT) p1 = x;
        !           198:     else
        !           199:     {
        !           200:       if (lg(y[1])!=2) err(concater);
        !           201:       p1=cgetg(2,t_COL); p1[1]=(long)x;
        !           202:     }
        !           203:     for (i=2; i<=ly; i++) z[i]=y[i-1];
        !           204:     z[1]=(long)p1; return z;
        !           205:   }
        !           206:   if (! is_matvec_t(ty))
        !           207:   {
        !           208:     z=cgetg(lx+1,tx);
        !           209:     if (tx != t_MAT) p1 = y;
        !           210:     else
        !           211:     {
        !           212:       if (lg(x[1])!=2) err(concater);
        !           213:       p1=cgetg(2,t_COL); p1[1]=(long)y;
        !           214:     }
        !           215:     for (i=1; i<lx; i++) z[i]=x[i];
        !           216:     z[lx]=(long)p1; return z;
        !           217:   }
        !           218:
        !           219:   if (tx == ty)
        !           220:   {
        !           221:     if (tx == t_MAT && lg(x[1]) != lg(y[1])) err(concater);
        !           222:     z=cgetg(lx+ly-1,tx);
        !           223:     for (i=1; i<lx; i++) z[i]=x[i];
        !           224:     for (i=1; i<ly; i++) z[lx+i-1]=y[i];
        !           225:     return z;
        !           226:   }
        !           227:
        !           228:   switch(tx)
        !           229:   {
        !           230:     case t_VEC:
        !           231:       switch(ty)
        !           232:       {
        !           233:        case t_COL:
        !           234:          if (lx<=2) return (lx==1)? y: concatsp((GEN) x[1],y);
        !           235:           if (ly>=3) break;
        !           236:           return (ly==1)? x: concatsp(x,(GEN) y[1]);
        !           237:        case t_MAT:
        !           238:          z=cgetg(ly,ty); if (lx != ly) break;
        !           239:          for (i=1; i<ly; i++) z[i]=(long)concatsp((GEN) x[i],(GEN) y[i]);
        !           240:           return z;
        !           241:       }
        !           242:       break;
        !           243:
        !           244:     case t_COL:
        !           245:       switch(ty)
        !           246:       {
        !           247:        case t_VEC:
        !           248:          if (lx<=2) return (lx==1)? y: concatsp((GEN) x[1],y);
        !           249:          if (ly>=3) break;
        !           250:          return (ly==1)? x: concatsp(x,(GEN) y[1]);
        !           251:        case t_MAT:
        !           252:          if (lx != lg(y[1])) break;
        !           253:          z=cgetg(ly+1,ty); z[1]=(long)x;
        !           254:          for (i=2; i<=ly; i++) z[i]=y[i-1];
        !           255:           return z;
        !           256:       }
        !           257:       break;
        !           258:
        !           259:     case t_MAT:
        !           260:       switch(ty)
        !           261:       {
        !           262:        case t_VEC:
        !           263:          z=cgetg(lx,tx); if (ly != lx) break;
        !           264:          for (i=1; i<lx; i++) z[i]=(long)concatsp((GEN) x[i],(GEN) y[i]);
        !           265:           return z;
        !           266:        case t_COL:
        !           267:          if (ly != lg(x[1])) break;
        !           268:          z=cgetg(lx+1,tx); z[lx]=(long)y;
        !           269:          for (i=1; i<lx; i++) z[i]=x[i];
        !           270:           return z;
        !           271:       }
        !           272:       break;
        !           273:   }
        !           274:   err(concater);
        !           275:   return NULL; /* not reached */
        !           276: }
        !           277:
        !           278: GEN
        !           279: concat(GEN x, GEN y)
        !           280: {
        !           281:   long tx = typ(x), lx,ty,ly,i;
        !           282:   GEN z,p1;
        !           283:
        !           284:   if (!y)
        !           285:   {
        !           286:     ulong av = avma;
        !           287:     if (tx == t_LIST)
        !           288:       { lx = lgef(x); i = 2; }
        !           289:     else if (tx == t_VEC)
        !           290:       { lx = lg(x); i = 1; }
        !           291:     else
        !           292:     {
        !           293:       err(concater);
        !           294:       return NULL; /* not reached */
        !           295:     }
        !           296:     if (i>=lx) err(talker,"trying to concat elements of an empty vector");
        !           297:     y = (GEN)x[i++];
        !           298:     for (; i<lx; i++) y = concatsp(y, (GEN)x[i]);
        !           299:     return gerepilecopy(av,y);
        !           300:   }
        !           301:   ty = typ(y);
        !           302:   if (tx==t_LIST || ty==t_LIST) return listconcat(x,y);
        !           303:   if (tx==t_STR  || ty==t_STR)  return strconcat(x,y);
        !           304:   lx=lg(x); ly=lg(y);
        !           305:
        !           306:   if (tx==t_MAT && lx==1)
        !           307:   {
        !           308:     if (ty!=t_VEC || ly==1) return gtomat(y);
        !           309:     err(concater);
        !           310:   }
        !           311:   if (ty==t_MAT && ly==1)
        !           312:   {
        !           313:     if (tx!=t_VEC || lx==1) return gtomat(x);
        !           314:     err(concater);
        !           315:   }
        !           316:
        !           317:   if (! is_matvec_t(tx))
        !           318:   {
        !           319:     if (! is_matvec_t(ty))
        !           320:     {
        !           321:       z=cgetg(3,t_VEC); z[1]=lcopy(x); z[2]=lcopy(y);
        !           322:       return z;
        !           323:     }
        !           324:     z=cgetg(ly+1,ty);
        !           325:     if (ty != t_MAT) p1 = gcopy(x);
        !           326:     else
        !           327:     {
        !           328:       if (lg(y[1])!=2) err(concater);
        !           329:       p1=cgetg(2,t_COL); p1[1]=lcopy(x);
        !           330:     }
        !           331:     for (i=2; i<=ly; i++) z[i]=lcopy((GEN) y[i-1]);
        !           332:     z[1]=(long)p1; return z;
        !           333:   }
        !           334:   if (! is_matvec_t(ty))
        !           335:   {
        !           336:     z=cgetg(lx+1,tx);
        !           337:     if (tx != t_MAT) p1 = gcopy(y);
        !           338:     else
        !           339:     {
        !           340:       if (lg(x[1])!=2) err(concater);
        !           341:       p1=cgetg(2,t_COL); p1[1]=lcopy(y);
        !           342:     }
        !           343:     for (i=1; i<lx; i++) z[i]=lcopy((GEN) x[i]);
        !           344:     z[lx]=(long)p1; return z;
        !           345:   }
        !           346:
        !           347:   if (tx == ty)
        !           348:   {
        !           349:     if (tx == t_MAT && lg(x[1]) != lg(y[1])) err(concater);
        !           350:     z=cgetg(lx+ly-1,tx);
        !           351:     for (i=1; i<lx; i++) z[i]=lcopy((GEN) x[i]);
        !           352:     for (i=1; i<ly; i++) z[lx+i-1]=lcopy((GEN) y[i]);
        !           353:     return z;
        !           354:   }
        !           355:
        !           356:   switch(tx)
        !           357:   {
        !           358:     case t_VEC:
        !           359:       switch(ty)
        !           360:       {
        !           361:        case t_COL:
        !           362:          if (lx<=2) return (lx==1)? gcopy(y): concat((GEN) x[1],y);
        !           363:           if (ly>=3) break;
        !           364:           return (ly==1)? gcopy(x): concat(x,(GEN) y[1]);
        !           365:        case t_MAT:
        !           366:          z=cgetg(ly,ty); if (lx != ly) break;
        !           367:          for (i=1; i<ly; i++) z[i]=lconcat((GEN) x[i],(GEN) y[i]);
        !           368:           return z;
        !           369:       }
        !           370:       break;
        !           371:
        !           372:     case t_COL:
        !           373:       switch(ty)
        !           374:       {
        !           375:        case t_VEC:
        !           376:          if (lx<=2) return (lx==1)? gcopy(y): concat((GEN) x[1],y);
        !           377:          if (ly>=3) break;
        !           378:          return (ly==1)? gcopy(x): concat(x,(GEN) y[1]);
        !           379:        case t_MAT:
        !           380:          if (lx != lg(y[1])) break;
        !           381:          z=cgetg(ly+1,ty); z[1]=lcopy(x);
        !           382:          for (i=2; i<=ly; i++) z[i]=lcopy((GEN) y[i-1]);
        !           383:           return z;
        !           384:       }
        !           385:       break;
        !           386:
        !           387:     case t_MAT:
        !           388:       switch(ty)
        !           389:       {
        !           390:        case t_VEC:
        !           391:          z=cgetg(lx,tx); if (ly != lx) break;
        !           392:          for (i=1; i<lx; i++) z[i]=lconcat((GEN) x[i],(GEN) y[i]);
        !           393:           return z;
        !           394:        case t_COL:
        !           395:          if (ly != lg(x[1])) break;
        !           396:          z=cgetg(lx+1,tx); z[lx]=lcopy(y);
        !           397:          for (i=1; i<lx; i++) z[i]=lcopy((GEN) x[i]);
        !           398:           return z;
        !           399:       }
        !           400:       break;
        !           401:   }
        !           402:   err(concater);
        !           403:   return NULL; /* not reached */
        !           404: }
        !           405:
        !           406: static long
        !           407: str_to_long(char *s, char **pt)
        !           408: {
        !           409:   long a = atol(s);
        !           410:   while (isspace((int)*s)) s++;
        !           411:   if (*s == '-' || *s == '+') s++;
        !           412:   while (isdigit((int)*s) || isspace((int)*s)) s++;
        !           413:   *pt = s; return a;
        !           414: }
        !           415:
        !           416: static int
        !           417: get_range(char *s, long *a, long *b, long *cmpl, long lx)
        !           418: {
        !           419:   long max = lx - 1;
        !           420:
        !           421:   *a = 1; *b = max;
        !           422:   if (*s == '^') { *cmpl = 1; s++; } else *cmpl = 0;
        !           423:   if (*s == 0) return 0;
        !           424:   if (*s != '.')
        !           425:   {
        !           426:     *a = str_to_long(s, &s);
        !           427:     if (*a < 0) *a += lx;
        !           428:     if (*a<1 || *a>max) return 0;
        !           429:   }
        !           430:   if (*s == '.')
        !           431:   {
        !           432:     s++; if (*s != '.') return 0;
        !           433:     do s++; while (isspace((int)*s));
        !           434:     if (*s)
        !           435:     {
        !           436:       *b = str_to_long(s, &s);
        !           437:       if (*b < 0) *b += lx;
        !           438:       if (*b<1 || *b>max || *s) return 0;
        !           439:     }
        !           440:     return 1;
        !           441:   }
        !           442:   if (*s) return 0;
        !           443:   *b = *a; return 1;
        !           444: }
        !           445:
        !           446: GEN
        !           447: vecextract_i(GEN A, long y1, long y2)
        !           448: {
        !           449:   long i,lB = y2 - y1 + 2;
        !           450:   GEN B = cgetg(lB, typ(A));
        !           451:   for (i=1; i<lB; i++) B[i] = A[y1-1+i];
        !           452:   return B;
        !           453: }
        !           454:
        !           455: GEN
        !           456: rowextract_i(GEN A, long x1, long x2)
        !           457: {
        !           458:   long i, lB = lg(A);
        !           459:   GEN B = cgetg(lB, typ(A));
        !           460:   for (i=1; i<lB; i++) B[i] = (long)vecextract_i((GEN)A[i],x1,x2);
        !           461:   return B;
        !           462: }
        !           463:
        !           464: GEN
        !           465: vecextract_p(GEN A, GEN p)
        !           466: {
        !           467:   long i,lB = lg(p);
        !           468:   GEN B = cgetg(lB, typ(A));
        !           469:   for (i=1; i<lB; i++) B[i] = A[p[i]];
        !           470:   return B;
        !           471: }
        !           472:
        !           473: GEN
        !           474: rowextract_p(GEN A, GEN p)
        !           475: {
        !           476:   long i, lB = lg(A);
        !           477:   GEN B = cgetg(lB, typ(A));
        !           478:   for (i=1; i<lB; i++) B[i] = (long)vecextract_p((GEN)A[i],p);
        !           479:   return B;
        !           480: }
        !           481:
        !           482: void
        !           483: vecselect_p(GEN A, GEN B, GEN p, long init, long lB)
        !           484: {
        !           485:   long i; setlg(B, lB);
        !           486:   for (i=init; i<lB; i++) B[i] = A[p[i]];
        !           487: }
        !           488:
        !           489: /* B := p . A = row selection according to permutation p. Treat only lower
        !           490:  * right corner init x init */
        !           491: void
        !           492: rowselect_p(GEN A, GEN B, GEN p, long init)
        !           493: {
        !           494:   long i, lB = lg(A), lp = lg(p);
        !           495:   for (i=1; i<init; i++) setlg(B[i],lp);
        !           496:   for (   ; i<lB;   i++) vecselect_p((GEN)A[i],(GEN)B[i],p,init,lp);
        !           497: }
        !           498:
        !           499: GEN
        !           500: extract(GEN x, GEN l)
        !           501: {
        !           502:   long av,i,j, tl = typ(l), tx = typ(x), lx = lg(x);
        !           503:   GEN y;
        !           504:
        !           505:   if (! is_matvec_t(tx)) err(typeer,"extract");
        !           506:   if (tl==t_INT)
        !           507:   {
        !           508:     /* extract components of x as per the bits of mask l */
        !           509:     if (!signe(l)) return cgetg(1,tx);
        !           510:     av=avma; y = (GEN) gpmalloc(lx*sizeof(long));
        !           511:     i = j = 1; while (!mpodd(l)) { l=shifti(l,-1); i++; }
        !           512:     while (signe(l) && i<lx)
        !           513:     {
        !           514:       if (mod2(l)) y[j++] = x[i];
        !           515:       i++; l=shifti(l,-1);
        !           516:     }
        !           517:     if (signe(l)) err(talker,"mask too large in vecextract");
        !           518:     y[0] = evaltyp(tx) | evallg(j);
        !           519:     avma=av; x = gcopy(y); free(y); return x;
        !           520:   }
        !           521:   if (tl==t_STR)
        !           522:   {
        !           523:     char *s = GSTR(l);
        !           524:     long first, last, cmpl;
        !           525:     if (! get_range(s, &first, &last, &cmpl, lx))
        !           526:       err(talker, "incorrect range in extract");
        !           527:     if (lx == 1) return gcopy(x);
        !           528:     if (cmpl)
        !           529:     {
        !           530:       if (first <= last)
        !           531:       {
        !           532:         y = cgetg(lx - (last - first + 1),tx);
        !           533:         for (j=1; j<first; j++) y[j] = lcopy((GEN)x[j]);
        !           534:         for (i=last+1; i<lx; i++,j++) y[j] = lcopy((GEN)x[i]);
        !           535:       }
        !           536:       else
        !           537:       {
        !           538:         y = cgetg(lx - (first - last + 1),tx);
        !           539:         for (j=1,i=lx-1; i>first; i--,j++) y[j] = lcopy((GEN)x[i]);
        !           540:         for (i=last-1; i>0; i--,j++) y[j] = lcopy((GEN)x[i]);
        !           541:       }
        !           542:     }
        !           543:     else
        !           544:     {
        !           545:       if (first <= last)
        !           546:       {
        !           547:         y = cgetg(last-first+2,tx);
        !           548:         for (i=first,j=1; i<=last; i++,j++) y[j] = lcopy((GEN)x[i]);
        !           549:       }
        !           550:       else
        !           551:       {
        !           552:         y = cgetg(first-last+2,tx);
        !           553:         for (i=first,j=1; i>=last; i--,j++) y[j] = lcopy((GEN)x[i]);
        !           554:       }
        !           555:     }
        !           556:     return y;
        !           557:   }
        !           558:
        !           559:   if (is_vec_t(tl))
        !           560:   {
        !           561:     long ll=lg(l); y=cgetg(ll,tx);
        !           562:     for (i=1; i<ll; i++)
        !           563:     {
        !           564:       j = itos((GEN) l[i]);
        !           565:       if (j>=lx || j<=0) err(talker,"no such component in vecextract");
        !           566:       y[i] = lcopy((GEN) x[j]);
        !           567:     }
        !           568:     return y;
        !           569:   }
        !           570:   if (tl == t_VECSMALL)
        !           571:   {
        !           572:     long ll=lg(l); y=cgetg(ll,tx);
        !           573:     for (i=1; i<ll; i++)
        !           574:     {
        !           575:       j = l[i];
        !           576:       if (j>=lx || j<=0) err(talker,"no such component in vecextract");
        !           577:       y[i] = lcopy((GEN) x[j]);
        !           578:     }
        !           579:     return y;
        !           580:   }
        !           581:   err(talker,"incorrect mask in vecextract");
        !           582:   return NULL; /* not reached */
        !           583: }
        !           584:
        !           585: GEN
        !           586: matextract(GEN x, GEN l1, GEN l2)
        !           587: {
        !           588:   long av = avma, tetpil;
        !           589:
        !           590:   if (typ(x)!=t_MAT) err(typeer,"matextract");
        !           591:   x = extract(gtrans(extract(x,l2)),l1); tetpil=avma;
        !           592:   return gerepile(av,tetpil, gtrans(x));
        !           593: }
        !           594:
        !           595: GEN
        !           596: extract0(GEN x, GEN l1, GEN l2)
        !           597: {
        !           598:   if (! l2) return extract(x,l1);
        !           599:   return matextract(x,l1,l2);
        !           600: }
        !           601:
        !           602: /*******************************************************************/
        !           603: /*                                                                 */
        !           604: /*                     SCALAR-MATRIX OPERATIONS                    */
        !           605: /*                                                                 */
        !           606: /*******************************************************************/
        !           607:
        !           608: /* create the square nxn matrix equal to z*Id */
        !           609: static GEN
        !           610: gscalmat_proto(GEN z, GEN myzero, long n, int flag)
        !           611: {
        !           612:   long i,j;
        !           613:   GEN y = cgetg(n+1,t_MAT);
        !           614:   if (n < 0) err(talker,"negative size in scalmat");
        !           615:   if (flag) z = (flag==1)? stoi((long)z): gcopy(z);
        !           616:   for (i=1; i<=n; i++)
        !           617:   {
        !           618:     y[i]=lgetg(n+1,t_COL);
        !           619:     for (j=1; j<=n; j++)
        !           620:       coeff(y,j,i) = (i==j)? (long)z: (long)myzero;
        !           621:   }
        !           622:   return y;
        !           623: }
        !           624:
        !           625: GEN
        !           626: gscalmat(GEN x, long n) { return gscalmat_proto(x,gzero,n,2); }
        !           627:
        !           628: GEN
        !           629: gscalsmat(long x, long n) { return gscalmat_proto((GEN)x,gzero,n,1); }
        !           630:
        !           631: GEN
        !           632: idmat(long n) { return gscalmat_proto(gun,gzero,n,0); }
        !           633:
        !           634: GEN
        !           635: idmat_intern(long n,GEN myun,GEN z) { return gscalmat_proto(myun,z,n,0); }
        !           636:
        !           637: GEN
        !           638: gscalcol_proto(GEN z, GEN myzero, long n)
        !           639: {
        !           640:   GEN y = cgetg(n+1,t_COL);
        !           641:   long i;
        !           642:
        !           643:   if (n)
        !           644:   {
        !           645:     y[1]=(long)z;
        !           646:     for (i=2; i<=n; i++) y[i]=(long)myzero;
        !           647:   }
        !           648:   return y;
        !           649: }
        !           650:
        !           651: GEN
        !           652: zerocol(long n)
        !           653: {
        !           654:   GEN y = cgetg(n+1,t_COL);
        !           655:   long i; for (i=1; i<=n; i++) y[i]=zero;
        !           656:   return y;
        !           657: }
        !           658:
        !           659: GEN
        !           660: zerovec(long n)
        !           661: {
        !           662:   GEN y = cgetg(n+1,t_VEC);
        !           663:   long i; for (i=1; i<=n; i++) y[i]=zero;
        !           664:   return y;
        !           665: }
        !           666:
        !           667: GEN
        !           668: zeromat(long m, long n)
        !           669: {
        !           670:   GEN y = cgetg(n+1,t_MAT);
        !           671:   long i; for (i=1; i<=n; i++) y[i]=(long)zerocol(m);
        !           672:   return y;
        !           673: }
        !           674:
        !           675: GEN
        !           676: gscalcol(GEN x, long n)
        !           677: {
        !           678:   GEN y=gscalcol_proto(gzero,gzero,n);
        !           679:   if (n) y[1]=lcopy(x);
        !           680:   return y;
        !           681: }
        !           682:
        !           683: GEN
        !           684: gscalcol_i(GEN x, long n) { return gscalcol_proto(x,gzero,n); }
        !           685:
        !           686: GEN
        !           687: gtomat(GEN x)
        !           688: {
        !           689:   long tx,lx,i;
        !           690:   GEN y,p1;
        !           691:
        !           692:   if (!x) return cgetg(1, t_MAT);
        !           693:   tx = typ(x);
        !           694:   if (! is_matvec_t(tx))
        !           695:   {
        !           696:     y=cgetg(2,t_MAT); p1=cgetg(2,t_COL); y[1]=(long)p1;
        !           697:     p1[1]=lcopy(x); return y;
        !           698:   }
        !           699:   switch(tx)
        !           700:   {
        !           701:     case t_VEC:
        !           702:       lx=lg(x); y=cgetg(lx,t_MAT);
        !           703:       for (i=1; i<lx; i++)
        !           704:       {
        !           705:        p1=cgetg(2,t_COL); y[i]=(long)p1;
        !           706:        p1[1]=lcopy((GEN) x[i]);
        !           707:       }
        !           708:       break;
        !           709:     case t_COL:
        !           710:       y=cgetg(2,t_MAT); y[1]=lcopy(x); break;
        !           711:     default: /* case t_MAT: */
        !           712:       y=gcopy(x); break;
        !           713:   }
        !           714:   return y;
        !           715: }
        !           716:
        !           717: long
        !           718: isscalarmat(GEN x, GEN s)
        !           719: {
        !           720:   long nco,i,j;
        !           721:
        !           722:   if (typ(x)!=t_MAT) err(typeer,"isdiagonal");
        !           723:   nco=lg(x)-1; if (!nco) return 1;
        !           724:   if (nco != lg(x[1])-1) return 0;
        !           725:
        !           726:   for (j=1; j<=nco; j++)
        !           727:   {
        !           728:     GEN *col = (GEN*) x[j];
        !           729:     for (i=1; i<=nco; i++)
        !           730:       if (i == j)
        !           731:       {
        !           732:         if (!gegal(col[i],s)) return 0;
        !           733:       }
        !           734:       else if (!gcmp0(col[i])) return 0;
        !           735:   }
        !           736:   return 1;
        !           737: }
        !           738:
        !           739: long
        !           740: isdiagonal(GEN x)
        !           741: {
        !           742:   long nco,i,j;
        !           743:
        !           744:   if (typ(x)!=t_MAT) err(typeer,"isdiagonal");
        !           745:   nco=lg(x)-1; if (!nco) return 1;
        !           746:   if (nco != lg(x[1])-1) return 0;
        !           747:
        !           748:   for (j=1; j<=nco; j++)
        !           749:   {
        !           750:     GEN *col = (GEN*) x[j];
        !           751:     for (i=1; i<=nco; i++)
        !           752:       if (i!=j && !gcmp0(col[i])) return 0;
        !           753:   }
        !           754:   return 1;
        !           755: }
        !           756:
        !           757: /* create the diagonal matrix, whose diagonal is given by x */
        !           758: GEN
        !           759: diagonal(GEN x)
        !           760: {
        !           761:   long i,j,lx,tx=typ(x);
        !           762:   GEN y,p1;
        !           763:
        !           764:   if (! is_matvec_t(tx)) return gscalmat(x,1);
        !           765:   if (tx==t_MAT)
        !           766:   {
        !           767:     if (isdiagonal(x)) return gcopy(x);
        !           768:     err(talker,"incorrect object in diagonal");
        !           769:   }
        !           770:   lx=lg(x); y=cgetg(lx,t_MAT);
        !           771:   for (j=1; j<lx; j++)
        !           772:   {
        !           773:     p1=cgetg(lx,t_COL); y[j]=(long)p1;
        !           774:     for (i=1; i<lx; i++)
        !           775:       p1[i] = (i==j)? lcopy((GEN) x[i]): zero;
        !           776:   }
        !           777:   return y;
        !           778: }
        !           779:
        !           780: /* compute m*diagonal(d) */
        !           781: GEN
        !           782: matmuldiagonal(GEN m, GEN d)
        !           783: {
        !           784:   long j=typ(d),lx=lg(m);
        !           785:   GEN y;
        !           786:
        !           787:   if (typ(m)!=t_MAT) err(typeer,"matmuldiagonal");
        !           788:   if (! is_vec_t(j) || lg(d)!=lx)
        !           789:     err(talker,"incorrect vector in matmuldiagonal");
        !           790:   y=cgetg(lx,t_MAT);
        !           791:   for (j=1; j<lx; j++) y[j] = lmul((GEN) d[j],(GEN) m[j]);
        !           792:   return y;
        !           793: }
        !           794:
        !           795: /* compute m*n assuming the result is a diagonal matrix */
        !           796: GEN
        !           797: matmultodiagonal(GEN m, GEN n)
        !           798: {
        !           799:   long lx,i,j;
        !           800:   GEN s,y;
        !           801:
        !           802:   if (typ(m)!=t_MAT || typ(n)!=t_MAT) err(typeer,"matmultodiagonal");
        !           803:   lx=lg(n); y=idmat(lx-1);
        !           804:   if (lx == 1)
        !           805:     { if (lg(m) != 1) err(consister,"matmultodiagonal"); }
        !           806:   else
        !           807:     { if (lg(m) != lg(n[1])) err(consister,"matmultodiagonal"); }
        !           808:   for (i=1; i<lx; i++)
        !           809:   {
        !           810:     s = gzero;
        !           811:     for (j=1; j<lx; j++)
        !           812:       s = gadd(s,gmul(gcoeff(m,i,j),gcoeff(n,j,i)));
        !           813:     coeff(y,i,i) = (long)s;
        !           814:   }
        !           815:   return y;
        !           816: }
        !           817:
        !           818: /* [m[1,1], ..., m[l,l]], internal */
        !           819: GEN
        !           820: mattodiagonal_i(GEN m)
        !           821: {
        !           822:   long i, lx = lg(m);
        !           823:   GEN y = cgetg(lx,t_VEC);
        !           824:   for (i=1; i<lx; i++) y[i] = coeff(m,i,i);
        !           825:   return y;
        !           826: }
        !           827:
        !           828: /* same, public function */
        !           829: GEN
        !           830: mattodiagonal(GEN m)
        !           831: {
        !           832:   long i, lx = lg(m);
        !           833:   GEN y = cgetg(lx,t_VEC);
        !           834:
        !           835:   if (typ(m)!=t_MAT) err(typeer,"mattodiagonal");
        !           836:   for (i=1; i<lx; i++) y[i] = lcopy(gcoeff(m,i,i));
        !           837:   return y;
        !           838: }
        !           839:
        !           840: /*******************************************************************/
        !           841: /*                                                                 */
        !           842: /*                    ADDITION SCALAR + MATRIX                     */
        !           843: /*                                                                 */
        !           844: /*******************************************************************/
        !           845:
        !           846: /* create the square matrix x*Id + y */
        !           847: GEN
        !           848: gaddmat(GEN x, GEN y)
        !           849: {
        !           850:   long ly,dy,i,j;
        !           851:   GEN z;
        !           852:
        !           853:   ly=lg(y); if (ly==1) return cgetg(1,t_MAT);
        !           854:   dy=lg(y[1]);
        !           855:   if (typ(y)!=t_MAT || ly!=dy) err(mattype1,"gaddmat");
        !           856:   z=cgetg(ly,t_MAT);
        !           857:   for (i=1; i<ly; i++)
        !           858:   {
        !           859:     z[i]=lgetg(dy,t_COL);
        !           860:     for (j=1; j<dy; j++)
        !           861:       coeff(z,j,i) = i==j? ladd(x,gcoeff(y,j,i)): lcopy(gcoeff(y,j,i));
        !           862:   }
        !           863:   return z;
        !           864: }
        !           865:
        !           866: /*******************************************************************/
        !           867: /*                                                                 */
        !           868: /*                       Solve A*X=B (Gauss pivot)                 */
        !           869: /*                                                                 */
        !           870: /*******************************************************************/
        !           871: #define swap(x,y) { long _t=x; x=y; y=_t; }
        !           872:
        !           873: /* Assume x is a non-empty matrix. Return 0 if maximal pivot should not be
        !           874:  * used, and the matrix precision (min real precision of coeffs) otherwise.
        !           875:  */
        !           876: static long
        !           877: matprec(GEN x)
        !           878: {
        !           879:   long tx,i,j,l, k = VERYBIGINT, lx = lg(x), ly = lg(x[1]);
        !           880:   GEN p1;
        !           881:   for (i=1; i<lx; i++)
        !           882:     for (j=1; j<ly; j++)
        !           883:     {
        !           884:       p1 = gmael(x,i,j); tx = typ(p1);
        !           885:       if (!is_scalar_t(tx)) return 0;
        !           886:       l = precision(p1); if (l && l<k) k = l;
        !           887:     }
        !           888:   return (k==VERYBIGINT)? 0: k;
        !           889: }
        !           890:
        !           891: /* As above, returning 1 if the precision would be non-zero, 0 otherwise */
        !           892: static long
        !           893: use_maximal_pivot(GEN x)
        !           894: {
        !           895:   long tx,i,j, lx = lg(x), ly = lg(x[1]);
        !           896:   GEN p1;
        !           897:   for (i=1; i<lx; i++)
        !           898:     for (j=1; j<ly; j++)
        !           899:     {
        !           900:       p1 = gmael(x,i,j); tx = typ(p1);
        !           901:       if (!is_scalar_t(tx)) return 0;
        !           902:       if (precision(p1)) return 1;
        !           903:     }
        !           904:   return 0;
        !           905: }
        !           906:
        !           907: static GEN
        !           908: check_b(GEN b, long nbli)
        !           909: {
        !           910:   GEN col;
        !           911:   if (!b) return idmat(nbli);
        !           912:   col = (typ(b) == t_MAT)? (GEN)b[1]: b;
        !           913:   if (nbli != lg(col)-1) err(talker,"incompatible matrix dimensions in gauss");
        !           914:   return dummycopy(b);
        !           915: }
        !           916:
        !           917: /* C = A^(-1)(tB) where A, B, C are integral, A is upper triangular, t t_INT */
        !           918: GEN
        !           919: gauss_triangle_i(GEN A, GEN B, GEN t)
        !           920: {
        !           921:   long n = lg(A)-1, i,j,k;
        !           922:   GEN m, c = cgetg(n+1,t_MAT);
        !           923:
        !           924:   if (!n) return c;
        !           925:   for (k=1; k<=n; k++)
        !           926:   {
        !           927:     GEN u = cgetg(n+1, t_COL), b = (GEN)B[k];
        !           928:     ulong av = avma;
        !           929:     c[k] = (long)u; m = mulii((GEN)b[n],t);
        !           930:     u[n] = (long)gerepileuptoint(av, divii(m, gcoeff(A,n,n)));
        !           931:     for (i=n-1; i>0; i--)
        !           932:     {
        !           933:       av = avma; m = mulii(negi((GEN)b[i]),t);
        !           934:       for (j=i+1; j<=n; j++)
        !           935:         m = addii(m, mulii(gcoeff(A,i,j),(GEN) u[j]));
        !           936:       u[i] = (long)gerepileuptoint(av, divii(negi(m), gcoeff(A,i,i)));
        !           937:     }
        !           938:   }
        !           939:   return c;
        !           940: }
        !           941:
        !           942: GEN
        !           943: gauss_get_col(GEN a, GEN b, GEN p, long li)
        !           944: {
        !           945:   GEN m, u=cgetg(li+1,t_COL);
        !           946:   long i,j;
        !           947:
        !           948:   u[li] = ldiv((GEN)b[li], p);
        !           949:   for (i=li-1; i>0; i--)
        !           950:   {
        !           951:     m = gneg_i((GEN)b[i]);
        !           952:     for (j=i+1; j<=li; j++)
        !           953:       m = gadd(m, gmul(gcoeff(a,i,j), (GEN)u[j]));
        !           954:     u[i] = ldiv(gneg_i(m), gcoeff(a,i,i));
        !           955:   }
        !           956:   return u;
        !           957: }
        !           958:
        !           959: GEN
        !           960: Fp_gauss_get_col(GEN a, GEN b, GEN piv, long li, GEN p)
        !           961: {
        !           962:   GEN m, u=cgetg(li+1,t_COL);
        !           963:   long i,j;
        !           964:
        !           965:   u[li] = lresii(mulii((GEN)b[li], mpinvmod(piv,p)), p);
        !           966:   for (i=li-1; i>0; i--)
        !           967:   {
        !           968:     m = (GEN)b[i];
        !           969:     for (j=i+1; j<=li; j++)
        !           970:       m = subii(m, mulii(gcoeff(a,i,j), (GEN)u[j]));
        !           971:     m = resii(m, p);
        !           972:     u[i] = lresii(mulii(m, mpinvmod(gcoeff(a,i,i), p)), p);
        !           973:   }
        !           974:   return u;
        !           975: }
        !           976:
        !           977: /* assume -p < a < p, return 1/a mod p */
        !           978: static long
        !           979: u_Fp_inv(long a, long p)
        !           980: {
        !           981:   if (a < 0) a = p + a; /* pb with ulongs < 0 */
        !           982:   return u_invmod(a,p);
        !           983: }
        !           984:
        !           985: GEN
        !           986: u_Fp_gauss_get_col(GEN a, GEN b, long piv, long li, long p)
        !           987: {
        !           988:   GEN u=cgetg(li+1,t_VECSMALL);
        !           989:   long i,j, m;
        !           990:
        !           991:   u[li] = (b[li] *  u_Fp_inv(piv,p)) % p;
        !           992:   if (u[li] < 0) u[li] += p;
        !           993:   for (i=li-1; i>0; i--)
        !           994:   {
        !           995:     m = b[i];
        !           996:     for (j=i+1; j<=li; j++) { m -= coeff(a,i,j) * u[j]; if (m & MASK) m %= p; }
        !           997:     u[i] = ((m%p) * u_Fp_inv(coeff(a,i,i), p)) % p;
        !           998:     if (u[i] < 0) u[i] += p;
        !           999:   }
        !          1000:   return u;
        !          1001: }
        !          1002:
        !          1003: /* bk += m * bi */
        !          1004: static void
        !          1005: _addmul(GEN b, long k, long i, GEN m)
        !          1006: {
        !          1007:   b[k] = ladd((GEN)b[k], gmul(m, (GEN)b[i]));
        !          1008: }
        !          1009:
        !          1010: /* same, reduce mod p */
        !          1011: static void
        !          1012: _Fp_addmul(GEN b, long k, long i, GEN m, GEN p)
        !          1013: {
        !          1014:   if (lgefint(b[i]) > lgefint(p)) b[i] = lresii((GEN)b[i], p);
        !          1015:   b[k] = laddii((GEN)b[k], mulii(m, (GEN)b[i]));
        !          1016: }
        !          1017:
        !          1018: static void
        !          1019: _u_Fp_addmul(GEN b, long k, long i, long m, long p)
        !          1020: {
        !          1021:   long a;
        !          1022:   if (b[i] & MASK) b[i] %= p;
        !          1023:   a = b[k] + m * b[i];
        !          1024:   if (a & MASK) a %= p;
        !          1025:   b[k] = a;
        !          1026: }
        !          1027:
        !          1028: /* Gaussan Elimination. Compute a^(-1)*b
        !          1029:  * b is a matrix or column vector, NULL meaning: take the identity matrix
        !          1030:  * If a and b are empty, the result is the empty matrix.
        !          1031:  *
        !          1032:  * li: nb lines of a and b
        !          1033:  * aco: nb columns of a
        !          1034:  * bco: nb columns of b (if matrix)
        !          1035:  *
        !          1036:  * li > aco is allowed if b = NULL, in which case return c such that c a = Id */
        !          1037: GEN
        !          1038: gauss_intern(GEN a, GEN b)
        !          1039: {
        !          1040:   long inexact,iscol,i,j,k,av,lim,li,bco, aco = lg(a)-1;
        !          1041:   GEN p,m,u;
        !          1042:
        !          1043:   if (typ(a)!=t_MAT) err(mattype1,"gauss");
        !          1044:   if (b && typ(b)!=t_COL && typ(b)!=t_MAT) err(typeer,"gauss");
        !          1045:   if (!aco)
        !          1046:   {
        !          1047:     if (b && lg(b)!=1) err(consister,"gauss");
        !          1048:     if (DEBUGLEVEL) err(warner,"in Gauss lg(a)=1 lg(b)=%ld", b?1:-1);
        !          1049:     return cgetg(1,t_MAT);
        !          1050:   }
        !          1051:   av=avma; lim=stack_lim(av,1);
        !          1052:   li = lg(a[1])-1;
        !          1053:   if (li != aco && (li < aco || b)) err(mattype1,"gauss");
        !          1054:   a = dummycopy(a);
        !          1055:   b = check_b(b,li); bco = lg(b)-1;
        !          1056:   inexact = use_maximal_pivot(a);
        !          1057:   iscol   = (typ(b)==t_COL);
        !          1058:   if(DEBUGLEVEL>4)
        !          1059:     fprintferr("Entering gauss with inexact=%ld iscol=%ld\n",inexact,iscol);
        !          1060:
        !          1061:   p = NULL; /* gcc -Wall */
        !          1062:   for (i=1; i<=aco; i++)
        !          1063:   {
        !          1064:     /* k is the line where we find the pivot */
        !          1065:     p = gcoeff(a,i,i); k = i;
        !          1066:     if (inexact) /* maximal pivot */
        !          1067:     {
        !          1068:       long e, ex = gexpo(p);
        !          1069:       for (j=i+1; j<=li; j++)
        !          1070:       {
        !          1071:         e = gexpo(gcoeff(a,j,i));
        !          1072:         if (e > ex) { ex=e; k=j; }
        !          1073:       }
        !          1074:       if (gcmp0(gcoeff(a,k,i))) return NULL;
        !          1075:     }
        !          1076:     else if (gcmp0(p)) /* first non-zero pivot */
        !          1077:     {
        !          1078:       do k++; while (k<=li && gcmp0(gcoeff(a,k,i)));
        !          1079:       if (k>li) return NULL;
        !          1080:     }
        !          1081:
        !          1082:     /* if (k!=i), exchange the lines s.t. k = i */
        !          1083:     if (k != i)
        !          1084:     {
        !          1085:       for (j=i; j<=aco; j++) swap(coeff(a,i,j), coeff(a,k,j));
        !          1086:       if (iscol) { swap(b[i],b[k]); }
        !          1087:       else
        !          1088:         for (j=1; j<=bco; j++) swap(coeff(b,i,j), coeff(b,k,j));
        !          1089:       p = gcoeff(a,i,i);
        !          1090:     }
        !          1091:     if (i == aco) break;
        !          1092:
        !          1093:     for (k=i+1; k<=li; k++)
        !          1094:     {
        !          1095:       m=gcoeff(a,k,i);
        !          1096:       if (!gcmp0(m))
        !          1097:       {
        !          1098:        m = gneg_i(gdiv(m,p));
        !          1099:        for (j=i+1; j<=aco; j++) _addmul((GEN)a[j],k,i,m);
        !          1100:        if (iscol) _addmul(b,k,i,m);
        !          1101:         else
        !          1102:           for (j=1; j<=bco; j++) _addmul((GEN)b[j],k,i,m);
        !          1103:       }
        !          1104:     }
        !          1105:     if (low_stack(lim, stack_lim(av,1)))
        !          1106:     {
        !          1107:       GEN *gptr[2]; gptr[0]=&a; gptr[1]=&b;
        !          1108:       if(DEBUGMEM>1) err(warnmem,"gauss. i=%ld",i);
        !          1109:       gerepilemany(av,gptr,2);
        !          1110:     }
        !          1111:   }
        !          1112:
        !          1113:   if(DEBUGLEVEL>4) fprintferr("Solving the triangular system\n");
        !          1114:   if (iscol) u = gauss_get_col(a,b,p,aco);
        !          1115:   else
        !          1116:   {
        !          1117:     long av1 = avma;
        !          1118:     lim = stack_lim(av1,1); u=cgetg(bco+1,t_MAT);
        !          1119:     for (j=2; j<=bco; j++) u[j] = zero; /* dummy */
        !          1120:     for (j=1; j<=bco; j++)
        !          1121:     {
        !          1122:       u[j] = (long)gauss_get_col(a,(GEN)b[j],p,aco);
        !          1123:       if (low_stack(lim, stack_lim(av1,1)))
        !          1124:       {
        !          1125:         if(DEBUGMEM>1) err(warnmem,"gauss[2]. j=%ld", j);
        !          1126:         u = gerepilecopy(av1, u);
        !          1127:       }
        !          1128:     }
        !          1129:   }
        !          1130:   return gerepilecopy(av, u);
        !          1131: }
        !          1132:
        !          1133: GEN
        !          1134: gauss(GEN a, GEN b)
        !          1135: {
        !          1136:   GEN z = gauss_intern(a,b);
        !          1137:   if (!z) err(matinv1);
        !          1138:   return z;
        !          1139: }
        !          1140:
        !          1141: GEN
        !          1142: u_FpM_gauss(GEN a, GEN b, long p)
        !          1143: {
        !          1144:   long piv,m,iscol,i,j,k,li,bco, aco = lg(a)-1;
        !          1145:   GEN u;
        !          1146:
        !          1147:   if (!aco) return cgetg(1,t_MAT);
        !          1148:   li = lg(a[1])-1;
        !          1149:   bco = lg(b)-1;
        !          1150:   iscol = (typ(b)==t_COL);
        !          1151:   piv = 0; /* gcc -Wall */
        !          1152:   for (i=1; i<=aco; i++)
        !          1153:   {
        !          1154:     /* k is the line where we find the pivot */
        !          1155:     coeff(a,i,i) = coeff(a,i,i) % p;
        !          1156:     piv = coeff(a,i,i); k = i;
        !          1157:     if (!piv)
        !          1158:     {
        !          1159:       for (k++; k <= li; k++)
        !          1160:       {
        !          1161:         coeff(a,k,i) %= p;
        !          1162:         if (coeff(a,k,i)) break;
        !          1163:       }
        !          1164:       if (k>li) return NULL;
        !          1165:     }
        !          1166:
        !          1167:     /* if (k!=i), exchange the lines s.t. k = i */
        !          1168:     if (k != i)
        !          1169:     {
        !          1170:       for (j=i; j<=aco; j++) swap(coeff(a,i,j), coeff(a,k,j));
        !          1171:       if (iscol) { swap(b[i],b[k]); }
        !          1172:       else
        !          1173:         for (j=1; j<=bco; j++) swap(coeff(b,i,j), coeff(b,k,j));
        !          1174:       piv = coeff(a,i,i);
        !          1175:     }
        !          1176:     if (i == aco) break;
        !          1177:
        !          1178:     for (k=i+1; k<=li; k++)
        !          1179:     {
        !          1180:       coeff(a,k,i) %= p;
        !          1181:       m = coeff(a,k,i); coeff(a,k,i) = 0;
        !          1182:       if (m)
        !          1183:       {
        !          1184:        m = - (m * u_Fp_inv(piv,p)) % p;
        !          1185:        for (j=i+1; j<=aco; j++) _u_Fp_addmul((GEN)a[j],k,i,m, p);
        !          1186:        if (iscol) _u_Fp_addmul(b,k,i,m, p);
        !          1187:         else
        !          1188:           for (j=1; j<=bco; j++) _u_Fp_addmul((GEN)b[j],k,i,m, p);
        !          1189:       }
        !          1190:     }
        !          1191:   }
        !          1192:   if (iscol) u = u_Fp_gauss_get_col(a,b,piv,aco,p);
        !          1193:   else
        !          1194:   {
        !          1195:     u=cgetg(bco+1,t_MAT);
        !          1196:     for (j=1; j<=bco; j++)
        !          1197:       u[j] = (long)u_Fp_gauss_get_col(a,(GEN)b[j],piv,aco,p);
        !          1198:   }
        !          1199:   return u;
        !          1200: }
        !          1201:
        !          1202: GEN
        !          1203: FpM_gauss(GEN a, GEN b, GEN p)
        !          1204: {
        !          1205:   long iscol,i,j,k,av,lim,li,bco, aco = lg(a)-1;
        !          1206:   GEN piv,m,u;
        !          1207:
        !          1208:   if (typ(a)!=t_MAT) err(mattype1,"gauss");
        !          1209:   if (b && typ(b)!=t_COL && typ(b)!=t_MAT) err(typeer,"gauss");
        !          1210:   if (!aco)
        !          1211:   {
        !          1212:     if (b && lg(b)!=1) err(consister,"gauss");
        !          1213:     if (DEBUGLEVEL) err(warner,"in Gauss lg(a)=1 lg(b)=%ld", b?1:-1);
        !          1214:     return cgetg(1,t_MAT);
        !          1215:   }
        !          1216:   li = lg(a[1])-1;
        !          1217:   if (li != aco && (li < aco || b)) err(mattype1,"gauss");
        !          1218:   b = check_b(b,li); av = avma;
        !          1219:   if (OK_ULONG(p))
        !          1220:   {
        !          1221:     ulong pp=p[2];
        !          1222:     a = u_Fp_FpM(a, pp);
        !          1223:     b = u_Fp_FpM(b, pp);
        !          1224:     u = u_FpM_gauss(a,b, pp);
        !          1225:     return gerepileupto(av, small_to_mat(u));
        !          1226:   }
        !          1227:   lim = stack_lim(av,1);
        !          1228:   a = dummycopy(a);
        !          1229:   bco = lg(b)-1;
        !          1230:   iscol = (typ(b)==t_COL);
        !          1231:   piv = NULL; /* gcc -Wall */
        !          1232:   for (i=1; i<=aco; i++)
        !          1233:   {
        !          1234:     /* k is the line where we find the pivot */
        !          1235:     coeff(a,i,i) = lresii(gcoeff(a,i,i), p);
        !          1236:     piv = gcoeff(a,i,i); k = i;
        !          1237:     if (!signe(piv))
        !          1238:     {
        !          1239:       for (k++; k <= li; k++)
        !          1240:       {
        !          1241:         coeff(a,k,i) = lresii(gcoeff(a,k,i), p);
        !          1242:         if (signe(coeff(a,k,i))) break;
        !          1243:       }
        !          1244:       if (k>li) return NULL;
        !          1245:     }
        !          1246:
        !          1247:     /* if (k!=i), exchange the lines s.t. k = i */
        !          1248:     if (k != i)
        !          1249:     {
        !          1250:       for (j=i; j<=aco; j++) swap(coeff(a,i,j), coeff(a,k,j));
        !          1251:       if (iscol) { swap(b[i],b[k]); }
        !          1252:       else
        !          1253:         for (j=1; j<=bco; j++) swap(coeff(b,i,j), coeff(b,k,j));
        !          1254:       piv = gcoeff(a,i,i);
        !          1255:     }
        !          1256:     if (i == aco) break;
        !          1257:
        !          1258:     for (k=i+1; k<=li; k++)
        !          1259:     {
        !          1260:       coeff(a,k,i) = lresii(gcoeff(a,k,i), p);
        !          1261:       m = gcoeff(a,k,i); coeff(a,k,i) = zero;
        !          1262:       if (signe(m))
        !          1263:       {
        !          1264:        m = mulii(m, mpinvmod(piv,p));
        !          1265:         m = resii(negi(m), p);
        !          1266:        for (j=i+1; j<=aco; j++) _Fp_addmul((GEN)a[j],k,i,m, p);
        !          1267:        if (iscol) _Fp_addmul(b,k,i,m, p);
        !          1268:         else
        !          1269:           for (j=1; j<=bco; j++) _Fp_addmul((GEN)b[j],k,i,m, p);
        !          1270:       }
        !          1271:     }
        !          1272:     if (low_stack(lim, stack_lim(av,1)))
        !          1273:     {
        !          1274:       GEN *gptr[2]; gptr[0]=&a; gptr[1]=&b;
        !          1275:       if(DEBUGMEM>1) err(warnmem,"FpM_gauss. i=%ld",i);
        !          1276:       gerepilemany(av,gptr,2);
        !          1277:     }
        !          1278:   }
        !          1279:
        !          1280:   if(DEBUGLEVEL>4) fprintferr("Solving the triangular system\n");
        !          1281:   if (iscol) u = Fp_gauss_get_col(a,b,piv,aco,p);
        !          1282:   else
        !          1283:   {
        !          1284:     long av1 = avma;
        !          1285:     lim = stack_lim(av1,1); u=cgetg(bco+1,t_MAT);
        !          1286:     for (j=2; j<=bco; j++) u[j] = zero; /* dummy */
        !          1287:     for (j=1; j<=bco; j++)
        !          1288:     {
        !          1289:       u[j] = (long)Fp_gauss_get_col(a,(GEN)b[j],piv,aco,p);
        !          1290:       if (low_stack(lim, stack_lim(av1,1)))
        !          1291:       {
        !          1292:         if(DEBUGMEM>1) err(warnmem,"gauss[2]. j=%ld", j);
        !          1293:         u = gerepilecopy(av1, u);
        !          1294:       }
        !          1295:     }
        !          1296:   }
        !          1297:   return gerepilecopy(av, u);
        !          1298: }
        !          1299:
        !          1300: GEN
        !          1301: FpM_inv(GEN x, GEN p) { return FpM_gauss(x, NULL, p); }
        !          1302:
        !          1303: static GEN
        !          1304: u_idmat(long n)
        !          1305: {
        !          1306:   GEN y = cgetg(n+1,t_MAT);
        !          1307:   long i,j;
        !          1308:   if (n < 0) err(talker,"negative size in u_idmat");
        !          1309:   for (i=1; i<=n; i++)
        !          1310:   {
        !          1311:     y[i]=lgetg(n+1,t_VECSMALL);
        !          1312:     for (j=1; j<=n; j++) coeff(y,j,i) = (i==j)? 1: 0;
        !          1313:   }
        !          1314:   return y;
        !          1315: }
        !          1316:
        !          1317: /* set y = x * y */
        !          1318: #define HIGHWORD(a) ((a) >> BITS_IN_HALFULONG)
        !          1319: static GEN
        !          1320: u_FpM_Fp_mul_ip(GEN y, long x, long p)
        !          1321: {
        !          1322:   int i,j, m = lg(y[1]), l = lg(y);
        !          1323:   if (HIGHWORD(x | p))
        !          1324:     for(j=1; j<l; j++)
        !          1325:       for(i=1; i<m; i++)
        !          1326:         coeff(y,i,j) = (long)mulssmod(coeff(y,i,j), x, p);
        !          1327:   else
        !          1328:     for(j=1; j<l; j++)
        !          1329:       for(i=1; i<m; i++)
        !          1330:         coeff(y,i,j) = (coeff(y,i,j) * x) % p;
        !          1331:   return y;
        !          1332: }
        !          1333:
        !          1334: /* M integral, dM such that M' = dM M^-1 is integral [e.g det(M)]. Return M' */
        !          1335: GEN
        !          1336: ZM_inv(GEN M, GEN dM)
        !          1337: {
        !          1338:   GEN  ID,Hp,q,H;
        !          1339:   ulong p,dMp, av2, av = avma, lim = stack_lim(av,1);
        !          1340:   byteptr d = diffptr;
        !          1341:   long lM = lg(M), stable = 0;
        !          1342:
        !          1343:   if (lM == 1) return cgetg(1,t_MAT);
        !          1344:   if (!dM) dM = det(M);
        !          1345:
        !          1346:   av2 = avma;
        !          1347:   H = NULL;
        !          1348:   d += 3000; /* 27449 = prime(3000) */
        !          1349:   for(p = 27449; ; p+= *d++)
        !          1350:   {
        !          1351:     if (!*d) err(primer1);
        !          1352:     dMp = umodiu(dM,p);
        !          1353:     if (!dMp) continue;
        !          1354:     ID = u_idmat(lM-1);
        !          1355:     Hp = u_FpM_gauss(u_Fp_FpM(M,p), ID, p);
        !          1356:     if (dMp != 1) Hp = u_FpM_Fp_mul_ip(Hp, dMp, p);
        !          1357:
        !          1358:     if (!H)
        !          1359:     {
        !          1360:       H = ZM_init_CRT(Hp, p);
        !          1361:       q = utoi(p);
        !          1362:     }
        !          1363:     else
        !          1364:     {
        !          1365:       GEN qp = muliu(q,p);
        !          1366:       stable = ZM_incremental_CRT(H, Hp, q,qp, p);
        !          1367:       q = qp;
        !          1368:     }
        !          1369:     if (DEBUGLEVEL>5) msgtimer("inverse mod %ld (stable=%ld)", p,stable);
        !          1370:     if (stable && isscalarmat(gmul(M, H), dM)) break; /* DONE */
        !          1371:
        !          1372:     if (low_stack(lim, stack_lim(av,2)))
        !          1373:     {
        !          1374:       GEN *gptr[2]; gptr[0] = &H; gptr[1] = &q;
        !          1375:       if (DEBUGMEM>1) err(warnmem,"ZM_inv");
        !          1376:       gerepilemany(av2,gptr, 2);
        !          1377:     }
        !          1378:
        !          1379:   }
        !          1380:   if (DEBUGLEVEL>5) msgtimer("ZM_inv done");
        !          1381:   return gerepilecopy(av, H);
        !          1382: }
        !          1383:
        !          1384: /* same as above, M rational */
        !          1385: GEN
        !          1386: QM_inv(GEN M, GEN dM)
        !          1387: {
        !          1388:   ulong av = avma;
        !          1389:   GEN cM = content(M);
        !          1390:   if (is_pm1(cM)) { avma = av; return ZM_inv(M,dM); }
        !          1391:   return gerepileupto(av, ZM_inv(gdiv(M,cM), gdiv(dM,cM)));
        !          1392: }
        !          1393:
        !          1394: /* x a matrix with integer coefficients. Return a multiple of the determinant
        !          1395:  * of the lattice generated by the columns of x (to be used with hnfmod)
        !          1396:  */
        !          1397: GEN
        !          1398: detint(GEN x)
        !          1399: {
        !          1400:   GEN pass,c,v,det1,piv,pivprec,vi,p1;
        !          1401:   long i,j,k,rg,n,m,m1,av=avma,av1,lim;
        !          1402:
        !          1403:   if (typ(x)!=t_MAT) err(typeer,"detint");
        !          1404:   n=lg(x)-1; if (!n) return gun;
        !          1405:   m1=lg(x[1]); m=m1-1; lim=stack_lim(av,1);
        !          1406:   c=new_chunk(m1); for (k=1; k<=m; k++) c[k]=0;
        !          1407:   av1=avma; pass=cgetg(m1,t_MAT);
        !          1408:   for (j=1; j<=m; j++)
        !          1409:   {
        !          1410:     p1=cgetg(m1,t_COL); pass[j]=(long)p1;
        !          1411:     for (i=1; i<=m; i++) p1[i]=zero;
        !          1412:   }
        !          1413:   for (k=1; k<=n; k++)
        !          1414:     for (j=1; j<=m; j++)
        !          1415:       if (typ(gcoeff(x,j,k)) != t_INT)
        !          1416:         err(talker,"not an integer matrix in detint");
        !          1417:   v=cgetg(m1,t_COL);
        !          1418:   det1=gzero; piv=pivprec=gun;
        !          1419:   for (rg=0,k=1; k<=n; k++)
        !          1420:   {
        !          1421:     long t = 0;
        !          1422:     for (i=1; i<=m; i++)
        !          1423:       if (!c[i])
        !          1424:       {
        !          1425:        vi=mulii(piv,gcoeff(x,i,k));
        !          1426:        for (j=1; j<=m; j++)
        !          1427:          if (c[j]) vi=addii(vi,mulii(gcoeff(pass,i,j),gcoeff(x,j,k)));
        !          1428:        v[i]=(long)vi; if (!t && signe(vi)) t=i;
        !          1429:       }
        !          1430:     if (t)
        !          1431:     {
        !          1432:       if (rg == m-1)
        !          1433:         { det1=mppgcd((GEN)v[t],det1); c[t]=0; }
        !          1434:       else
        !          1435:       {
        !          1436:         rg++; pivprec = piv; piv=(GEN)v[t]; c[t]=k;
        !          1437:        for (i=1; i<=m; i++)
        !          1438:          if (!c[i])
        !          1439:          {
        !          1440:             GEN p2 = negi((GEN)v[i]);
        !          1441:            for (j=1; j<=m; j++)
        !          1442:              if (c[j] && j!=t)
        !          1443:              {
        !          1444:                p1 = addii(mulii(gcoeff(pass,i,j), piv),
        !          1445:                           mulii(gcoeff(pass,t,j), p2));
        !          1446:                 if (rg>1) p1 = divii(p1,pivprec);
        !          1447:                coeff(pass,i,j) = (long)p1;
        !          1448:              }
        !          1449:            coeff(pass,i,t) = (long)p2;
        !          1450:          }
        !          1451:       }
        !          1452:     }
        !          1453:     if (low_stack(lim, stack_lim(av,1)))
        !          1454:     {
        !          1455:       GEN *gptr[5];
        !          1456:       if(DEBUGMEM>1) err(warnmem,"detint. k=%ld",k);
        !          1457:       gptr[0]=&det1; gptr[1]=&piv; gptr[2]=&pivprec;
        !          1458:       gptr[3]=&pass; gptr[4]=&v; gerepilemany(av1,gptr,5);
        !          1459:     }
        !          1460:   }
        !          1461:   return gerepileupto(av, absi(det1));
        !          1462: }
        !          1463:
        !          1464: static void
        !          1465: gerepile_gauss_ker(GEN x, long m, long n, long k, long t, ulong av)
        !          1466: {
        !          1467:   ulong tetpil = avma,A;
        !          1468:   long dec,u,i;
        !          1469:
        !          1470:   if (DEBUGMEM > 1) err(warnmem,"gauss_pivot_ker. k=%ld, n=%ld",k,n);
        !          1471:   for (u=t+1; u<=m; u++) copyifstack(coeff(x,u,k), coeff(x,u,k));
        !          1472:   for (i=k+1; i<=n; i++)
        !          1473:     for (u=1; u<=m; u++) copyifstack(coeff(x,u,i), coeff(x,u,i));
        !          1474:
        !          1475:   (void)gerepile(av,tetpil,NULL); dec = av-tetpil;
        !          1476:   for (u=t+1; u<=m; u++)
        !          1477:   {
        !          1478:     A=coeff(x,u,k);
        !          1479:     if (A<av && A>=bot) coeff(x,u,k)+=dec;
        !          1480:   }
        !          1481:   for (i=k+1; i<=n; i++)
        !          1482:     for (u=1; u<=m; u++)
        !          1483:     {
        !          1484:       A=coeff(x,u,i);
        !          1485:       if (A<av && A>=bot) coeff(x,u,i)+=dec;
        !          1486:     }
        !          1487: }
        !          1488:
        !          1489: static void
        !          1490: gerepile_gauss_FpM_ker(GEN x, GEN p, long m, long n, long k, long t, ulong av)
        !          1491: {
        !          1492:   ulong tetpil = avma,A;
        !          1493:   long dec,u,i;
        !          1494:
        !          1495:   if (DEBUGMEM > 1) err(warnmem,"gauss_pivot_ker. k=%ld, n=%ld",k,n);
        !          1496:   for (u=t+1; u<=m; u++)
        !          1497:     if (isonstack(coeff(x,u,k))) coeff(x,u,k) = lmodii(gcoeff(x,u,k),p);
        !          1498:   for (i=k+1; i<=n; i++)
        !          1499:     for (u=1; u<=m; u++)
        !          1500:       if (isonstack(coeff(x,u,i))) coeff(x,u,i) = lmodii(gcoeff(x,u,i),p);
        !          1501:
        !          1502:   (void)gerepile(av,tetpil,NULL); dec = av-tetpil;
        !          1503:   for (u=t+1; u<=m; u++)
        !          1504:   {
        !          1505:     A=coeff(x,u,k);
        !          1506:     if (A<av && A>=bot) coeff(x,u,k)+=dec;
        !          1507:   }
        !          1508:   for (i=k+1; i<=n; i++)
        !          1509:     for (u=1; u<=m; u++)
        !          1510:     {
        !          1511:       A=coeff(x,u,i);
        !          1512:       if (A<av && A>=bot) coeff(x,u,i)+=dec;
        !          1513:     }
        !          1514: }
        !          1515:
        !          1516: /* special gerepile for huge matrices */
        !          1517:
        !          1518: static void
        !          1519: gerepile_gauss(GEN x,long m,long n,long k,long t,ulong av, long j, GEN c)
        !          1520: {
        !          1521:   ulong tetpil = avma,A;
        !          1522:   long dec,u,i;
        !          1523:
        !          1524:   if (DEBUGMEM > 1) err(warnmem,"gauss_pivot. k=%ld, n=%ld",k,n);
        !          1525:   for (u=t+1; u<=m; u++)
        !          1526:     if (u==j || !c[u]) copyifstack(coeff(x,u,k), coeff(x,u,k));
        !          1527:   for (u=1; u<=m; u++)
        !          1528:     if (u==j || !c[u])
        !          1529:       for (i=k+1; i<=n; i++) copyifstack(coeff(x,u,i), coeff(x,u,i));
        !          1530:
        !          1531:   (void)gerepile(av,tetpil,NULL); dec = av-tetpil;
        !          1532:   for (u=t+1; u<=m; u++)
        !          1533:     if (u==j || !c[u])
        !          1534:     {
        !          1535:       A=coeff(x,u,k);
        !          1536:       if (A<av && A>=bot) coeff(x,u,k)+=dec;
        !          1537:     }
        !          1538:   for (u=1; u<=m; u++)
        !          1539:     if (u==j || !c[u])
        !          1540:       for (i=k+1; i<=n; i++)
        !          1541:       {
        !          1542:         A=coeff(x,u,i);
        !          1543:         if (A<av && A>=bot) coeff(x,u,i)+=dec;
        !          1544:       }
        !          1545: }
        !          1546:
        !          1547: /*******************************************************************/
        !          1548: /*                                                                 */
        !          1549: /*                    KERNEL of an m x n matrix                    */
        !          1550: /*          return n - rk(x) linearly independant vectors          */
        !          1551: /*                                                                 */
        !          1552: /*******************************************************************/
        !          1553:
        !          1554: /* x has INTEGER coefficients */
        !          1555: GEN
        !          1556: keri(GEN x)
        !          1557: {
        !          1558:   GEN c,d,y,p,pp;
        !          1559:   long i,j,k,r,t,n,m,av,av0,tetpil,lim;
        !          1560:
        !          1561:   if (typ(x)!=t_MAT) err(typeer,"keri");
        !          1562:   n=lg(x)-1; if (!n) return cgetg(1,t_MAT);
        !          1563:
        !          1564:   av0=avma; m=lg(x[1])-1; r=0;
        !          1565:   pp=cgetg(n+1,t_COL);
        !          1566:   x=dummycopy(x); p=gun;
        !          1567:   c=new_chunk(m+1); for (k=1; k<=m; k++) c[k]=0;
        !          1568:   d=new_chunk(n+1); av=avma; lim=stack_lim(av,1);
        !          1569:   for (k=1; k<=n; k++)
        !          1570:   {
        !          1571:     j=1;
        !          1572:     while (j<=m && (c[j] || !signe(gcoeff(x,j,k))) ) j++;
        !          1573:     if (j>m)
        !          1574:     {
        !          1575:       r++; d[k]=0;
        !          1576:       for(j=1; j<k; j++)
        !          1577:        if (d[j]) coeff(x,d[j],k) = lclone(gcoeff(x,d[j],k));
        !          1578:       pp[k]=lclone(p);
        !          1579:     }
        !          1580:     else
        !          1581:     {
        !          1582:       GEN p0 = p;
        !          1583:       long av1;
        !          1584:
        !          1585:       c[j]=k; d[k]=j; p = gcoeff(x,j,k);
        !          1586:
        !          1587:       for (t=1; t<=m; t++)
        !          1588:        if (t!=j)
        !          1589:        {
        !          1590:          GEN q=gcoeff(x,t,k), p1,p2;
        !          1591:          for (i=k+1; i<=n; i++)
        !          1592:          {
        !          1593:            av1=avma; (void)new_chunk(lgefint(p0));
        !          1594:            p1=mulii(q,gcoeff(x,j,i));
        !          1595:            p2=mulii(p,gcoeff(x,t,i));
        !          1596:            p1=subii(p2,p1); avma=av1;
        !          1597:            coeff(x,t,i) = ldivii(p1,p0);
        !          1598:          }
        !          1599:          if (low_stack(lim, stack_lim(av,1)))
        !          1600:           {
        !          1601:             p1 = gclone(p);
        !          1602:             gerepile_gauss_ker(x,m,n,k,t,av);
        !          1603:             p = gcopy(p1); gunclone(p1);
        !          1604:           }
        !          1605:        }
        !          1606:     }
        !          1607:   }
        !          1608:   if (!r) { avma=av0; y=cgetg(1,t_MAT); return y; }
        !          1609:
        !          1610:   /* non trivial kernel */
        !          1611:   tetpil=avma; y=cgetg(r+1,t_MAT);
        !          1612:   for (j=k=1; j<=r; j++,k++)
        !          1613:   {
        !          1614:     p = cgetg(n+1, t_COL);
        !          1615:     y[j]=(long)p; while (d[k]) k++;
        !          1616:     for (i=1; i<k; i++)
        !          1617:       if (d[i])
        !          1618:       {
        !          1619:        c=gcoeff(x,d[i],k);
        !          1620:        p[i] = (long) forcecopy(c); gunclone(c);
        !          1621:       }
        !          1622:       else
        !          1623:        p[i] = zero;
        !          1624:     p[k]=lnegi((GEN)pp[k]); gunclone((GEN)pp[k]);
        !          1625:     for (i=k+1; i<=n; i++) p[i]=zero;
        !          1626:   }
        !          1627:   return gerepile(av0,tetpil,y);
        !          1628: }
        !          1629:
        !          1630: GEN
        !          1631: deplin(GEN x)
        !          1632: {
        !          1633:   long i,j,k,t,nc,nl, av=avma;
        !          1634:   GEN y,q,c,l,d;
        !          1635:
        !          1636:   if (typ(x) != t_MAT) err(typeer,"deplin");
        !          1637:   nc=lg(x)-1; if (!nc) err(talker,"empty matrix in deplin");
        !          1638:   nl=lg(x[1])-1;
        !          1639:   c=new_chunk(nl+1);
        !          1640:   l=new_chunk(nc+1);
        !          1641:   d=cgetg(nl+1,t_VEC);
        !          1642:   for (i=1; i<=nl; i++) { d[i]=un; c[i]=0; }
        !          1643:   k=1; t=1;
        !          1644:   while (t<=nl && k<=nc)
        !          1645:   {
        !          1646:     for (j=1; j<k; j++)
        !          1647:      for (i=1; i<=nl; i++)
        !          1648:       if (i!=l[j])
        !          1649:        coeff(x,i,k)=lsub(gmul((GEN) d[j],gcoeff(x,i,k)),
        !          1650:                          gmul(gcoeff(x,i,j),gcoeff(x,l[j],k)));
        !          1651:     t=1;
        !          1652:     while ( t<=nl && (c[t] || gcmp0(gcoeff(x,t,k))) ) t++;
        !          1653:     if (t<=nl)
        !          1654:     {
        !          1655:       d[k]=coeff(x,t,k);
        !          1656:       c[t]=k; l[k++]=t;
        !          1657:     }
        !          1658:   }
        !          1659:   if (k>nc)
        !          1660:   {
        !          1661:     avma=av; y=cgetg(nc+1,t_COL);
        !          1662:     for (j=1; j<=nc; j++) y[j]=zero;
        !          1663:     return y;
        !          1664:   }
        !          1665:   y=cgetg(nc+1,t_COL);
        !          1666:   y[1]=(k>1)? coeff(x,l[1],k): un;
        !          1667:   for (q=gun,j=2; j<k; j++)
        !          1668:   {
        !          1669:     q=gmul(q,(GEN) d[j-1]);
        !          1670:     y[j]=lmul(gcoeff(x,l[j],k),q);
        !          1671:   }
        !          1672:   if (k>1) y[k]=lneg(gmul(q,(GEN) d[k-1]));
        !          1673:   for (j=k+1; j<=nc; j++) y[j]=zero;
        !          1674:   d=content(y); t=avma;
        !          1675:   return gerepile(av,t,gdiv(y,d));
        !          1676: }
        !          1677:
        !          1678: /*******************************************************************/
        !          1679: /*                                                                 */
        !          1680: /*         GAUSS REDUCTION OF MATRICES  (m lines x n cols)         */
        !          1681: /*           (kernel, image, complementary image, rank)            */
        !          1682: /*                                                                 */
        !          1683: /*******************************************************************/
        !          1684: static long gauss_ex;
        !          1685: static int (*gauss_is_zero)(GEN);
        !          1686:
        !          1687: static int
        !          1688: real0(GEN x)
        !          1689: {
        !          1690:   return gcmp0(x) || (gexpo(x) < gauss_ex);
        !          1691: }
        !          1692:
        !          1693: static void
        !          1694: gauss_get_prec(GEN x, long prec)
        !          1695: {
        !          1696:   long pr = matprec(x);
        !          1697:
        !          1698:   if (!pr) { gauss_is_zero = &gcmp0; return; }
        !          1699:   if (pr > prec) prec = pr;
        !          1700:
        !          1701:   gauss_ex = - (long)(0.85 * bit_accuracy(prec));
        !          1702:   gauss_is_zero = &real0;
        !          1703: }
        !          1704:
        !          1705: static long
        !          1706: gauss_get_pivot_NZ(GEN x, GEN x0/* unused */, GEN c, long i0)
        !          1707: {
        !          1708:   long i,lx = lg(x);
        !          1709:   if (c)
        !          1710:     for (i=i0; i<lx; i++)
        !          1711:     {
        !          1712:       if (c[i]) continue;
        !          1713:       if (!gcmp0((GEN)x[i])) break;
        !          1714:     }
        !          1715:   else
        !          1716:     for (i=i0; i<lx; i++)
        !          1717:       if (!gcmp0((GEN)x[i])) break;
        !          1718:   return i;
        !          1719:
        !          1720: }
        !          1721:
        !          1722: /* ~ 0 compared to reference y */
        !          1723: static int
        !          1724: approx_0(GEN x, GEN y)
        !          1725: {
        !          1726:   long tx = typ(x);
        !          1727:   if (tx == t_COMPLEX)
        !          1728:     return approx_0((GEN)x[1], y) && approx_0((GEN)x[2], y);
        !          1729:   return gcmp0(x) ||
        !          1730:          (tx == t_REAL && gexpo(y) - gexpo(x) > bit_accuracy(lg(x)));
        !          1731: }
        !          1732:
        !          1733: static long
        !          1734: gauss_get_pivot_max(GEN x, GEN x0, GEN c, long i0)
        !          1735: {
        !          1736:   long i,e, k = i0, ex = -HIGHEXPOBIT, lx = lg(x);
        !          1737:   GEN p,r;
        !          1738:   if (c)
        !          1739:     for (i=i0; i<lx; i++)
        !          1740:     {
        !          1741:       if (c[i]) continue;
        !          1742:       e = gexpo((GEN)x[i]);
        !          1743:       if (e > ex) { ex=e; k=i; }
        !          1744:     }
        !          1745:   else
        !          1746:     for (i=i0; i<lx; i++)
        !          1747:     {
        !          1748:       e = gexpo((GEN)x[i]);
        !          1749:       if (e > ex) { ex=e; k=i; }
        !          1750:     }
        !          1751:   p = (GEN)x[k];
        !          1752:   r = (GEN)x0[k]; if (isexactzero(r)) r = x0;
        !          1753:   return approx_0(p, r)? i: k;
        !          1754: }
        !          1755:
        !          1756: /* return the transform of x under a standard Gauss pivot. r = dim ker(x).
        !          1757:  * d[k] contains the index of the first non-zero pivot in column k
        !          1758:  * If a != NULL, use x - a Id instead (for eigen)
        !          1759:  */
        !          1760: static GEN
        !          1761: gauss_pivot_ker(GEN x0, GEN a, GEN *dd, long *rr)
        !          1762: {
        !          1763:   GEN x,c,d,p,mun;
        !          1764:   long i,j,k,r,t,n,m,av,lim;
        !          1765:   long (*get_pivot)(GEN,GEN,GEN,long);
        !          1766:
        !          1767:   if (typ(x0)!=t_MAT) err(typeer,"gauss_pivot");
        !          1768:   n=lg(x0)-1; if (!n) { *dd=NULL; *rr=0; return cgetg(1,t_MAT); }
        !          1769:   m=lg(x0[1])-1; r=0;
        !          1770:
        !          1771:   x = dummycopy(x0); mun = negi(gun);
        !          1772:   if (a)
        !          1773:   {
        !          1774:     if (n != m) err(consister,"gauss_pivot_ker");
        !          1775:     for (k=1; k<=n; k++) coeff(x,k,k) = lsub(gcoeff(x,k,k), a);
        !          1776:   }
        !          1777:   get_pivot = use_maximal_pivot(x)? gauss_get_pivot_max: gauss_get_pivot_NZ;
        !          1778:   c=cgetg(m+1,t_VECSMALL); for (k=1; k<=m; k++) c[k]=0;
        !          1779:   d=cgetg(n+1,t_VECSMALL);
        !          1780:   av=avma; lim=stack_lim(av,1);
        !          1781:   for (k=1; k<=n; k++)
        !          1782:   {
        !          1783:     j = get_pivot((GEN)x[k], (GEN)x0[k], c, 1);
        !          1784:     if (j > m)
        !          1785:     {
        !          1786:       r++; d[k]=0;
        !          1787:       for(j=1; j<k; j++)
        !          1788:         if (d[j]) coeff(x,d[j],k) = lclone(gcoeff(x,d[j],k));
        !          1789:     }
        !          1790:     else
        !          1791:     { /* pivot for column k on row j */
        !          1792:       c[j]=k; d[k]=j; p = gdiv(mun,gcoeff(x,j,k));
        !          1793:       coeff(x,j,k) = (long)mun;
        !          1794:       /* x[j,] /= - x[j,k] */
        !          1795:       for (i=k+1; i<=n; i++)
        !          1796:        coeff(x,j,i) = lmul(p,gcoeff(x,j,i));
        !          1797:       for (t=1; t<=m; t++)
        !          1798:        if (t!=j)
        !          1799:        { /* x[t,] -= 1 / x[j,k] x[j,] */
        !          1800:          p=gcoeff(x,t,k); coeff(x,t,k)=zero;
        !          1801:          for (i=k+1; i<=n; i++)
        !          1802:            coeff(x,t,i) = ladd(gcoeff(x,t,i),gmul(p,gcoeff(x,j,i)));
        !          1803:           if (low_stack(lim, stack_lim(av,1)))
        !          1804:             gerepile_gauss_ker(x,m,n,k,t,av);
        !          1805:        }
        !          1806:     }
        !          1807:   }
        !          1808:   *dd=d; *rr=r; return x;
        !          1809: }
        !          1810:
        !          1811: /* r = dim ker(x).
        !          1812:  * d[k] contains the index of the first non-zero pivot in column k
        !          1813:  */
        !          1814: static void
        !          1815: gauss_pivot(GEN x0, GEN *dd, long *rr)
        !          1816: {
        !          1817:   GEN x,c,d,d0,mun,p;
        !          1818:   long i,j,k,r,t,n,m,av,lim;
        !          1819:   long (*get_pivot)(GEN,GEN,GEN,long);
        !          1820:
        !          1821:   if (typ(x0)!=t_MAT) err(typeer,"gauss_pivot");
        !          1822:   n=lg(x0)-1; if (!n) { *dd=NULL; *rr=0; return; }
        !          1823:
        !          1824:   d0 = cgetg(n+1, t_VECSMALL);
        !          1825:   if (use_maximal_pivot(x0))
        !          1826:   { /* put exact columns first, then largest inexact ones */
        !          1827:     get_pivot = gauss_get_pivot_max;
        !          1828:     for (k=1; k<=n; k++)
        !          1829:       d0[k] = isinexactreal((GEN)x0[k])? -gexpo((GEN)x0[k]): -VERYBIGINT;
        !          1830:     d0 = gen_sort(d0, cmp_C|cmp_IND, NULL);
        !          1831:     x0 = vecextract_p(x0, d0);
        !          1832:   }
        !          1833:   else
        !          1834:   {
        !          1835:     get_pivot = gauss_get_pivot_NZ;
        !          1836:     for (k=1; k<=n; k++) d0[k] = k;
        !          1837:   }
        !          1838:   x = dummycopy(x0); mun = negi(gun);
        !          1839:   m=lg(x[1])-1; r=0;
        !          1840:   c=cgetg(m+1, t_VECSMALL); for (k=1; k<=m; k++) c[k]=0;
        !          1841:   d=(GEN)gpmalloc((n+1)*sizeof(long)); av=avma; lim=stack_lim(av,1);
        !          1842:   for (k=1; k<=n; k++)
        !          1843:   {
        !          1844:     j = get_pivot((GEN)x[k], (GEN)x0[k], c, 1);
        !          1845:     if (j>m) { r++; d[d0[k]]=0; }
        !          1846:     else
        !          1847:     {
        !          1848:       c[j]=k; d[d0[k]]=j; p = gdiv(mun,gcoeff(x,j,k));
        !          1849:       for (i=k+1; i<=n; i++)
        !          1850:        coeff(x,j,i) = lmul(p,gcoeff(x,j,i));
        !          1851:
        !          1852:       for (t=1; t<=m; t++)
        !          1853:         if (!c[t]) /* no pivot on that line yet */
        !          1854:         {
        !          1855:           p=gcoeff(x,t,k); coeff(x,t,k)=zero;
        !          1856:           for (i=k+1; i<=n; i++)
        !          1857:             coeff(x,t,i) = ladd(gcoeff(x,t,i), gmul(p,gcoeff(x,j,i)));
        !          1858:           if (low_stack(lim, stack_lim(av,1)))
        !          1859:             gerepile_gauss(x,m,n,k,t,av,j,c);
        !          1860:         }
        !          1861:       for (i=k; i<=n; i++) coeff(x,j,i) = zero; /* dummy */
        !          1862:     }
        !          1863:   }
        !          1864:   *dd=d; *rr=r;
        !          1865: }
        !          1866:
        !          1867: /* compute ker(x - aI) */
        !          1868: static GEN
        !          1869: ker0(GEN x, GEN a)
        !          1870: {
        !          1871:   GEN d,y;
        !          1872:   long i,j,k,r,n, av = avma, tetpil;
        !          1873:
        !          1874:   x = gauss_pivot_ker(x,a,&d,&r);
        !          1875:   if (!r) { avma=av; return cgetg(1,t_MAT); }
        !          1876:   n = lg(x)-1; tetpil=avma; y=cgetg(r+1,t_MAT);
        !          1877:   for (j=k=1; j<=r; j++,k++)
        !          1878:   {
        !          1879:     GEN p = cgetg(n+1,t_COL);
        !          1880:
        !          1881:     y[j]=(long)p; while (d[k]) k++;
        !          1882:     for (i=1; i<k; i++)
        !          1883:       if (d[i])
        !          1884:       {
        !          1885:        GEN p1=gcoeff(x,d[i],k);
        !          1886:        p[i] = (long)forcecopy(p1); gunclone(p1);
        !          1887:       }
        !          1888:       else
        !          1889:        p[i] = zero;
        !          1890:     p[k]=un; for (i=k+1; i<=n; i++) p[i]=zero;
        !          1891:   }
        !          1892:   return gerepile(av,tetpil,y);
        !          1893: }
        !          1894:
        !          1895: GEN
        !          1896: ker(GEN x) /* Programme pour types exacts */
        !          1897: {
        !          1898:   return ker0(x,NULL);
        !          1899: }
        !          1900:
        !          1901: GEN
        !          1902: matker0(GEN x,long flag)
        !          1903: {
        !          1904:   return flag? keri(x): ker(x);
        !          1905: }
        !          1906:
        !          1907: GEN
        !          1908: image(GEN x)
        !          1909: {
        !          1910:   GEN d,y;
        !          1911:   long j,k,r, av = avma;
        !          1912:
        !          1913:   gauss_pivot(x,&d,&r);
        !          1914:
        !          1915:   /* r = dim ker(x) */
        !          1916:   if (!r) { avma=av; if (d) free(d); return gcopy(x); }
        !          1917:
        !          1918:   /* r = dim Im(x) */
        !          1919:   r = lg(x)-1 - r; avma=av;
        !          1920:   y=cgetg(r+1,t_MAT);
        !          1921:   for (j=k=1; j<=r; k++)
        !          1922:     if (d[k]) y[j++] = lcopy((GEN)x[k]);
        !          1923:   free(d); return y;
        !          1924: }
        !          1925:
        !          1926: GEN
        !          1927: imagecompl(GEN x)
        !          1928: {
        !          1929:   GEN d,y;
        !          1930:   long j,i,r,av = avma;
        !          1931:
        !          1932:   gauss_pivot(x,&d,&r);
        !          1933:   avma=av; y=cgetg(r+1,t_VEC);
        !          1934:   for (i=j=1; j<=r; i++)
        !          1935:     if (!d[i]) y[j++]=lstoi(i);
        !          1936:   if (d) free(d); return y;
        !          1937: }
        !          1938:
        !          1939: /* for hnfspec: imagecompl(trans(x)) + image(trans(x)) */
        !          1940: GEN
        !          1941: imagecomplspec(GEN x, long *nlze)
        !          1942: {
        !          1943:   GEN d,y;
        !          1944:   long i,j,k,l,r,av = avma;
        !          1945:
        !          1946:   x = gtrans(x); l = lg(x);
        !          1947:   gauss_pivot(x,&d,&r);
        !          1948:   avma=av; y = cgetg(l,t_VECSMALL);
        !          1949:   for (i=j=1, k=r+1; i<l; i++)
        !          1950:     if (d[i]) y[k++]=i; else y[j++]=i;
        !          1951:   *nlze = r;
        !          1952:   if (d) free(d); return y;
        !          1953: }
        !          1954:
        !          1955: static GEN
        !          1956: sinverseimage(GEN mat, GEN y)
        !          1957: {
        !          1958:   long av=avma,tetpil,i, nbcol = lg(mat);
        !          1959:   GEN col,p1 = cgetg(nbcol+1,t_MAT);
        !          1960:
        !          1961:   if (nbcol==1) return NULL;
        !          1962:   if (lg(y) != lg(mat[1])) err(consister,"inverseimage");
        !          1963:
        !          1964:   p1[nbcol] = (long)y;
        !          1965:   for (i=1; i<nbcol; i++) p1[i]=mat[i];
        !          1966:   p1 = ker(p1); i=lg(p1)-1;
        !          1967:   if (!i) return NULL;
        !          1968:
        !          1969:   col = (GEN)p1[i]; p1 = (GEN) col[nbcol];
        !          1970:   if (gcmp0(p1)) return NULL;
        !          1971:
        !          1972:   p1 = gneg_i(p1); setlg(col,nbcol); tetpil=avma;
        !          1973:   return gerepile(av,tetpil, gdiv(col, p1));
        !          1974: }
        !          1975:
        !          1976: /* Calcule l'image reciproque de v par m */
        !          1977: GEN
        !          1978: inverseimage(GEN m,GEN v)
        !          1979: {
        !          1980:   long av=avma,j,lv,tv=typ(v);
        !          1981:   GEN y,p1;
        !          1982:
        !          1983:   if (typ(m)!=t_MAT) err(typeer,"inverseimage");
        !          1984:   if (tv==t_COL)
        !          1985:   {
        !          1986:     p1 = sinverseimage(m,v);
        !          1987:     if (p1) return p1;
        !          1988:     avma = av; return cgetg(1,t_MAT);
        !          1989:   }
        !          1990:   if (tv!=t_MAT) err(typeer,"inverseimage");
        !          1991:
        !          1992:   lv=lg(v)-1; y=cgetg(lv+1,t_MAT);
        !          1993:   for (j=1; j<=lv; j++)
        !          1994:   {
        !          1995:     p1 = sinverseimage(m,(GEN)v[j]);
        !          1996:     if (!p1) { avma = av; return cgetg(1,t_MAT); }
        !          1997:     y[j] = (long)p1;
        !          1998:   }
        !          1999:   return y;
        !          2000: }
        !          2001:
        !          2002: /* x is an n x k matrix, rank(x) = k <= n. Return an invertible n x n matrix
        !          2003:  * whose first k columns are given by x. If rank(x)<k, the result may be wrong
        !          2004:  */
        !          2005: GEN
        !          2006: suppl_intern(GEN x, GEN myid)
        !          2007: {
        !          2008:   long av = avma, lx = lg(x), n,i,j;
        !          2009:   GEN y,p1;
        !          2010:   stackzone *zone;
        !          2011:
        !          2012:   if (typ(x) != t_MAT) err(typeer,"suppl");
        !          2013:   if (lx==1) err(talker,"empty matrix in suppl");
        !          2014:   n=lg(x[1]); if (lx>n) err(suppler2);
        !          2015:   if (lx == n) return gcopy(x);
        !          2016:
        !          2017:   zone  = switch_stack(NULL, n*n);
        !          2018:   switch_stack(zone,1);
        !          2019:   y = myid? dummycopy(myid): idmat(n-1);
        !          2020:   switch_stack(zone,0);
        !          2021:   gauss_get_prec(x,0);
        !          2022:   for (i=1; i<lx; i++)
        !          2023:   {
        !          2024:     p1 = gauss(y,(GEN)x[i]); j=i;
        !          2025:     while (j<n && gauss_is_zero((GEN)p1[j])) j++;
        !          2026:     if (j>=n) err(suppler2);
        !          2027:     p1=(GEN)y[i]; y[i]=x[i]; if (i!=j) y[j]=(long)p1;
        !          2028:   }
        !          2029:   avma = av; y = gcopy(y);
        !          2030:   free(zone); return y;
        !          2031: }
        !          2032:
        !          2033: GEN
        !          2034: suppl(GEN x)
        !          2035: {
        !          2036:   return suppl_intern(x,NULL);
        !          2037: }
        !          2038:
        !          2039: GEN
        !          2040: image2(GEN x)
        !          2041: {
        !          2042:   long av=avma,tetpil,k,n,i;
        !          2043:   GEN p1,p2;
        !          2044:
        !          2045:   if (typ(x)!=t_MAT) err(typeer,"image2");
        !          2046:   k=lg(x)-1; if (!k) return gcopy(x);
        !          2047:   n=lg(x[1])-1; p1=ker(x); k=lg(p1)-1;
        !          2048:   if (k) { p1=suppl(p1); n=lg(p1)-1; }
        !          2049:   else p1=idmat(n);
        !          2050:
        !          2051:   tetpil=avma; p2=cgetg(n-k+1,t_MAT);
        !          2052:   for (i=k+1; i<=n; i++) p2[i-k]=lmul(x,(GEN) p1[i]);
        !          2053:   return gerepile(av,tetpil,p2);
        !          2054: }
        !          2055:
        !          2056: GEN
        !          2057: matimage0(GEN x,long flag)
        !          2058: {
        !          2059:   switch(flag)
        !          2060:   {
        !          2061:     case 0: return image(x);
        !          2062:     case 1: return image2(x);
        !          2063:     default: err(flagerr,"matimage");
        !          2064:   }
        !          2065:   return NULL; /* not reached */
        !          2066: }
        !          2067:
        !          2068: long
        !          2069: rank(GEN x)
        !          2070: {
        !          2071:   long av = avma, r;
        !          2072:   GEN d;
        !          2073:
        !          2074:   gauss_pivot(x,&d,&r);
        !          2075:   /* yield r = dim ker(x) */
        !          2076:
        !          2077:   avma=av; if (d) free(d);
        !          2078:   return lg(x)-1 - r;
        !          2079: }
        !          2080:
        !          2081: static void FpM_gauss_pivot(GEN x, GEN p, GEN *dd, long *rr);
        !          2082:
        !          2083: /* if p != NULL, assume x integral and compute rank over Fp */
        !          2084: static GEN
        !          2085: indexrank0(GEN x, GEN p, int small)
        !          2086: {
        !          2087:   long av = avma, i,j,n,r;
        !          2088:   GEN res,d,p1,p2;
        !          2089:
        !          2090:   /* yield r = dim ker(x) */
        !          2091:   FpM_gauss_pivot(x,p,&d,&r);
        !          2092:
        !          2093:   /* now r = dim Im(x) */
        !          2094:   n = lg(x)-1; r = n - r;
        !          2095:
        !          2096:   avma=av; res=cgetg(3,t_VEC);
        !          2097:   p1=cgetg(r+1,small? t_VECSMALL: t_VEC); res[1]=(long)p1;
        !          2098:   p2=cgetg(r+1,small? t_VECSMALL: t_VEC); res[2]=(long)p2;
        !          2099:   if (d)
        !          2100:   {
        !          2101:     for (i=0,j=1; j<=n; j++)
        !          2102:       if (d[j]) { i++; p1[i]=d[j]; p2[i]=j; }
        !          2103:     free(d);
        !          2104:     qsort(p1+1,r,sizeof(long),(QSCOMP)pari_compare_long);
        !          2105:   }
        !          2106:   if (!small)
        !          2107:     for (i=1;i<=r;i++) { p1[i]=lstoi(p1[i]); p2[i]=lstoi(p2[i]); }
        !          2108:   return res;
        !          2109: }
        !          2110:
        !          2111: GEN
        !          2112: indexrank(GEN x) { return indexrank0(x,NULL,0); }
        !          2113:
        !          2114: GEN
        !          2115: sindexrank(GEN x) { return indexrank0(x,NULL,1); }
        !          2116:
        !          2117: GEN
        !          2118: FpM_sindexrank(GEN x, GEN p) { return indexrank0(x,p,1); }
        !          2119:
        !          2120: /*******************************************************************/
        !          2121: /*                                                                 */
        !          2122: /*                    LINEAR ALGEBRA MODULO P                      */
        !          2123: /*                                                                 */
        !          2124: /*******************************************************************/
        !          2125:
        !          2126: /*If p is NULL no reduction is performed.*/
        !          2127: GEN
        !          2128: FpM_mul(GEN x, GEN y, GEN p)
        !          2129: {
        !          2130:   long i,j,l,lx=lg(x), ly=lg(y);
        !          2131:   GEN z;
        !          2132:   if (ly==1) return cgetg(ly,t_MAT);
        !          2133:   if (lx != lg(y[1])) err(operi,"* [mod p]",t_MAT,t_MAT);
        !          2134:   z=cgetg(ly,t_MAT);
        !          2135:   if (lx==1)
        !          2136:   {
        !          2137:     for (i=1; i<ly; i++) z[i]=lgetg(1,t_COL);
        !          2138:     return z;
        !          2139:   }
        !          2140:   l=lg(x[1]);
        !          2141:   for (j=1; j<ly; j++)
        !          2142:   {
        !          2143:     z[j] = lgetg(l,t_COL);
        !          2144:     for (i=1; i<l; i++)
        !          2145:     {
        !          2146:       ulong av;
        !          2147:       GEN p1,p2;
        !          2148:       int k;
        !          2149:       p1=gzero; av=avma;
        !          2150:       for (k=1; k<lx; k++)
        !          2151:       {
        !          2152:        p2=mulii(gcoeff(x,i,k),gcoeff(y,k,j));
        !          2153:        p1=addii(p1,p2);
        !          2154:       }
        !          2155:       coeff(z,i,j)=lpileupto(av,p?modii(p1,p):p1);
        !          2156:     }
        !          2157:   }
        !          2158:   return z;
        !          2159: }
        !          2160:
        !          2161: /*If p is NULL no reduction is performed.*/
        !          2162: GEN
        !          2163: FpM_FpV_mul(GEN x, GEN y, GEN p)
        !          2164: {
        !          2165:   long i,l,lx=lg(x), ly=lg(y);
        !          2166:   GEN z;
        !          2167:   if (lx != ly) err(operi,"* [mod p]",t_MAT,t_COL);
        !          2168:   z=cgetg(ly,t_COL);
        !          2169:   if (lx==1) return cgetg(1,t_COL);
        !          2170:   l=lg(x[1]);
        !          2171:   for (i=1; i<l; i++)
        !          2172:   {
        !          2173:     ulong av;
        !          2174:     GEN p1,p2;
        !          2175:     int k;
        !          2176:     p1=gzero; av=avma;
        !          2177:     for (k=1; k<lx; k++)
        !          2178:     {
        !          2179:       p2=mulii(gcoeff(x,i,k),(GEN)y[k]);
        !          2180:       p1=addii(p1,p2);
        !          2181:     }
        !          2182:     z[i]=lpileupto(av,p?modii(p1,p):p1);
        !          2183:   }
        !          2184:   return z;
        !          2185: }
        !          2186:
        !          2187: static GEN
        !          2188: u_FpM_ker(GEN x, GEN pp, long nontriv)
        !          2189: {
        !          2190:   GEN y,c,d;
        !          2191:   long a,i,j,k,r,t,n,m,av0,tetpil, p = pp[2], piv;
        !          2192:
        !          2193:   n = lg(x)-1;
        !          2194:   m=lg(x[1])-1; r=0; av0 = avma;
        !          2195:   x = dummycopy(x);
        !          2196:   for (i=1; i<=n; i++)
        !          2197:   {
        !          2198:     GEN p1 = (GEN)x[i];
        !          2199:     for (j=1; j<=m; j++) p1[j] = itos((GEN)p1[j]);
        !          2200:   }
        !          2201:   c=new_chunk(m+1); for (k=1; k<=m; k++) c[k]=0;
        !          2202:   d=new_chunk(n+1);
        !          2203:   a=0; /* for gcc -Wall */
        !          2204:   for (k=1; k<=n; k++)
        !          2205:   {
        !          2206:     for (j=1; j<=m; j++)
        !          2207:       if (!c[j])
        !          2208:       {
        !          2209:         a = coeff(x,j,k) % p;
        !          2210:         if (a) break;
        !          2211:       }
        !          2212:     if (j>m)
        !          2213:     {
        !          2214:       if (nontriv) { avma=av0; return NULL; }
        !          2215:       r++; d[k]=0;
        !          2216:     }
        !          2217:     else
        !          2218:     {
        !          2219:       c[j]=k; d[k]=j;
        !          2220:       piv = - u_Fp_inv(a, p);
        !          2221:       coeff(x,j,k) = -1;
        !          2222:       for (i=k+1; i<=n; i++)
        !          2223:        coeff(x,j,i) = (piv * coeff(x,j,i)) % p;
        !          2224:       for (t=1; t<=m; t++)
        !          2225:        if (t!=j)
        !          2226:        {
        !          2227:          piv = coeff(x,t,k) % p;
        !          2228:           if (piv)
        !          2229:           {
        !          2230:             coeff(x,t,k) = 0;
        !          2231:             for (i=k+1; i<=n; i++) _u_Fp_addmul((GEN)x[i],t,j,piv,p);
        !          2232:           }
        !          2233:        }
        !          2234:     }
        !          2235:   }
        !          2236:
        !          2237:   tetpil=avma; y=cgetg(r+1,t_MAT);
        !          2238:   for (j=k=1; j<=r; j++,k++)
        !          2239:   {
        !          2240:     GEN c = cgetg(n+1,t_COL);
        !          2241:
        !          2242:     y[j]=(long)c; while (d[k]) k++;
        !          2243:     for (i=1; i<k; i++)
        !          2244:       if (d[i])
        !          2245:       {
        !          2246:         long a = coeff(x,d[i],k) % p;
        !          2247:         if (a < 0) a += p;
        !          2248:        c[i] = lstoi(a);
        !          2249:       }
        !          2250:       else
        !          2251:        c[i] = zero;
        !          2252:     c[k]=un; for (i=k+1; i<=n; i++) c[i]=zero;
        !          2253:   }
        !          2254:   return gerepile(av0,tetpil,y);
        !          2255: }
        !          2256:
        !          2257: static GEN
        !          2258: FpM_ker_i(GEN x, GEN p, long nontriv)
        !          2259: {
        !          2260:   GEN y,c,d,piv,mun;
        !          2261:   long i,j,k,r,t,n,m,av0,av,lim,tetpil;
        !          2262:
        !          2263:   if (typ(x)!=t_MAT) err(typeer,"FpM_ker");
        !          2264:   n=lg(x)-1; if (!n) return cgetg(1,t_MAT);
        !          2265:   if (OK_ULONG(p)) return u_FpM_ker(x, p, nontriv);
        !          2266:
        !          2267:   m=lg(x[1])-1; r=0; av0 = avma;
        !          2268:   x=dummycopy(x); mun=negi(gun);
        !          2269:   c=new_chunk(m+1); for (k=1; k<=m; k++) c[k]=0;
        !          2270:   d=new_chunk(n+1);
        !          2271:   av=avma; lim=stack_lim(av,1);
        !          2272:   for (k=1; k<=n; k++)
        !          2273:   {
        !          2274:     for (j=1; j<=m; j++)
        !          2275:       if (!c[j])
        !          2276:       {
        !          2277:         coeff(x,j,k) = lmodii(gcoeff(x,j,k), p);
        !          2278:         if (signe(coeff(x,j,k))) break;
        !          2279:       }
        !          2280:     if (j>m)
        !          2281:     {
        !          2282:       if (nontriv) { avma = av0; return NULL; }
        !          2283:       r++; d[k]=0;
        !          2284:       for(j=1; j<k; j++)
        !          2285:         if (d[j]) coeff(x,d[j],k) = lclone(gcoeff(x,d[j],k));
        !          2286:     }
        !          2287:     else
        !          2288:     {
        !          2289:       c[j]=k; d[k]=j; piv = negi(mpinvmod(gcoeff(x,j,k), p));
        !          2290:       coeff(x,j,k) = (long)mun;
        !          2291:       for (i=k+1; i<=n; i++)
        !          2292:        coeff(x,j,i) = lmodii(mulii(piv,gcoeff(x,j,i)), p);
        !          2293:       for (t=1; t<=m; t++)
        !          2294:        if (t!=j)
        !          2295:        {
        !          2296:          piv = modii(gcoeff(x,t,k), p);
        !          2297:           if (signe(piv))
        !          2298:           {
        !          2299:             coeff(x,t,k)=zero;
        !          2300:             for (i=k+1; i<=n; i++)
        !          2301:               coeff(x,t,i) = laddii(gcoeff(x,t,i),mulii(piv,gcoeff(x,j,i)));
        !          2302:             if (low_stack(lim, stack_lim(av,1)))
        !          2303:               gerepile_gauss_FpM_ker(x,p,m,n,k,t,av);
        !          2304:           }
        !          2305:        }
        !          2306:     }
        !          2307:   }
        !          2308:
        !          2309:   tetpil=avma; y=cgetg(r+1,t_MAT);
        !          2310:   for (j=k=1; j<=r; j++,k++)
        !          2311:   {
        !          2312:     GEN c = cgetg(n+1,t_COL);
        !          2313:
        !          2314:     y[j]=(long)c; while (d[k]) k++;
        !          2315:     for (i=1; i<k; i++)
        !          2316:       if (d[i])
        !          2317:       {
        !          2318:        GEN p1=gcoeff(x,d[i],k);
        !          2319:        c[i] = lmodii(p1, p); gunclone(p1);
        !          2320:       }
        !          2321:       else
        !          2322:        c[i] = zero;
        !          2323:     c[k]=un; for (i=k+1; i<=n; i++) c[i]=zero;
        !          2324:   }
        !          2325:   return gerepile(av0,tetpil,y);
        !          2326: }
        !          2327:
        !          2328: static void
        !          2329: FpM_gauss_pivot(GEN x, GEN p, GEN *dd, long *rr)
        !          2330: {
        !          2331:   GEN c,d,piv;
        !          2332:   long i,j,k,r,t,n,m,av,lim;
        !          2333:
        !          2334:   if (!p) return gauss_pivot(x,dd,rr);
        !          2335:   if (typ(x)!=t_MAT) err(typeer,"FpM_gauss_pivot");
        !          2336:   n=lg(x)-1; if (!n) { *dd=NULL; *rr=0; return; }
        !          2337:
        !          2338:   m=lg(x[1])-1; r=0;
        !          2339:   x=dummycopy(x);
        !          2340:   c=new_chunk(m+1); for (k=1; k<=m; k++) c[k]=0;
        !          2341:   d=(GEN)gpmalloc((n+1)*sizeof(long)); av=avma; lim=stack_lim(av,1);
        !          2342:   for (k=1; k<=n; k++)
        !          2343:   {
        !          2344:     for (j=1; j<=m; j++)
        !          2345:       if (!c[j])
        !          2346:       {
        !          2347:         coeff(x,j,k) = lmodii(gcoeff(x,j,k), p);
        !          2348:         if (signe(coeff(x,j,k))) break;
        !          2349:       }
        !          2350:     if (j>m) { r++; d[k]=0; }
        !          2351:     else
        !          2352:     {
        !          2353:       c[j]=k; d[k]=j; piv = negi(mpinvmod(gcoeff(x,j,k), p));
        !          2354:       for (i=k+1; i<=n; i++)
        !          2355:        coeff(x,j,i) = lmodii(mulii(piv,gcoeff(x,j,i)), p);
        !          2356:       for (t=1; t<=m; t++)
        !          2357:         if (!c[t]) /* no pivot on that line yet */
        !          2358:         {
        !          2359:           piv=gcoeff(x,t,k);
        !          2360:           if (signe(piv))
        !          2361:           {
        !          2362:             coeff(x,t,k)=zero;
        !          2363:             for (i=k+1; i<=n; i++)
        !          2364:               coeff(x,t,i) = laddii(gcoeff(x,t,i), mulii(piv,gcoeff(x,j,i)));
        !          2365:             if (low_stack(lim, stack_lim(av,1)))
        !          2366:               gerepile_gauss(x,m,n,k,t,av,j,c);
        !          2367:           }
        !          2368:         }
        !          2369:       for (i=k; i<=n; i++) coeff(x,j,i) = zero; /* dummy */
        !          2370:     }
        !          2371:   }
        !          2372:   *dd=d; *rr=r;
        !          2373: }
        !          2374:
        !          2375: GEN
        !          2376: FpM_ker(GEN x, GEN p)
        !          2377: {
        !          2378:   return FpM_ker_i(x, p, 0);
        !          2379: }
        !          2380:
        !          2381: int
        !          2382: ker_trivial_mod_p(GEN x, GEN p)
        !          2383: {
        !          2384:   return FpM_ker_i(x, p, 1)==NULL;
        !          2385: }
        !          2386:
        !          2387: GEN
        !          2388: FpM_image(GEN x, GEN p)
        !          2389: {
        !          2390:   GEN d,y;
        !          2391:   long j,k,r, av = avma;
        !          2392:
        !          2393:   FpM_gauss_pivot(x,p,&d,&r);
        !          2394:
        !          2395:   /* r = dim ker(x) */
        !          2396:   if (!r) { avma=av; if (d) free(d); return gcopy(x); }
        !          2397:
        !          2398:   /* r = dim Im(x) */
        !          2399:   r = lg(x)-1 - r; avma=av;
        !          2400:   y=cgetg(r+1,t_MAT);
        !          2401:   for (j=k=1; j<=r; k++)
        !          2402:     if (d[k]) y[j++] = lcopy((GEN)x[k]);
        !          2403:   free(d); return y;
        !          2404: }
        !          2405:
        !          2406: static GEN
        !          2407: sFpM_invimage(GEN mat, GEN y, GEN p)
        !          2408: {
        !          2409:   long av=avma,i, nbcol = lg(mat);
        !          2410:   GEN col,p1 = cgetg(nbcol+1,t_MAT),res;
        !          2411:
        !          2412:   if (nbcol==1) return NULL;
        !          2413:   if (lg(y) != lg(mat[1])) err(consister,"FpM_invimage");
        !          2414:
        !          2415:   p1[nbcol] = (long)y;
        !          2416:   for (i=1; i<nbcol; i++) p1[i]=mat[i];
        !          2417:   p1 = FpM_ker(p1,p); i=lg(p1)-1;
        !          2418:   if (!i) return NULL;
        !          2419:
        !          2420:   col = (GEN)p1[i]; p1 = (GEN) col[nbcol];
        !          2421:   if (gcmp0(p1)) return NULL;
        !          2422:
        !          2423:   p1 = mpinvmod(negi(p1),p);
        !          2424:   setlg(col,nbcol);
        !          2425:   for(i=1;i<nbcol;i++)
        !          2426:     col[i]=lmulii((GEN)col[i],p1);
        !          2427:   res=cgetg(nbcol,t_COL);
        !          2428:   for(i=1;i<nbcol;i++)
        !          2429:     res[i]=lmodii((GEN)col[i],p);
        !          2430:   return gerepileupto(av,res);
        !          2431: }
        !          2432:
        !          2433: /* Calcule l'image reciproque de v par m */
        !          2434: GEN
        !          2435: FpM_invimage(GEN m, GEN v, GEN p)
        !          2436: {
        !          2437:   long av=avma,j,lv,tv=typ(v);
        !          2438:   GEN y,p1;
        !          2439:
        !          2440:   if (typ(m)!=t_MAT) err(typeer,"inverseimage");
        !          2441:   if (tv==t_COL)
        !          2442:   {
        !          2443:     p1 = sFpM_invimage(m,v,p);
        !          2444:     if (p1) return p1;
        !          2445:     avma = av; return cgetg(1,t_MAT);
        !          2446:   }
        !          2447:   if (tv!=t_MAT) err(typeer,"inverseimage");
        !          2448:
        !          2449:   lv=lg(v)-1; y=cgetg(lv+1,t_MAT);
        !          2450:   for (j=1; j<=lv; j++)
        !          2451:   {
        !          2452:     p1 = sFpM_invimage(m,(GEN)v[j],p);
        !          2453:     if (!p1) { avma = av; return cgetg(1,t_MAT); }
        !          2454:     y[j] = (long)p1;
        !          2455:   }
        !          2456:   return y;
        !          2457: }
        !          2458: /**************************************************************
        !          2459:  Rather stupid implementation of linear algebra in finite fields
        !          2460:  **************************************************************/
        !          2461: static GEN
        !          2462: Fq_add(GEN x, GEN y, GEN T/*unused*/, GEN p)
        !          2463: {
        !          2464:   switch((typ(x)==t_POL)|((typ(y)==t_POL)<<1))
        !          2465:   {
        !          2466:     case 0: return modii(addii(x,y),p);
        !          2467:     case 1: return FpX_Fp_add(x,y,p);
        !          2468:     case 2: return FpX_Fp_add(y,x,p);
        !          2469:     case 3: return FpX_add(x,y,p);
        !          2470:   }
        !          2471:   return NULL;
        !          2472: }
        !          2473: #if 0
        !          2474: /* this function is really for FpV_roots_to_pol in polarit1.c
        !          2475:  * For consistency we write the code there.
        !          2476:  * To avoid having to remove static status, we rewrite it in polarit1.c
        !          2477:  */
        !          2478: static GEN
        !          2479: Fq_neg(GEN x, GEN T, GEN p)
        !          2480: {
        !          2481:   switch(typ(x)==t_POL)
        !          2482:   {
        !          2483:     case 0: return signe(x)?subii(p,x):gzero;
        !          2484:     case 1: return FpX_neg(x,p);
        !          2485:   }
        !          2486:   return NULL;
        !          2487: }
        !          2488: #endif
        !          2489:
        !          2490: static GEN
        !          2491: Fq_mul(GEN x, GEN y, GEN T, GEN p)
        !          2492: {
        !          2493:   switch((typ(x)==t_POL)|((typ(y)==t_POL)<<1))
        !          2494:   {
        !          2495:     case 0: return modii(mulii(x,y),p);
        !          2496:     case 1: return FpX_Fp_mul(x,y,p);
        !          2497:     case 2: return FpX_Fp_mul(y,x,p);
        !          2498:     case 3: return FpXQ_mul(x,y,T,p);
        !          2499:   }
        !          2500:   return NULL;
        !          2501: }
        !          2502:
        !          2503: static GEN
        !          2504: Fq_neg_inv(GEN x, GEN T, GEN p)
        !          2505: {
        !          2506:   switch(typ(x)==t_POL)
        !          2507:   {
        !          2508:     case 0: return mpinvmod(negi(x),p);
        !          2509:     case 1: return FpXQ_inv(FpX_neg(x,p),T,p);
        !          2510:   }
        !          2511:   return NULL;
        !          2512: }
        !          2513:
        !          2514: static GEN
        !          2515: Fq_res(GEN x, GEN T, GEN p)
        !          2516: {
        !          2517:   ulong ltop=avma;
        !          2518:   switch(typ(x)==t_POL)
        !          2519:   {
        !          2520:     case 0: return modii(x,p);
        !          2521:     case 1: return gerepileupto(ltop,FpX_res(FpX_red(x,p),T,p));
        !          2522:   }
        !          2523:   return NULL;
        !          2524: }
        !          2525:
        !          2526: static void
        !          2527: Fq_gerepile_gauss_ker(GEN x, GEN T, GEN p, long m, long n, long k, long t,
        !          2528:                       ulong av)
        !          2529: {
        !          2530:   ulong tetpil = avma,A;
        !          2531:   long dec,u,i;
        !          2532:
        !          2533:   if (DEBUGMEM > 1) err(warnmem,"gauss_pivot_ker. k=%ld, n=%ld",k,n);
        !          2534:   for (u=t+1; u<=m; u++)
        !          2535:     if (isonstack(coeff(x,u,k))) coeff(x,u,k) = (long) Fq_res(gcoeff(x,u,k),T,p);
        !          2536:   for (i=k+1; i<=n; i++)
        !          2537:     for (u=1; u<=m; u++)
        !          2538:       if (isonstack(coeff(x,u,i))) coeff(x,u,i) = (long) Fq_res(gcoeff(x,u,i),T,p);
        !          2539:
        !          2540:   (void)gerepile(av,tetpil,NULL); dec = av-tetpil;
        !          2541:   for (u=t+1; u<=m; u++)
        !          2542:   {
        !          2543:     A=coeff(x,u,k);
        !          2544:     if (A<av && A>=bot) coeff(x,u,k)+=dec;
        !          2545:   }
        !          2546:   for (i=k+1; i<=n; i++)
        !          2547:     for (u=1; u<=m; u++)
        !          2548:     {
        !          2549:       A=coeff(x,u,i);
        !          2550:       if (A<av && A>=bot) coeff(x,u,i)+=dec;
        !          2551:     }
        !          2552: }
        !          2553:
        !          2554: static GEN
        !          2555: FqM_ker_i(GEN x, GEN T, GEN p, long nontriv)
        !          2556: {
        !          2557:   GEN y,c,d,piv,mun;
        !          2558:   long i,j,k,r,t,n,m,av0,av,lim,tetpil;
        !          2559:
        !          2560:   if (typ(x)!=t_MAT) err(typeer,"FpM_ker");
        !          2561:   n=lg(x)-1; if (!n) return cgetg(1,t_MAT);
        !          2562:
        !          2563:   m=lg(x[1])-1; r=0; av0 = avma;
        !          2564:   x=dummycopy(x); mun=negi(gun);
        !          2565:   c=new_chunk(m+1); for (k=1; k<=m; k++) c[k]=0;
        !          2566:   d=new_chunk(n+1);
        !          2567:   av=avma; lim=stack_lim(av,1);
        !          2568:   for (k=1; k<=n; k++)
        !          2569:   {
        !          2570:     for (j=1; j<=m; j++)
        !          2571:       if (!c[j])
        !          2572:       {
        !          2573:         coeff(x,j,k) = (long) Fq_res(gcoeff(x,j,k), T, p);
        !          2574:         if (signe(coeff(x,j,k))) break;
        !          2575:       }
        !          2576:     if (j>m)
        !          2577:     {
        !          2578:       if (nontriv) { avma = av0; return NULL; }
        !          2579:       r++; d[k]=0;
        !          2580:       for(j=1; j<k; j++)
        !          2581:         if (d[j]) coeff(x,d[j],k) = lclone(gcoeff(x,d[j],k));
        !          2582:     }
        !          2583:     else
        !          2584:     {
        !          2585:       c[j]=k; d[k]=j; piv = Fq_neg_inv(gcoeff(x,j,k), T, p);
        !          2586:       coeff(x,j,k) = (long)mun;
        !          2587:       for (i=k+1; i<=n; i++)
        !          2588:        coeff(x,j,i) = (long) Fq_mul(piv,gcoeff(x,j,i), T, p);
        !          2589:       for (t=1; t<=m; t++)
        !          2590:        if (t!=j)
        !          2591:        {
        !          2592:          piv = Fq_res(gcoeff(x,t,k), T, p);
        !          2593:           if (signe(piv))
        !          2594:           {
        !          2595:             coeff(x,t,k)=zero;
        !          2596:             for (i=k+1; i<=n; i++)
        !          2597:               coeff(x,t,i) = (long)Fq_add(gcoeff(x,t,i),Fq_mul(piv,gcoeff(x,j,i), T, p), T, p);
        !          2598:             if (low_stack(lim, stack_lim(av,1)))
        !          2599:               Fq_gerepile_gauss_ker(x,T,p,m,n,k,t,av);
        !          2600:           }
        !          2601:        }
        !          2602:     }
        !          2603:   }
        !          2604:
        !          2605:   tetpil=avma; y=cgetg(r+1,t_MAT);
        !          2606:   for (j=k=1; j<=r; j++,k++)
        !          2607:   {
        !          2608:     GEN c = cgetg(n+1,t_COL);
        !          2609:
        !          2610:     y[j]=(long)c; while (d[k]) k++;
        !          2611:     for (i=1; i<k; i++)
        !          2612:       if (d[i])
        !          2613:       {
        !          2614:        GEN p1=gcoeff(x,d[i],k);
        !          2615:        c[i] = (long) Fq_res(p1, T, p); gunclone(p1);
        !          2616:       }
        !          2617:       else
        !          2618:        c[i] = zero;
        !          2619:     c[k]=un; for (i=k+1; i<=n; i++) c[i]=zero;
        !          2620:   }
        !          2621:   return gerepile(av0,tetpil,y);
        !          2622: }
        !          2623: GEN
        !          2624: FqM_ker(GEN x, GEN T, GEN p)
        !          2625: {
        !          2626:   return FqM_ker_i(x, T, p, 0);
        !          2627: }
        !          2628:
        !          2629: /*******************************************************************/
        !          2630: /*                                                                 */
        !          2631: /*                        EIGENVECTORS                             */
        !          2632: /*   (independent eigenvectors, sorted by increasing eigenvalue)   */
        !          2633: /*                                                                 */
        !          2634: /*******************************************************************/
        !          2635:
        !          2636: GEN
        !          2637: eigen(GEN x, long prec)
        !          2638: {
        !          2639:   GEN y,rr,p,ssesp,r1,r2,r3;
        !          2640:   long e,i,k,l,ly,ex, n = lg(x);
        !          2641:   ulong av = avma;
        !          2642:
        !          2643:   if (typ(x)!=t_MAT) err(typeer,"eigen");
        !          2644:   if (n != 1 && n != lg(x[1])) err(mattype1,"eigen");
        !          2645:   if (n<=2) return gcopy(x);
        !          2646:
        !          2647:   ex = 16 - bit_accuracy(prec);
        !          2648:   y=cgetg(n,t_MAT);
        !          2649:   p=caradj(x,0,NULL); rr=roots(p,prec);
        !          2650:   for (i=1; i<n; i++)
        !          2651:   {
        !          2652:     GEN p1 = (GEN)rr[i];
        !          2653:     if (!signe(p1[2]) || gexpo((GEN)p1[2]) - gexpo(p1) < ex) rr[i] = p1[1];
        !          2654:   }
        !          2655:   ly=1; k=2; r2=(GEN)rr[1];
        !          2656:   for(;;)
        !          2657:   {
        !          2658:     r3 = grndtoi(r2, &e); if (e < ex) r2 = r3;
        !          2659:     ssesp = ker0(x,r2); l = lg(ssesp);
        !          2660:     if (l == 1 || ly + (l-1) > n)
        !          2661:       err(talker2, "missing eigenspace. Compute the matrix to higher accuracy, then restart eigen at the current precision",NULL,NULL);
        !          2662:     for (i=1; i<l; ) y[ly++]=ssesp[i++]; /* done with this eigenspace */
        !          2663:
        !          2664:     r1=r2; /* try to find a different eigenvalue */
        !          2665:     do
        !          2666:     {
        !          2667:       if (k == n || ly == n)
        !          2668:       {
        !          2669:         setlg(y,ly); /* x may not be diagonalizable */
        !          2670:         return gerepilecopy(av,y);
        !          2671:       }
        !          2672:       r2 = (GEN)rr[k++];
        !          2673:       r3 = gsub(r1,r2);
        !          2674:     }
        !          2675:     while (gcmp0(r3) || gexpo(r3) < ex);
        !          2676:   }
        !          2677: }
        !          2678:
        !          2679: /*******************************************************************/
        !          2680: /*                                                                 */
        !          2681: /*                           DETERMINANT                           */
        !          2682: /*                                                                 */
        !          2683: /*******************************************************************/
        !          2684:
        !          2685: GEN
        !          2686: det0(GEN a,long flag)
        !          2687: {
        !          2688:   switch(flag)
        !          2689:   {
        !          2690:     case 0: return det(a);
        !          2691:     case 1: return det2(a);
        !          2692:     default: err(flagerr,"matdet");
        !          2693:   }
        !          2694:   return NULL; /* not reached */
        !          2695: }
        !          2696:
        !          2697: /* Exact types: choose the first non-zero pivot. Otherwise: maximal pivot */
        !          2698: static GEN
        !          2699: det_simple_gauss(GEN a, long inexact)
        !          2700: {
        !          2701:   long i,j,k,av,av1,s, nbco = lg(a)-1;
        !          2702:   GEN x,p;
        !          2703:
        !          2704:   av=avma; s=1; x=gun; a=dummycopy(a);
        !          2705:   for (i=1; i<nbco; i++)
        !          2706:   {
        !          2707:     p=gcoeff(a,i,i); k=i;
        !          2708:     if (inexact)
        !          2709:     {
        !          2710:       long e, ex = gexpo(p);
        !          2711:       GEN p1;
        !          2712:
        !          2713:       for (j=i+1; j<=nbco; j++)
        !          2714:       {
        !          2715:         e = gexpo(gcoeff(a,i,j));
        !          2716:         if (e > ex) { ex=e; k=j; }
        !          2717:       }
        !          2718:       p1 = gcoeff(a,i,k);
        !          2719:       if (gcmp0(p1)) return gerepilecopy(av, p1);
        !          2720:     }
        !          2721:     else if (gcmp0(p))
        !          2722:     {
        !          2723:       do k++; while(k<=nbco && gcmp0(gcoeff(a,i,k)));
        !          2724:       if (k>nbco) return gerepilecopy(av, p);
        !          2725:     }
        !          2726:     if (k != i)
        !          2727:     {
        !          2728:       swap(a[i],a[k]); s = -s;
        !          2729:       p = gcoeff(a,i,i);
        !          2730:     }
        !          2731:
        !          2732:     x = gmul(x,p);
        !          2733:     for (k=i+1; k<=nbco; k++)
        !          2734:     {
        !          2735:       GEN m = gcoeff(a,i,k);
        !          2736:       if (!gcmp0(m))
        !          2737:       {
        !          2738:        m = gneg_i(gdiv(m,p));
        !          2739:        for (j=i+1; j<=nbco; j++)
        !          2740:          coeff(a,j,k) = ladd(gcoeff(a,j,k), gmul(m,gcoeff(a,j,i)));
        !          2741:       }
        !          2742:     }
        !          2743:   }
        !          2744:   if (s<0) x = gneg_i(x);
        !          2745:   av1=avma; return gerepile(av,av1,gmul(x,gcoeff(a,nbco,nbco)));
        !          2746: }
        !          2747:
        !          2748: /* a has integer entries, N = P^n */
        !          2749: GEN
        !          2750: det_mod_P_n(GEN a, GEN N, GEN P)
        !          2751: {
        !          2752:   long va,i,j,k,s, av = avma, nbco = lg(a)-1;
        !          2753:   GEN x,p;
        !          2754:
        !          2755:   s=1; va=0; x=gun; a=dummycopy(a);
        !          2756:   p = NULL; /* for gcc -Wall */
        !          2757:   for (i=1; i<nbco; i++)
        !          2758:   {
        !          2759:     long fl = 0;
        !          2760:     for(;;)
        !          2761:     {
        !          2762:       for (k=i; k<=nbco; k++)
        !          2763:       {
        !          2764:         p=gcoeff(a,i,k);
        !          2765:         if (signe(p))
        !          2766:         {
        !          2767:           fl = 1;
        !          2768:           if (resii(p,P) != gzero) break;
        !          2769:         }
        !          2770:       }
        !          2771:       if (k <= nbco) break;
        !          2772:       va++; N = divii(N, P);
        !          2773:       if (!fl || is_pm1(N)) { avma=av; return gzero; }
        !          2774:       for (k=i; k<=nbco; k++) coeff(a,i,k) = ldivii(gcoeff(a,i,k), P);
        !          2775:     }
        !          2776:     if (k != i) { swap(a[i],a[k]); s = -s; }
        !          2777:
        !          2778:     x = gmul(x,p); p = mpinvmod(p,N);
        !          2779:     for (k=i+1; k<=nbco; k++)
        !          2780:     {
        !          2781:       GEN m = resii(gcoeff(a,i,k), N);
        !          2782:       coeff(a,i,k) = zero;
        !          2783:       if (signe(m))
        !          2784:       {
        !          2785:        m = negi(resii(mulii(m,p), N));
        !          2786:        for (j=i+1; j<=nbco; j++)
        !          2787:          coeff(a,j,k) = lresii(addii(gcoeff(a,j,k),
        !          2788:                                 mulii(m,gcoeff(a,j,i))), N);
        !          2789:       }
        !          2790:     }
        !          2791:   }
        !          2792:   if (s<0) x = negi(x);
        !          2793:   x = resii(mulii(x,gcoeff(a,nbco,nbco)), N);
        !          2794:   return gerepileuptoint(av, mulii(x, gpowgs(P,va)));
        !          2795: }
        !          2796:
        !          2797: GEN
        !          2798: det2(GEN a)
        !          2799: {
        !          2800:   long nbco = lg(a)-1;
        !          2801:   if (typ(a)!=t_MAT) err(mattype1,"det2");
        !          2802:   if (!nbco) return gun;
        !          2803:   if (nbco != lg(a[1])-1) err(mattype1,"det2");
        !          2804:   return det_simple_gauss(a,use_maximal_pivot(a));
        !          2805: }
        !          2806:
        !          2807: static GEN
        !          2808: mydiv(GEN x, GEN y)
        !          2809: {
        !          2810:   long tx = typ(x), ty = typ(y);
        !          2811:   if (tx == ty && tx == t_POL && varn(x) == varn(y))
        !          2812:     return gdeuc(x,y);
        !          2813:   return gdiv(x,y);
        !          2814: }
        !          2815:
        !          2816: /* determinant in a ring A: all computations are done within A
        !          2817:  * (Gauss-Bareiss algorithm) */
        !          2818: GEN
        !          2819: det(GEN a)
        !          2820: {
        !          2821:   ulong av, lim;
        !          2822:   long nbco = lg(a)-1,i,j,k,s;
        !          2823:   GEN p,pprec;
        !          2824:
        !          2825:   if (typ(a)!=t_MAT) err(mattype1,"det");
        !          2826:   if (!nbco) return gun;
        !          2827:   if (nbco != lg(a[1])-1) err(mattype1,"det");
        !          2828:   if (use_maximal_pivot(a)) return det_simple_gauss(a,1);
        !          2829:   if (DEBUGLEVEL > 7) timer2();
        !          2830:
        !          2831:   av = avma; lim = stack_lim(av,2);
        !          2832:   a = dummycopy(a); s = 1;
        !          2833:   for (pprec=gun,i=1; i<nbco; i++,pprec=p)
        !          2834:   {
        !          2835:     GEN *ci, *ck, m, p1;
        !          2836:     int diveuc = (gcmp1(pprec)==0);
        !          2837:
        !          2838:     p = gcoeff(a,i,i);
        !          2839:     if (gcmp0(p))
        !          2840:     {
        !          2841:       k=i+1; while (k<=nbco && gcmp0(gcoeff(a,i,k))) k++;
        !          2842:       if (k>nbco) return gerepilecopy(av, p);
        !          2843:       swap(a[k], a[i]); s = -s;
        !          2844:       p = gcoeff(a,i,i);
        !          2845:     }
        !          2846:     ci = (GEN*)a[i];
        !          2847:     for (k=i+1; k<=nbco; k++)
        !          2848:     {
        !          2849:       ck = (GEN*)a[k]; m = (GEN)ck[i];
        !          2850:       if (gcmp0(m))
        !          2851:       {
        !          2852:         if (gcmp1(p))
        !          2853:         {
        !          2854:           if (diveuc)
        !          2855:             a[k] = (long)mydiv((GEN)a[k], pprec);
        !          2856:         }
        !          2857:         else
        !          2858:           for (j=i+1; j<=nbco; j++)
        !          2859:           {
        !          2860:             p1 = gmul(p,ck[j]);
        !          2861:             if (diveuc) p1 = mydiv(p1,pprec);
        !          2862:             ck[j] = p1;
        !          2863:           }
        !          2864:       }
        !          2865:       else
        !          2866:       {
        !          2867:         m = gneg_i(m);
        !          2868:         for (j=i+1; j<=nbco; j++)
        !          2869:         {
        !          2870:           p1 = gadd(gmul(p,ck[j]), gmul(m,ci[j]));
        !          2871:           if (diveuc) p1 = mydiv(p1,pprec);
        !          2872:           ck[j] = p1;
        !          2873:         }
        !          2874:       }
        !          2875:       if (low_stack(lim,stack_lim(av,2)))
        !          2876:       {
        !          2877:         GEN *gptr[2]; gptr[0]=&a; gptr[1]=&pprec;
        !          2878:         if(DEBUGMEM>1) err(warnmem,"det. col = %ld",i);
        !          2879:         gerepilemany(av,gptr,2); p = gcoeff(a,i,i); ci = (GEN*)a[i];
        !          2880:       }
        !          2881:     }
        !          2882:     if (DEBUGLEVEL > 7) msgtimer("det, col %ld / %ld",i,nbco-1);
        !          2883:   }
        !          2884:   p = gcoeff(a,nbco,nbco);
        !          2885:   if (s < 0) p = gneg(p); else p = gcopy(p);
        !          2886:   return gerepileupto(av, p);
        !          2887: }
        !          2888:
        !          2889: /* return a solution of congruence system sum M_{ i,j } X_j = Y_i mod D_i
        !          2890:  * If ptu1 != NULL, put in *ptu1 a Z-basis of the homogeneous system
        !          2891:  */
        !          2892: static GEN
        !          2893: gaussmoduloall(GEN M, GEN D, GEN Y, GEN *ptu1)
        !          2894: {
        !          2895:   long n,m,i,j,lM,av=avma,tetpil;
        !          2896:   GEN p1,delta,H,U,u1,u2,x;
        !          2897:
        !          2898:   if (typ(M)!=t_MAT) err(typeer,"gaussmodulo");
        !          2899:   lM = lg(M); m = lM-1;
        !          2900:   if (!m)
        !          2901:   {
        !          2902:     if ((typ(Y)!=t_INT && lg(Y)!=1)
        !          2903:      || (typ(D)!=t_INT && lg(D)!=1)) err(consister,"gaussmodulo");
        !          2904:     return gzero;
        !          2905:   }
        !          2906:   n = lg(M[1])-1;
        !          2907:   switch(typ(D))
        !          2908:   {
        !          2909:     case t_VEC:
        !          2910:     case t_COL: delta=diagonal(D); break;
        !          2911:     case t_INT: delta=gscalmat(D,n); break;
        !          2912:     default: err(typeer,"gaussmodulo");
        !          2913:       return NULL; /* not reached */
        !          2914:   }
        !          2915:   if (typ(Y) == t_INT)
        !          2916:   {
        !          2917:     p1 = cgetg(n+1,t_COL);
        !          2918:     for (i=1; i<=n; i++) p1[i]=(long)Y;
        !          2919:     Y = p1;
        !          2920:   }
        !          2921:   p1 = hnfall(concatsp(M,delta));
        !          2922:   H = (GEN)p1[1]; U = (GEN)p1[2];
        !          2923:   Y = gauss(H,Y);
        !          2924:   if (!gcmp1(denom(Y))) return gzero;
        !          2925:   u1 = cgetg(m+1,t_MAT);
        !          2926:   u2 = cgetg(n+1,t_MAT);
        !          2927:   for (j=1; j<=m; j++)
        !          2928:   {
        !          2929:     p1 = (GEN)U[j]; setlg(p1,lM);
        !          2930:     u1[j] = (long)p1;
        !          2931:   }
        !          2932:   U += m;
        !          2933:   for (j=1; j<=n; j++)
        !          2934:   {
        !          2935:     p1 = (GEN)U[j]; setlg(p1,lM);
        !          2936:     u2[j] = (long)p1;
        !          2937:   }
        !          2938:   x = gmul(u2,Y);
        !          2939:   tetpil=avma; x=lllreducemodmatrix(x,u1);
        !          2940:   if (!ptu1) x = gerepile(av,tetpil,x);
        !          2941:   else
        !          2942:   {
        !          2943:     GEN *gptr[2];
        !          2944:     *ptu1=gcopy(u1); gptr[0]=ptu1; gptr[1]=&x;
        !          2945:     gerepilemanysp(av,tetpil,gptr,2);
        !          2946:   }
        !          2947:   return x;
        !          2948: }
        !          2949:
        !          2950: GEN
        !          2951: matsolvemod0(GEN M, GEN D, GEN Y, long flag)
        !          2952: {
        !          2953:   long av;
        !          2954:   GEN p1,y;
        !          2955:
        !          2956:   if (!flag) return gaussmoduloall(M,D,Y,NULL);
        !          2957:
        !          2958:   av=avma; y = cgetg(3,t_VEC);
        !          2959:   p1 = gaussmoduloall(M,D,Y, (GEN*)y+2);
        !          2960:   if (p1==gzero) { avma=av; return gzero; }
        !          2961:   y[1] = (long)p1; return y;
        !          2962: }
        !          2963:
        !          2964: GEN
        !          2965: gaussmodulo2(GEN M, GEN D, GEN Y)
        !          2966: {
        !          2967:   return matsolvemod0(M,D,Y,1);
        !          2968: }
        !          2969:
        !          2970: GEN
        !          2971: gaussmodulo(GEN M, GEN D, GEN Y)
        !          2972: {
        !          2973:   return matsolvemod0(M,D,Y,0);
        !          2974: }

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