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]=ϖ 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>