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