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