00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <ctype.h>
00019 #include <polylib/polylib.h>
00020
00021 #ifdef mac_os
00022 #define abs __abs
00023 #endif
00024
00025
00026
00027
00028 Matrix *Matrix_Alloc(unsigned NbRows,unsigned NbColumns) {
00029
00030 Matrix *Mat;
00031 Value *p, **q;
00032 int i,j;
00033
00034 Mat=(Matrix *)malloc(sizeof(Matrix));
00035 if(!Mat) {
00036 errormsg1("Matrix_Alloc", "outofmem", "out of memory space");
00037 return 0;
00038 }
00039 Mat->NbRows=NbRows;
00040 Mat->NbColumns=NbColumns;
00041 if (NbRows==0 || NbColumns==0) {
00042 Mat->p = (Value **)0;
00043 Mat->p_Init= (Value *)0;
00044 Mat->p_Init_size = 0;
00045 } else {
00046 q = (Value **)malloc(NbRows * sizeof(*q));
00047 if(!q) {
00048 free(Mat);
00049 errormsg1("Matrix_Alloc", "outofmem", "out of memory space");
00050 return 0;
00051 }
00052 p = value_alloc(NbRows * NbColumns, &Mat->p_Init_size);
00053 if(!p) {
00054 free(q);
00055 free(Mat);
00056 errormsg1("Matrix_Alloc", "outofmem", "out of memory space");
00057 return 0;
00058 }
00059 Mat->p = q;
00060 Mat->p_Init = p;
00061 for (i=0;i<NbRows;i++) {
00062 *q++ = p;
00063 p += NbColumns;
00064 }
00065 }
00066 p = NULL;
00067 q = NULL;
00068
00069 return Mat;
00070 }
00071
00072
00073
00074
00075 void Matrix_Free(Matrix *Mat)
00076 {
00077 if (Mat->p_Init)
00078 value_free(Mat->p_Init, Mat->p_Init_size);
00079
00080 if (Mat->p)
00081 free(Mat->p);
00082 free(Mat);
00083
00084 }
00085
00086
00087
00088
00089 void Matrix_Print(FILE *Dst,char *Format,Matrix *Mat) {
00090
00091 Value *p;
00092 int i, j;
00093 unsigned NbRows, NbColumns;
00094
00095 fprintf(Dst,"%d %d\n", NbRows=Mat->NbRows, NbColumns=Mat->NbColumns);
00096 for (i=0;i<NbRows;i++) {
00097 p=*(Mat->p+i);
00098 for (j=0;j<NbColumns;j++) {
00099 if (!Format) {
00100 value_print(Dst," "P_VALUE_FMT" ",*p++);
00101 }
00102 else {
00103 value_print(Dst,Format,*p++);
00104 }
00105 }
00106 fprintf(Dst, "\n");
00107 }
00108 }
00109
00110
00111
00112
00113 void Matrix_Read_Input(Matrix *Mat) {
00114
00115 Value *p;
00116 int i,j,n;
00117 char *c, s[1024],str[1024];
00118
00119 p = Mat->p_Init;
00120 for (i=0;i<Mat->NbRows;i++) {
00121 do {
00122 c = fgets(s, 1024, stdin);
00123 while(isspace(*c) && *c!='\n')
00124 ++c;
00125 } while(c && (*c =='#' || *c== '\n'));
00126
00127 if (!c) {
00128 errormsg1( "Matrix_Read", "baddim", "not enough rows" );
00129 break;
00130 }
00131 for (j=0;j<Mat->NbColumns;j++) {
00132 if(!c || *c=='\n' || *c=='#') {
00133 errormsg1("Matrix_Read", "baddim", "not enough columns");
00134 break;
00135 }
00136 if (sscanf(c,"%s%n",str,&n) == 0) {
00137 errormsg1( "Matrix_Read", "baddim", "not enough columns" );
00138 break;
00139 }
00140 value_read(*(p++),str);
00141 c += n;
00142 }
00143 }
00144 }
00145
00146
00147
00148
00149
00150 Matrix *Matrix_Read(void) {
00151
00152 Matrix *Mat;
00153 unsigned NbRows, NbColumns;
00154 char s[1024];
00155
00156 while(fgets(s, 1024, stdin)==0);
00157 while ((*s=='#' || *s=='\n') ||
00158 (sscanf(s, "%d %d", &NbRows, &NbColumns)<2))
00159 fgets(s, 1024, stdin);
00160 Mat = Matrix_Alloc(NbRows,NbColumns);
00161 if(!Mat) {
00162 errormsg1("Matrix_Read", "outofmem", "out of memory space");
00163 return(NULL);
00164 }
00165 Matrix_Read_Input(Mat);
00166 return Mat;
00167 }
00168
00169
00170
00171
00172 static int hermite(Matrix *H,Matrix *U,Matrix *Q) {
00173
00174 int nc, nr, i, j, k, rank, reduced, pivotrow;
00175 Value pivot,x,aux;
00176 Value *temp1, *temp2;
00177
00178
00179
00180
00181 if (!H) {
00182 errormsg1("Domlib", "nullH", "hermite: ? Null H");
00183 return -1;
00184 }
00185 nc = H->NbColumns;
00186 nr = H->NbRows;
00187 temp1 = (Value *) malloc(nc * sizeof(Value));
00188 temp2 = (Value *) malloc(nr * sizeof(Value));
00189 if (!temp1 ||!temp2) {
00190 errormsg1("Domlib", "outofmem", "out of memory space");
00191 return -1;
00192 }
00193
00194
00195 value_init(pivot); value_init(x);
00196 value_init(aux);
00197 for(i=0;i<nc;i++)
00198 value_init(temp1[i]);
00199 for(i=0;i<nr;i++)
00200 value_init(temp2[i]);
00201
00202 #ifdef DEBUG
00203 fprintf(stderr,"Start -----------\n");
00204 Matrix_Print(stderr,0,H);
00205 #endif
00206 for (k=0, rank=0; k<nc && rank<nr; k=k+1) {
00207 reduced = 1;
00208 #ifdef DEBUG
00209 fprintf(stderr, "Working on col %d. Rank=%d ----------\n", k+1, rank+1);
00210 #endif
00211 while (reduced) {
00212 reduced=0;
00213
00214
00215 value_absolute(pivot,H->p[rank][k]);
00216
00217
00218 pivotrow = rank;
00219
00220
00221 for (i=rank+1; i<nr; i++) {
00222 value_absolute(x,H->p[i][k]);
00223 if (value_notzero_p(x) &&
00224 (value_lt(x,pivot) || value_zero_p(pivot))) {
00225 value_assign(pivot,x);
00226 pivotrow = i;
00227 }
00228 }
00229
00230
00231 if (pivotrow != rank) {
00232 Vector_Exchange(H->p[pivotrow],H->p[rank],nc);
00233 if (U)
00234 Vector_Exchange(U->p[pivotrow],U->p[rank],nr);
00235 if (Q)
00236 Vector_Exchange(Q->p[pivotrow],Q->p[rank],nr);
00237
00238 #ifdef DEBUG
00239 fprintf(stderr,"Exchange rows %d and %d -----------\n", rank+1, pivotrow+1);
00240 Matrix_Print(stderr,0,H);
00241 #endif
00242 }
00243 value_assign(pivot,H->p[rank][k]);
00244
00245
00246 if (value_neg_p(pivot)) {
00247 value_oppose(pivot,pivot);
00248 for (j=0; j<nc; j++)
00249 value_oppose(H->p[rank][j],H->p[rank][j]);
00250
00251
00252 if (U)
00253 for (j=0; j<nr; j++)
00254 value_oppose(U->p[rank][j],U->p[rank][j]);
00255
00256
00257 if (Q)
00258 for (j=0; j<nr; j++)
00259 value_oppose(Q->p[rank][j],Q->p[rank][j]);
00260
00261
00262 #ifdef DEBUG
00263 fprintf(stderr,"Negate row %d -----------\n", rank+1);
00264 Matrix_Print(stderr,0,H);
00265 #endif
00266
00267 }
00268 if (value_notzero_p(pivot)) {
00269
00270
00271
00272
00273
00274 for (i=rank+1;i<nr;i++) {
00275 value_assign(x,H->p[i][k]);
00276 if (value_notzero_p(x)) {
00277 value_modulus(aux,x,pivot);
00278
00279
00280 if (value_neg_p(x) && value_notzero_p(aux)) {
00281
00282
00283 value_division(x,x,pivot);
00284 value_decrement(x,x);
00285 }
00286 else
00287 value_division(x,x,pivot);
00288 for (j=0; j<nc; j++) {
00289 value_multiply(aux,x,H->p[rank][j]);
00290 value_subtract(H->p[i][j],H->p[i][j],aux);
00291 }
00292
00293
00294 if (U)
00295 for (j=0; j<nr; j++) {
00296 value_multiply(aux,x,U->p[rank][j]);
00297 value_subtract(U->p[i][j],U->p[i][j],aux);
00298 }
00299
00300
00301 if (Q)
00302 for(j=0;j<nr;j++) {
00303
00304
00305 value_addmul(Q->p[rank][j], x, Q->p[i][j]);
00306 }
00307 reduced = 1;
00308
00309 #ifdef DEBUG
00310 fprintf(stderr,
00311 "row %d = row %d - %d row %d -----------\n", i+1, i+1, x, rank+1);
00312 Matrix_Print(stderr,0,H);
00313 #endif
00314
00315 }
00316 }
00317 }
00318 }
00319
00320
00321
00322
00323
00324 if (value_notzero_p(pivot)) {
00325 for (i=0; i<rank; i++) {
00326 value_assign(x,H->p[i][k]);
00327 if (value_notzero_p(x)) {
00328 value_modulus(aux,x,pivot);
00329
00330
00331 if (value_neg_p(x) && value_notzero_p(aux)) {
00332 value_division(x,x,pivot);
00333 value_decrement(x,x);
00334
00335
00336 }
00337 else
00338 value_division(x,x,pivot);
00339
00340
00341 for (j=0; j<nc; j++) {
00342 value_multiply(aux,x,H->p[rank][j]);
00343 value_subtract(H->p[i][j],H->p[i][j],aux);
00344 }
00345
00346
00347 if (U)
00348 for (j=0; j<nr; j++) {
00349 value_multiply(aux,x,U->p[rank][j]);
00350 value_subtract(U->p[i][j],U->p[i][j],aux);
00351 }
00352
00353
00354 if (Q)
00355 for (j=0; j<nr; j++) {
00356
00357
00358 value_addmul(Q->p[rank][j], x, Q->p[i][j]);
00359 }
00360 #ifdef DEBUG
00361 fprintf(stderr,
00362 "row %d = row %d - %d row %d -----------\n", i+1, i+1, x, rank+1);
00363 Matrix_Print(stderr,0,H);
00364 #endif
00365 }
00366 }
00367 rank++;
00368 }
00369 }
00370
00371
00372 value_clear(pivot); value_clear(x);
00373 value_clear(aux);
00374 for(i=0;i<nc;i++)
00375 value_clear(temp1[i]);
00376 for(i=0;i<nr;i++)
00377 value_clear(temp2[i]);
00378 free(temp2);
00379 free(temp1);
00380 return rank;
00381 }
00382
00383 void right_hermite(Matrix *A,Matrix **Hp,Matrix **Up,Matrix **Qp) {
00384
00385 Matrix *H, *Q, *U;
00386 int i, j, nr, nc, rank;
00387 Value tmp;
00388
00389
00390 nc = A->NbColumns;
00391 nr = A->NbRows;
00392
00393
00394 *Hp = H = Matrix_Alloc(nr,nc);
00395 if (!H) {
00396 errormsg1("DomRightHermite", "outofmem", "out of memory space");
00397 return;
00398 }
00399
00400
00401 value_init(tmp);
00402
00403 Vector_Copy(A->p_Init,H->p_Init,nr*nc);
00404
00405
00406 if (Up) {
00407 *Up = U = Matrix_Alloc(nr, nr);
00408 if (!U) {
00409 errormsg1("DomRightHermite", "outofmem", "out of memory space");
00410 value_clear(tmp);
00411 return;
00412 }
00413 Vector_Set(U->p_Init,0,nr*nr);
00414 for(i=0;i<nr;i++)
00415 value_set_si(U->p[i][i],1);
00416 }
00417 else
00418 U = (Matrix *)0;
00419
00420
00421
00422 if (Qp) {
00423 *Qp = Q = Matrix_Alloc(nr,nr);
00424 if (!Q) {
00425 errormsg1("DomRightHermite", "outofmem", "out of memory space");
00426 value_clear(tmp);
00427 return;
00428 }
00429 Vector_Set(Q->p_Init,0,nr*nr);
00430 for (i=0;i<nr;i++)
00431 value_set_si(Q->p[i][i],1);
00432 }
00433 else
00434 Q = (Matrix *)0;
00435
00436 rank = hermite(H,U,Q);
00437
00438
00439
00440 if (Q) {
00441 for (i=0; i<nr; i++) {
00442 for (j=i+1; j<nr; j++) {
00443 value_assign(tmp,Q->p[i][j]);
00444 value_assign(Q->p[i][j],Q->p[j][i] );
00445 value_assign(Q->p[j][i],tmp);
00446 }
00447 }
00448 }
00449 value_clear(tmp);
00450 return;
00451 }
00452
00453 void left_hermite(Matrix *A,Matrix **Hp,Matrix **Qp,Matrix **Up) {
00454
00455 Matrix *H, *HT, *Q, *U;
00456 int i, j, nc, nr, rank;
00457 Value tmp;
00458
00459
00460
00461
00462
00463 nr = A->NbRows;
00464 nc = A->NbColumns;
00465
00466
00467 HT = Matrix_Alloc(nc, nr);
00468 if (!HT) {
00469 errormsg1("DomLeftHermite", "outofmem", "out of memory space");
00470 return;
00471 }
00472 value_init(tmp);
00473 for (i=0; i<nr; i++)
00474 for (j=0; j<nc; j++)
00475 value_assign(HT->p[j][i],A->p[i][j]);
00476
00477
00478 if (Up) {
00479 *Up = U = Matrix_Alloc(nc,nc);
00480 if (!U) {
00481 errormsg1("DomLeftHermite", "outofmem", "out of memory space");
00482 value_clear(tmp);
00483 return;
00484 }
00485 Vector_Set(U->p_Init,0,nc*nc);
00486 for (i=0;i<nc;i++)
00487 value_set_si(U->p[i][i],1);
00488 }
00489 else U=(Matrix *)0;
00490
00491
00492 if (Qp) {
00493 *Qp = Q = Matrix_Alloc(nc, nc);
00494 if (!Q) {
00495 errormsg1("DomLeftHermite", "outofmem", "out of memory space");
00496 value_clear(tmp);
00497 return;
00498 }
00499 Vector_Set(Q->p_Init,0,nc*nc);
00500 for (i=0;i<nc;i++)
00501 value_set_si(Q->p[i][i],1);
00502 }
00503 else Q=(Matrix *)0;
00504 rank = hermite(HT,U,Q);
00505
00506
00507 *Hp = H = Matrix_Alloc(nr,nc);
00508 if (!H) {
00509 errormsg1("DomLeftHermite", "outofmem", "out of memory space");
00510 value_clear(tmp);
00511 return;
00512 }
00513 for (i=0; i<nr; i++)
00514 for (j=0;j<nc;j++)
00515 value_assign(H->p[i][j],HT->p[j][i]);
00516 Matrix_Free(HT);
00517
00518
00519 if (U) {
00520 for (i=0; i<nc; i++) {
00521 for (j=i+1; j<nc; j++) {
00522 value_assign(tmp,U->p[i][j]);
00523 value_assign(U->p[i][j],U->p[j][i] );
00524 value_assign(U->p[j][i],tmp);
00525 }
00526 }
00527 }
00528 value_clear(tmp);
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 int MatInverse(Matrix *Mat,Matrix *MatInv ) {
00540
00541 int i, k, j, c;
00542 Value x, gcd, piv;
00543 Value m1,m2;
00544
00545 if(Mat->NbRows != Mat->NbColumns) {
00546 fprintf(stderr,"Trying to invert a non-square matrix !\n");
00547 return 0;
00548 }
00549
00550
00551 value_init(x); value_init(gcd); value_init(piv);
00552 value_init(m1); value_init(m2);
00553
00554 k = Mat->NbRows;
00555
00556
00557 Vector_Set(MatInv->p[0],0,k*(k+1));
00558
00559
00560
00561
00562 for(i=0;i<k;++i) {
00563 value_set_si(MatInv->p[i][i],1);
00564 value_set_si(MatInv->p[i][k],1);
00565 }
00566
00567
00568 for(i=0;i<k;++i) {
00569
00570
00571 if(value_zero_p(Mat->p[i][i])) {
00572
00573
00574 for(j=i;j<k;++j)
00575 if(value_notzero_p(Mat->p[j][i]))
00576 break;
00577
00578
00579
00580 if(j==k) {
00581
00582
00583 value_clear(x); value_clear(gcd); value_clear(piv);
00584 value_clear(m1); value_clear(m2);
00585 return 0;
00586 }
00587
00588
00589
00590
00591 for(c=0;c<k;++c) {
00592
00593
00594 value_assign(x,Mat->p[j][c]);
00595 value_assign(Mat->p[j][c],Mat->p[i][c]);
00596 value_assign(Mat->p[i][c],x);
00597
00598
00599 value_assign(x,MatInv->p[j][c]);
00600 value_assign(MatInv->p[j][c],MatInv->p[i][c]);
00601 value_assign(MatInv->p[i][c],x);
00602 }
00603 }
00604
00605
00606
00607
00608 for(j=0;j<k;++j) {
00609 if (j==i) continue;
00610 value_assign(x,Mat->p[j][i]);
00611 if(value_notzero_p(x)) {
00612 value_assign(piv,Mat->p[i][i]);
00613 Gcd(x,piv,&gcd);
00614 if (value_notone_p(gcd) ) {
00615 value_division(x,x,gcd);
00616 value_division(piv,piv,gcd);
00617 }
00618 for(c=((j>i)?i:0);c<k;++c) {
00619 value_multiply(m1,piv,Mat->p[j][c]);
00620 value_multiply(m2,x,Mat->p[i][c]);
00621 value_subtract(Mat->p[j][c],m1,m2);
00622 }
00623 for(c=0;c<k;++c) {
00624 value_multiply(m1,piv,MatInv->p[j][c]);
00625 value_multiply(m2,x,MatInv->p[i][c]);
00626 value_subtract(MatInv->p[j][c],m1,m2);
00627 }
00628
00629
00630
00631 Vector_Gcd(&MatInv->p[j][0],k,&m1);
00632 Vector_Gcd(&Mat->p[j][0],k,&m2);
00633 Gcd(m1,m2,&gcd);
00634 if(value_notone_p(gcd)) {
00635 for(c=0;c<k;++c) {
00636 value_division(Mat->p[j][c],Mat->p[j][c],gcd);
00637 value_division(MatInv->p[j][c],MatInv->p[j][c],gcd);
00638 }
00639 }
00640 }
00641 }
00642 }
00643
00644
00645
00646 for(j=0;j<k;++j) {
00647 value_assign(MatInv->p[j][k],Mat->p[j][j]);
00648
00649
00650
00651 Vector_Normalize_Positive(&MatInv->p[j][0],k+1,k);
00652 }
00653
00654
00655 value_clear(x); value_clear(gcd); value_clear(piv);
00656 value_clear(m1); value_clear(m2);
00657
00658 return 1;
00659 }
00660
00661
00662
00663
00664
00665
00666
00667 void rat_prodmat(Matrix *S,Matrix *X,Matrix *P) {
00668
00669 int i,j,k;
00670 int last_column_index = P->NbColumns - 1;
00671 Value lcm, old_lcm,gcd,last_column_entry,s1;
00672
00673 Value m1,m2;
00674
00675
00676 value_init(lcm); value_init(old_lcm); value_init(gcd);
00677 value_init(last_column_entry); value_init(s1);
00678
00679 value_init(m1); value_init(m2);
00680
00681
00682 value_assign(lcm,P->p[0][last_column_index]);
00683 for(k=1;k<P->NbRows;++k) {
00684 value_assign(old_lcm,lcm);
00685 value_assign(last_column_entry,P->p[k][last_column_index]);
00686 Gcd(lcm,last_column_entry,&gcd);
00687 value_division(m1,last_column_entry,gcd);
00688 value_multiply(lcm,lcm,m1);
00689 }
00690
00691
00692 for(i=0;i<X->NbRows;++i)
00693 for(j=0;j<P->NbColumns-1;++j) {
00694
00695
00696 value_set_si(s1,0);
00697 for(k=0;k<P->NbRows;++k) {
00698
00699
00700 if(value_one_p(lcm)) {
00701
00702
00703
00704 value_addmul(s1, X->p[i][k], P->p[k][j]);
00705 }
00706
00707
00708
00709
00710 else {
00711 value_multiply(m1,X->p[i][k],P->p[k][j]);
00712 value_division(m2,lcm,P->p[k][last_column_index]);
00713
00714
00715 value_addmul(s1, m1, m2);
00716 }
00717 }
00718 value_assign(S->p[i][j],s1);
00719 }
00720
00721 for(i=0;i<S->NbRows;++i) {
00722 value_assign(S->p[i][last_column_index],lcm);
00723
00724
00725 Vector_Normalize_Positive(&S->p[i][0],S->NbColumns,S->NbColumns-1);
00726 }
00727
00728
00729 value_clear(lcm); value_clear(old_lcm); value_clear(gcd);
00730 value_clear(last_column_entry); value_clear(s1);
00731
00732 value_clear(m1); value_clear(m2);
00733
00734 return;
00735 }
00736
00737
00738
00739
00740
00741 void Matrix_Vector_Product(Matrix *Mat,Value *p1,Value *p2) {
00742
00743 int NbRows, NbColumns, i, j;
00744 Value **cm, *q, *cp1, *cp2;
00745
00746
00747
00748 NbRows=Mat->NbRows;
00749 NbColumns=Mat->NbColumns;
00750
00751 cm = Mat->p;
00752 cp2 = p2;
00753 for(i=0;i<NbRows;i++) {
00754 q = *cm++;
00755 cp1 = p1;
00756 value_multiply(*cp2,*q,*cp1);
00757 q++;
00758 cp1++;
00759
00760
00761 for(j=1;j<NbColumns;j++) {
00762
00763
00764
00765
00766 value_addmul(*cp2, *q, *cp1);
00767 q++;
00768 cp1++;
00769 }
00770 cp2++;
00771 }
00772
00773 return;
00774 }
00775
00776
00777
00778
00779
00780 void Vector_Matrix_Product(Value *p1,Matrix *Mat,Value *p2) {
00781
00782 int NbRows, NbColumns, i, j;
00783 Value **cm, *cp1, *cp2;
00784
00785
00786
00787 NbRows=Mat->NbRows;
00788 NbColumns=Mat->NbColumns;
00789 cp2 = p2;
00790 cm = Mat->p;
00791 for (j=0;j<NbColumns;j++) {
00792 cp1 = p1;
00793 value_multiply(*cp2,*(*cm+j),*cp1);
00794 cp1++;
00795
00796
00797 for (i=1;i<NbRows;i++) {
00798
00799
00800
00801
00802 value_addmul(*cp2, *(*(cm+i)+j), *cp1);
00803 cp1++;
00804 }
00805 cp2++;
00806 }
00807
00808 return;
00809 }
00810
00811
00812
00813
00814
00815 void Matrix_Product(Matrix *Mat1,Matrix *Mat2,Matrix *Mat3) {
00816
00817 int Size, i, j, k;
00818 unsigned NbRows, NbColumns;
00819 Value **q1, **q2, *p1, *p3,sum;
00820
00821
00822 NbRows = Mat1->NbRows;
00823 NbColumns = Mat2->NbColumns;
00824
00825 Size = Mat1->NbColumns;
00826 if(Mat2->NbRows!=Size||Mat3->NbRows!=NbRows||Mat3->NbColumns!=NbColumns) {
00827 fprintf(stderr, "? Matrix_Product : incompatable matrix dimension\n");
00828 return;
00829 }
00830 value_init(sum);
00831
00832 p3 = Mat3->p_Init;
00833 q1 = Mat1->p;
00834 q2 = Mat2->p;
00835
00836
00837 for (i=0;i<NbRows;i++) {
00838 for (j=0;j<NbColumns;j++) {
00839 p1 = *(q1+i);
00840 value_set_si(sum,0);
00841 for (k=0;k<Size;k++) {
00842
00843
00844
00845
00846
00847 value_addmul(sum, *p1, *(*(q2+k)+j));
00848 p1++;
00849 }
00850 value_assign(*p3,sum);
00851 p3++;
00852 }
00853 }
00854 value_clear(sum);
00855
00856 return;
00857 }
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 int Matrix_Inverse(Matrix *Mat,Matrix *MatInv ) {
00868
00869 int i, k, j, c;
00870 Value x, gcd, piv;
00871 Value m1,m2;
00872 Value *den;
00873
00874 if(Mat->NbRows != Mat->NbColumns) {
00875 fprintf(stderr,"Trying to invert a non-square matrix !\n");
00876 return 0;
00877 }
00878
00879
00880 value_init(x); value_init(gcd); value_init(piv);
00881 value_init(m1); value_init(m2);
00882
00883 k = Mat->NbRows;
00884
00885
00886 Vector_Set(MatInv->p[0],0,k*k);
00887
00888
00889
00890
00891 for(i=0;i<k;++i) {
00892 value_set_si(MatInv->p[i][i],1);
00893
00894 }
00895
00896
00897 for(i=0;i<k;++i) {
00898
00899
00900 if(value_zero_p(Mat->p[i][i])) {
00901
00902
00903 for(j=i;j<k;++j)
00904 if(value_notzero_p(Mat->p[j][i]))
00905 break;
00906
00907
00908
00909 if(j==k) {
00910
00911
00912 value_clear(x); value_clear(gcd); value_clear(piv);
00913 value_clear(m1); value_clear(m2);
00914 return 0;
00915 }
00916
00917
00918
00919
00920 for(c=0;c<k;++c) {
00921
00922
00923 value_assign(x,Mat->p[j][c]);
00924 value_assign(Mat->p[j][c],Mat->p[i][c]);
00925 value_assign(Mat->p[i][c],x);
00926
00927
00928 value_assign(x,MatInv->p[j][c]);
00929 value_assign(MatInv->p[j][c],MatInv->p[i][c]);
00930 value_assign(MatInv->p[i][c],x);
00931 }
00932 }
00933
00934
00935
00936
00937 for(j=0;j<k;++j) {
00938 if (j==i) continue;
00939 value_assign(x,Mat->p[j][i]);
00940 if(value_notzero_p(x)) {
00941 value_assign(piv,Mat->p[i][i]);
00942 Gcd(x,piv,&gcd);
00943 if (value_notone_p(gcd) ) {
00944 value_division(x,x,gcd);
00945 value_division(piv,piv,gcd);
00946 }
00947 for(c=((j>i)?i:0);c<k;++c) {
00948 value_multiply(m1,piv,Mat->p[j][c]);
00949 value_multiply(m2,x,Mat->p[i][c]);
00950 value_subtract(Mat->p[j][c],m1,m2);
00951 }
00952 for(c=0;c<k;++c) {
00953 value_multiply(m1,piv,MatInv->p[j][c]);
00954 value_multiply(m2,x,MatInv->p[i][c]);
00955 value_subtract(MatInv->p[j][c],m1,m2);
00956 }
00957
00958
00959
00960 Vector_Gcd(&MatInv->p[j][0],k,&m1);
00961 Vector_Gcd(&Mat->p[j][0],k,&m2);
00962 Gcd(m1,m2,&gcd);
00963 if(value_notone_p(gcd)) {
00964 for(c=0;c<k;++c) {
00965 value_division(Mat->p[j][c],Mat->p[j][c],gcd);
00966 value_division(MatInv->p[j][c],MatInv->p[j][c],gcd);
00967 }
00968 }
00969 }
00970 }
00971 }
00972
00973
00974 den = (Value *)malloc(k*sizeof(Value));
00975 value_set_si(x,1);
00976 for(j=0 ; j<k ; ++j) {
00977 value_init(den[j]);
00978 value_assign(den[j],Mat->p[j][j]);
00979
00980
00981 Vector_Gcd(&MatInv->p[j][0],k,&gcd);
00982 Gcd(gcd,den[j],&gcd);
00983 if (value_neg_p(den[j]))
00984 value_oppose(gcd,gcd);
00985 if (value_notone_p(gcd)) {
00986 for (c=0; c<k; c++)
00987 value_division(MatInv->p[j][c],MatInv->p[j][c],gcd);
00988 value_division(den[j],den[j],gcd);
00989 }
00990 Gcd(x,den[j],&gcd);
00991 value_division(m1,den[j],gcd);
00992 value_multiply(x,x,m1);
00993 }
00994 if (value_notone_p(x))
00995 for(j=0 ; j<k ; ++j) {
00996 for (c=0; c<k; c++) {
00997 value_division(m1,x,den[j]);
00998 value_multiply(MatInv->p[j][c],MatInv->p[j][c],m1);
00999 }
01000 }
01001
01002
01003 for(j=0 ; j<k ; ++j) {
01004 value_clear(den[j]);
01005 }
01006 value_clear(x); value_clear(gcd); value_clear(piv);
01007 value_clear(m1); value_clear(m2);
01008 free(den);
01009
01010 return 1;
01011 }
01012
01013
01014
01015
01016
01017
01018
01019