00001 #include <stdlib.h>
00002 #include <polylib/polylib.h>
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 static void moins_l(Value *a,int i,int n,int p) {
00013
00014 int k;
00015 Value *c;
00016
00017 c=a+(i-1)*p;
00018
00019 for(k=1; k<=p; k++) {
00020 value_oppose(*c,*c);
00021 c++;
00022 }
00023 return;
00024 }
00025
00026
00027
00028
00029
00030
00031 static void moins_c(Value *a,int i,int n,int p) {
00032
00033 int k;
00034 Value *c;
00035
00036 c=a+(i-1);
00037
00038 for(k=1;k<=n;k++) {
00039 value_oppose(*c,*c);
00040 c=c+p;
00041 }
00042 return;
00043 }
00044
00045
00046
00047
00048
00049
00050 static void echange_l(Value *a,int i,int j,int n,int p) {
00051
00052 int k;
00053 Value s;
00054 Value *c1,*c2;
00055
00056 value_init(s);
00057 c1=a+(i-1)*p;
00058 c2=a+(j-1)*p;
00059
00060 for(k=1;k<=p;k++) {
00061 value_assign(s,*c1);
00062 value_assign(*c1,*c2);
00063 value_assign(*c2,s);
00064 c1++;
00065 c2++;
00066 }
00067 value_clear(s);
00068 return;
00069 }
00070
00071
00072
00073
00074
00075
00076 static void echange_c(Value *a,int i,int j,int n,int p) {
00077
00078 int k;
00079 Value s;
00080 Value *c1,*c2;
00081
00082 value_init(s);
00083 c1=a+(i-1);
00084 c2=a+(j-1);
00085
00086 for(k=1;k<=n;k++) {
00087 value_assign(s,*c1);
00088 value_assign(*c1,*c2);
00089 value_assign(*c2,s);
00090 c1=c1+p;
00091 c2=c2+p;
00092 }
00093 value_clear(s);
00094 return;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104 static void ligne(Value *a,int i,int j,Value x,int n,int p) {
00105
00106 int k;
00107 Value *c1,*c2;
00108 Value tmp;
00109
00110 value_init(tmp);
00111 c1=a+(i-1)*p;
00112 c2=a+(j-1)*p;
00113
00114 for(k=1;k<=p;k++) {
00115
00116 value_multiply(tmp,x,*c2);
00117 value_addto(*c1,*c1,tmp);
00118 c1++;
00119 c2++;
00120 }
00121 value_clear(tmp);
00122 return;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 static void colonne(Value *a,int i,int j,Value x,int n,int p) {
00134
00135 int k;
00136 Value *c1,*c2;
00137 Value tmp;
00138
00139 value_init(tmp);
00140 c1=a+(i-1);
00141 c2=a+(j-1);
00142
00143 for(k=1;k<=n;k++) {
00144 value_multiply(tmp,x,*c2);
00145 value_addto(*c1,*c1,tmp);
00146 c1=c1+p;
00147 c2=c2+p;
00148 }
00149 value_clear(tmp);
00150 return;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 static int petit_l(Value *a,int n,int p,int q) {
00165
00166 int numero=0, k, tousnuls;
00167 Value minus, comp;
00168 Value *c;
00169
00170 value_init(minus); value_init(comp);
00171 c=a+(q-1)*p+(p-1);
00172 tousnuls=1;
00173 for(k=p;k>q;k--) {
00174 value_absolute(comp,*c);
00175 if (value_notzero_p(comp)) {
00176 if (tousnuls==1) {
00177 value_assign(minus,comp);
00178 numero=k;
00179 tousnuls=0;
00180 }
00181 else if (value_ge(minus,comp)) {
00182 value_assign(minus,comp);
00183 numero=k;
00184 }
00185 }
00186 c--;
00187 }
00188 if (tousnuls==1) {
00189 value_clear(minus); value_clear(comp);
00190 return(0);
00191 }
00192 else {
00193 value_absolute(comp,*c);
00194 if ((value_notzero_p(comp))&&(value_ge(minus,comp))) {
00195 value_clear(minus); value_clear(comp);
00196 return(q);
00197 }
00198 else {
00199 value_clear(minus); value_clear(comp);
00200 return(numero);
00201 }
00202 }
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 static int petit_c(Value *a,int n,int p,int q) {
00217
00218 int numero=0, k, tousnuls;
00219 Value minus, comp;
00220 Value *c;
00221
00222 value_init(minus); value_init(comp);
00223 c = a+q-1+p*(n-1);
00224 tousnuls=1;
00225 for(k=n;k>q;k--) {
00226 value_absolute(comp,*c);
00227 if (value_notzero_p(comp)) {
00228 if (tousnuls==1) {
00229 value_assign(minus,comp);
00230 numero=k;
00231 tousnuls=0;
00232 }
00233 else if (value_ge(minus,comp)) {
00234 value_assign(minus,comp);
00235 numero=k;
00236 }
00237 }
00238 c=c-p;
00239 }
00240
00241 if (tousnuls==1) {
00242 value_clear(minus); value_clear(comp);
00243 return(0);
00244 }
00245 else {
00246 value_absolute(comp,*c);
00247 if ((value_notzero_p(comp)) && (value_ge(minus,comp))) {
00248 value_clear(minus); value_clear(comp);
00249 return(q);
00250 }
00251 else {
00252 value_clear(minus); value_clear(comp);
00253 return(numero);
00254 }
00255 }
00256 }
00257
00258
00259
00260
00261
00262
00263 static void identite(Value *a,int n,int p) {
00264
00265 int i,j;
00266 Value *b;
00267
00268 b = a;
00269 for(i=1;i<=n;i++) {
00270 for(j=1;j<=p;j++) {
00271 if (i==j)
00272 value_set_si(*b,1);
00273 else
00274 value_set_si(*b,0);
00275 b++;
00276 }
00277 }
00278 return;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288 static void transpose(Value *a,int n,int q) {
00289
00290 int i;
00291 Value val;
00292 Value *b,*c;
00293
00294 value_init(val);
00295 if (q<n) {
00296 b=a+(q-1)+(q-1)*n;
00297 c=b;
00298 for(i=q+1;i<=n;i++) {
00299 b++;
00300 c=c+n;
00301 value_assign(val,*b);
00302 value_assign(*b,*c);
00303 value_assign(*c,val);
00304 }
00305 transpose(a,n,q+1);
00306 }
00307 value_clear(val);
00308 return;
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 static int encore(Value *a,int n,int p,int q,Value val) {
00321
00322 int k,l;
00323 Value comp, tmp;
00324 Value *c;
00325
00326 if ((q>=n)||(q>=p)) return(0);
00327
00328 value_init(comp); value_init(tmp);
00329 c=a+q*p+q;
00330 k=q+1;
00331 l=q+1;
00332 while (k<=n) {
00333 value_absolute(comp,*c);
00334 if (value_zero_p(val)) {
00335 if (value_notzero_p(comp)) {
00336 value_clear(comp);
00337 value_clear(tmp);
00338 return(l);
00339 }
00340 }
00341 else {
00342 value_modulus(tmp,comp,val);
00343 if (value_notzero_p(tmp)) {
00344 value_clear(comp);
00345 value_clear(tmp);
00346 return(l);
00347 }
00348 }
00349 if (l==p) {
00350 k=k+1;
00351 l=q+1;
00352 c=c+q+1;
00353 }
00354 else {
00355 l++;
00356 c++;
00357 }
00358 }
00359 value_clear(comp);
00360 value_clear(tmp);
00361 return(0);
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 static void smith(Value *a,Value *b,Value *c,Value *b_inverse,Value *c_inverse,int n,int p,int q) {
00375
00376 int i,k,fini;
00377 Value x, pivot, tmp, x_inv;
00378 Value *f;
00379
00380 value_init(pivot); value_init(tmp);
00381 value_init(x); value_init(x_inv);
00382
00383 if ((q<=n)&&(q<=p)) {
00384 fini = 1;
00385
00386 while (fini!=0) {
00387 i=petit_c(a,n,p,q);
00388 while (i!=0) {
00389 if (i!=q) {
00390 echange_l(a,i,q,n,p);
00391 echange_l(b,i,q,n,n);
00392 echange_c(b_inverse,i,q,n,n);
00393 }
00394 f=a+(q-1)+(q-1)*p;
00395 value_assign(pivot,*f);
00396 if (value_neg_p(pivot)) {
00397 moins_l(a,q,n,p);
00398 moins_l(b,q,n,n);
00399 moins_c(b_inverse,q,n,n);
00400 value_oppose(pivot,pivot);
00401 }
00402 for(k=q+1;k<=n;k++) {
00403 f=f+p;
00404 if (value_notzero_p(*f)) {
00405 value_division(x,*f,pivot);
00406 value_modulus(tmp,*f,pivot);
00407 if (value_neg_p(tmp))
00408 value_decrement(x,x);
00409 value_oppose(x_inv,x);
00410 ligne(a,k,q,x_inv,n,p);
00411 ligne(b,k,q,x_inv,n,n);
00412 colonne(b_inverse,q,k,x,n,n);
00413 }
00414 }
00415 i=petit_c(a,n,p,q);
00416 }
00417 fini=0;
00418 i=petit_l(a,n,p,q);
00419 while (i!=0) {
00420 if (i!=q) {
00421 echange_c(a,i,q,n,p);
00422 echange_c(c,i,q,p,p);
00423 echange_l(c_inverse,i,q,p,p);
00424 fini=1;
00425 }
00426 f=a+(q-1)+(q-1)*p;
00427 value_assign(pivot,*f);
00428 if (value_neg_p(pivot)) {
00429 moins_c(a,q,n,p);
00430 moins_c(c,q,p,p);
00431 moins_l(c_inverse,q,p,p);
00432 value_oppose(pivot,pivot);
00433 }
00434 for(k=q+1;k<=p;k++) {
00435 f++;
00436 if (value_notzero_p(*f)) {
00437 value_division(x,*f,pivot);
00438 value_modulus(tmp,*f,pivot);
00439 if (value_neg_p(tmp))
00440 value_decrement(x,x);
00441 value_oppose(x_inv,x);
00442 colonne(a,k,q,x_inv,n,p);
00443 colonne(c,k,q,x_inv,p,p);
00444 ligne(c_inverse,q,k,x,p,p);
00445 }
00446 }
00447 i=petit_l(a,n,p,q);
00448 }
00449 }
00450 value_assign(pivot,*(a+(q-1)+(q-1)*p));
00451 if (value_neg_p(pivot)) {
00452 moins_l(a,q,n,p);
00453 moins_l(b,q,n,n);
00454 moins_c(b_inverse,q,n,n);
00455 value_oppose(pivot,pivot);
00456 }
00457
00458 i=encore(a,n,p,q,pivot);
00459 if (i!=0) {
00460 value_set_si(x,1);
00461 value_set_si(x_inv,-1);
00462 colonne(a,q,i,x,n,p);
00463 colonne(c,q,i,x,p,p);
00464 ligne(c_inverse,i,q,x_inv,p,p);
00465 smith(a,b,c,b_inverse,c_inverse,n,p,q);
00466 }
00467 else smith(a,b,c,b_inverse,c_inverse,n,p,q+1);
00468 }
00469 value_clear(pivot); value_clear(tmp);
00470 value_clear(x); value_clear(x_inv);
00471
00472 return;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 static void hermite(Value *a,Value *b,Value *d,int n,int p,int q) {
00484
00485 int i,k;
00486 Value x, pivot, x_inv, tmp;
00487 Value *c1;
00488
00489 value_init(pivot); value_init(tmp);
00490 value_init(x); value_init(x_inv);
00491
00492 if ((q<=p)&&(q<=n)) {
00493 i=petit_c(a,n,p,q);
00494 while (i!=0) {
00495 if (i!=q) {
00496 echange_l(a,i,q,n,p);
00497 echange_c(b,i,q,n,n);
00498 echange_l(d,i,q,n,n);
00499 }
00500
00501 c1=a+(q-1)+(q-1)*p;
00502 value_assign(pivot,*c1);
00503 if (value_neg_p(pivot)) {
00504 moins_l(a,q,n,p);
00505 moins_l(d,q,n,n);
00506 moins_c(b,q,n,n);
00507 value_oppose(pivot,pivot);
00508 }
00509 for(k=q+1;k<=n;k++) {
00510 c1=c1+p;
00511 if (value_notzero_p(*c1)) {
00512 value_division(x,*c1,pivot);
00513 value_modulus(tmp,*c1,pivot);
00514 if (value_neg_p(tmp))
00515 value_decrement(x,x);
00516 value_oppose(x_inv,x);
00517 ligne(a,k,q,x_inv,n,p);
00518 colonne(b,q,k,x,n,n);
00519 ligne(d,k,q,x_inv,n,n);
00520 }
00521 }
00522 i=petit_c(a,n,p,q);
00523 }
00524 c1=a+(q-1);
00525 value_assign(pivot,*(c1+(q-1)*p));
00526 if (value_neg_p(pivot)) {
00527 moins_l(a,q,n,p);
00528 moins_l(d,q,n,n);
00529 moins_c(b,q,n,n);
00530 value_oppose(pivot,pivot);
00531 }
00532 if (value_notzero_p(pivot)) {
00533 for(k=1;k<q;k++) {
00534 if (value_notzero_p(*c1)) {
00535 value_division(x,*c1,pivot);
00536 value_modulus(tmp,*c1,pivot);
00537 if (value_neg_p(tmp))
00538 value_decrement(x,x);
00539 value_oppose(x_inv,x);
00540 ligne(a,k,q,x_inv,n,p);
00541 colonne(b,q,k,x,n,n);
00542 ligne(d,k,q,x_inv,n,n);
00543 }
00544 c1=c1+p;
00545 }
00546 }
00547 hermite(a,b,d,n,p,q+1);
00548 }
00549 value_clear(pivot); value_clear(tmp);
00550 value_clear(x); value_clear(x_inv);
00551 return;
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 static Value *ConvertPolMattoDarMat(Matrix *A ) {
00572
00573 int i,j;
00574 Value *result;
00575
00576 result = (Value *)malloc(sizeof(Value) * A->NbRows * A->NbColumns);
00577 for(i=0;i<A->NbRows * A->NbColumns;i++)
00578 value_init(result[i]);
00579
00580 for (i = 0; i < A->NbRows; i++)
00581 for (j = 0 ; j < A->NbColumns; j++)
00582 value_assign(result[i*A->NbColumns + j],A->p[i][j]);
00583 return result;
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 static Matrix *ConvertDarMattoPolMat (Value *A, int NbRows, int NbCols) {
00596
00597 int i,j;
00598 Matrix *result;
00599
00600 result = Matrix_Alloc(NbRows, NbCols);
00601
00602 for (i = 0; i < NbRows; i ++)
00603 for (j = 0; j < NbCols; j ++)
00604 value_assign(result->p[i][j],A[i*NbCols + j]);
00605 return result;
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 void Smith (Matrix *A, Matrix **U, Matrix **V, Matrix **Product) {
00620
00621 int i;
00622 Value *a, *u, *v, *u_inv, *v_inv;
00623 Matrix *temp;
00624
00625 u = (Value *) malloc(sizeof(Value) * (A->NbRows) * (A->NbRows));
00626 v = (Value *) malloc(sizeof(Value) * A->NbColumns * A->NbColumns);
00627 u_inv = (Value *) malloc(sizeof(Value) * A->NbRows * A->NbRows);
00628 v_inv = (Value *) malloc(sizeof(Value) * A->NbColumns * A->NbColumns);
00629
00630 for (i=0;i < (A->NbRows * A->NbRows);i++)
00631 value_init(u[i]);
00632 for (i=0;i < (A->NbColumns * A->NbColumns);i++)
00633 value_init(v[i]);
00634 for (i=0;i < (A->NbRows * A->NbRows);i++)
00635 value_init(u_inv[i]);
00636 for (i=0;i < (A->NbColumns * A->NbColumns);i++)
00637 value_init(v_inv[i]);
00638
00639 identite(u,A->NbRows,A->NbRows);
00640 identite(u_inv,A->NbRows,A->NbRows);
00641 identite(v, A->NbColumns,A->NbColumns);
00642 identite(v_inv,A->NbColumns,A->NbColumns);
00643
00644 a = ConvertPolMattoDarMat(A);
00645 smith(a,u,v,u_inv,v_inv,A->NbRows,A->NbColumns,1);
00646 *Product = ConvertDarMattoPolMat(a,A->NbRows,A->NbColumns);
00647 temp = ConvertDarMattoPolMat(u,A->NbRows, A->NbRows);
00648 *U= Matrix_Alloc(temp->NbRows, temp->NbColumns);
00649 Matrix_Inverse(temp, *U);
00650 Matrix_Free(temp);
00651
00652 temp = ConvertDarMattoPolMat(v,A->NbColumns, A->NbColumns);
00653 *V= Matrix_Alloc(temp->NbRows, temp->NbColumns);
00654 Matrix_Inverse(temp, *V);
00655 Matrix_Free(temp);
00656
00657 for (i=0;i < (A->NbRows * A->NbRows);i++)
00658 value_clear(u[i]);
00659 for (i=0;i < (A->NbColumns * A->NbColumns);i++)
00660 value_clear(v[i]);
00661 for (i=0;i < (A->NbRows * A->NbRows);i++)
00662 value_clear(u_inv[i]);
00663 for (i=0;i < (A->NbColumns * A->NbColumns);i++)
00664 value_clear(v_inv[i]);
00665 free (a);
00666 free (u); free (v);
00667 free (u_inv); free (v_inv);
00668 return;
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 void Hermite (Matrix *A, Matrix **H, Matrix **U) {
00696
00697 int i;
00698 Matrix *transpose, *tempH, *tempU ;
00699 Value *darte_matA, *darte_identite, *darte_id_inv;
00700
00701 transpose = Transpose(A);
00702 darte_matA = ConvertPolMattoDarMat(transpose);
00703
00704 darte_identite = (Value *)malloc(sizeof(Value) * A->NbColumns* A->NbColumns);
00705 darte_id_inv = (Value *) malloc(sizeof(Value) * A->NbColumns*A->NbColumns);
00706 for (i=0; i< A->NbColumns * A->NbColumns; i++)
00707 value_init(darte_identite[i]);
00708 for (i=0; i< A->NbColumns * A->NbColumns; i++)
00709 value_init(darte_id_inv[i]);
00710
00711 identite(darte_identite, transpose->NbRows, transpose->NbRows);
00712 identite(darte_id_inv, transpose->NbRows, transpose->NbRows);
00713 hermite(darte_matA, darte_identite, darte_id_inv,A->NbColumns,A->NbRows, 1);
00714 Matrix_Free (transpose);
00715 transpose = ConvertDarMattoPolMat(darte_matA, A->NbColumns, A->NbRows);
00716 tempU = ConvertDarMattoPolMat(darte_identite, A->NbColumns, A->NbColumns);
00717
00718
00719 tempH = Transpose(transpose);
00720 Matrix_Free(transpose);
00721
00722
00723 transpose = Transpose(tempU);
00724
00725 H[0] = Matrix_Copy(tempH);
00726 U[0] = Matrix_Copy(transpose);
00727
00728 Matrix_Free (tempH);
00729 Matrix_Free (transpose);
00730 Matrix_Free (tempU);
00731
00732 for (i=0; i< A->NbColumns * A->NbColumns; i++)
00733 value_clear(darte_identite[i]);
00734 for (i=0; i< A->NbColumns * A->NbColumns; i++)
00735 value_clear(darte_id_inv[i]);
00736 free (darte_matA);
00737 free (darte_identite);
00738 free (darte_id_inv);
00739 return;
00740 }
00741
00742