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