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