polylib: NormalForms.c Source File

- Main Page
- Classes
- Files

- File List
- File Members

# NormalForms.c

Go to the documentation of this file.

    00001 /*
    00002     This file is part of PolyLib.
    00003
    00004     PolyLib is free software: you can redistribute it and/or modify
    00005     it under the terms of the GNU General Public License as published by
    00006     the Free Software Foundation, either version 3 of the License, or
    00007     (at your option) any later version.
    00008
    00009     PolyLib is distributed in the hope that it will be useful,
    00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00012     GNU General Public License for more details.
    00013
    00014     You should have received a copy of the GNU General Public License
    00015     along with PolyLib.  If not, see <http://www.gnu.org/licenses/>.
    00016 */
    00017
    00018 #include <stdlib.h>
    00019 #include <polylib/polylib.h>
    00020
    00021 /* nota bene: on stocke les matrices par lignes */
    00022 /* nota bene: matrices are stored in row major order */
    00023
    00024 /*------------------------------------------------------------------------
    00025         change les signes de la ligne i de la matrice A
    00026         change the sign of row i of matrix A
    00027 ------------------------------------------------------------------------*/
    00028
    00029 static void moins_l(Value *a,int i,int n,int p) {
    00030
    00031   int k;
    00032   Value *c;
    00033
    00034   c=a+(i-1)*p;
    00035
    00036   for(k=1; k<=p; k++) {
    00037     value_oppose(*c,*c);
    00038     c++;
    00039   }
    00040   return;
    00041 } /* moins_l */
    00042
    00043 /*------------------------------------------------------------------------
    00044         change les signes de la colonne i de la matrice A
    00045         change the sign of column i of matrix A
    00046 ------------------------------------------------------------------------*/
    00047
    00048 static void moins_c(Value *a,int i,int n,int p) {
    00049
    00050   int k;
    00051   Value *c;
    00052
    00053   c=a+(i-1);
    00054
    00055   for(k=1;k<=n;k++) {
    00056     value_oppose(*c,*c);
    00057     c=c+p;
    00058   }
    00059   return;
    00060 } /* moins_c */
    00061
    00062 /*------------------------------------------------------------------------
    00063         echange les lignes i et j de la matrice A
    00064         exchange row i and j of matrix A
    00065 ------------------------------------------------------------------------*/
    00066
    00067 static void echange_l(Value *a,int i,int j,int n,int p) {
    00068
    00069   int k;
    00070   Value s;
    00071   Value *c1,*c2;
    00072
    00073   value_init(s);
    00074   c1=a+(i-1)*p;
    00075   c2=a+(j-1)*p;
    00076
    00077   for(k=1;k<=p;k++) {
    00078     value_assign(s,*c1);
    00079     value_assign(*c1,*c2);
    00080     value_assign(*c2,s);
    00081     c1++;
    00082     c2++;
    00083   }
    00084   value_clear(s);
    00085   return;
    00086 } /* echange_l */
    00087
    00088 /*------------------------------------------------------------------------
    00089         echange les colonnes i et j de la matrice A
    00090         exchange columns i and j of matrix A
    00091 ------------------------------------------------------------------------*/
    00092
    00093 static void echange_c(Value *a,int i,int j,int n,int p) {
    00094
    00095   int k;
    00096   Value s;
    00097   Value *c1,*c2;
    00098
    00099   value_init(s);
    00100   c1=a+(i-1);
    00101   c2=a+(j-1);
    00102
    00103   for(k=1;k<=n;k++) {
    00104     value_assign(s,*c1);
    00105     value_assign(*c1,*c2);
    00106     value_assign(*c2,s);
    00107     c1=c1+p;
    00108     c2=c2+p;
    00109   }
    00110   value_clear(s);
    00111   return;
    00112 } /* echange_c */
    00113
    00114 /*------------------------------------------------------------------------
    00115         A est une matrice de taille n*p
    00116         on ajoute a la ligne i, x fois la ligne j
    00117         A is a matrix of size n*p
    00118         we add x times the row j to the row i
    00119 ------------------------------------------------------------------------*/
    00120
    00121 static void ligne(Value *a,int i,int j,Value x,int n,int p) {
    00122
    00123   int k;
    00124   Value *c1,*c2;
    00125
    00126   c1=a+(i-1)*p;
    00127   c2=a+(j-1)*p;
    00128
    00129   for(k=1;k<=p;k++) {
    00130
    00131     value_addmul(*c1, x, *c2);
    00132     c1++;
    00133     c2++;
    00134   }
    00135   return;
    00136 } /* ligne */
    00137
    00138 /*------------------------------------------------------------------------
    00139         A est une matrice de taille n*p
    00140         on ajoute a la colonne i, x fois la colonne j
    00141         A is a matrix of size n*p
    00142         we add x times the column j to the column i
    00143
    00144 ------------------------------------------------------------------------*/
    00145
    00146 static void colonne(Value *a,int i,int j,Value x,int n,int p) {
    00147
    00148   int k;
    00149   Value *c1,*c2;
    00150
    00151   c1=a+(i-1);
    00152   c2=a+(j-1);
    00153
    00154   for(k=1;k<=n;k++) {
    00155     value_addmul(*c1, x, *c2);
    00156     c1=c1+p;
    00157     c2=c2+p;
    00158   }
    00159   return;
    00160 } /* colonne */
    00161
    00162 /*----------------------------------------------------------------------
    00163         trouve le numero de colonne du plus petit element non nul de
    00164         la ligne q, d'indice superieur a q, de la matrice A,  mais
    00165         renvoie zero si tous les elements sont nuls sauf le qieme.
    00166
    00167         find the column number (greater than q) of the smallest non
    00168         null element of row q . it returns
    00169         0 if all the last elements of row q are null except the qth
    00170
    00171 ----------------------------------------------------------------------*/
    00172
    00173 static int petit_l(Value *a,int n,int p,int q) {
    00174
    00175   int numero=0, k, tousnuls;
    00176   Value minus, comp;
    00177   Value *c;
    00178
    00179   value_init(minus); value_init(comp);
    00180   c=a+(q-1)*p+(p-1);
    00181   tousnuls=1;
    00182   for(k=p;k>q;k--) {
    00183     value_absolute(comp,*c);
    00184     if (value_notzero_p(comp)) {
    00185       if (tousnuls==1) {
    00186         value_assign(minus,comp);
    00187         numero=k;
    00188         tousnuls=0;
    00189       }
    00190       else if (value_ge(minus,comp)) {
    00191         value_assign(minus,comp);
    00192         numero=k;
    00193       }
    00194     }
    00195     c--;
    00196   }
    00197   if (tousnuls==1) {
    00198     value_clear(minus); value_clear(comp);
    00199     return(0);
    00200   }
    00201   else  {
    00202     value_absolute(comp,*c);
    00203     if ((value_notzero_p(comp))&&(value_ge(minus,comp))) {
    00204       value_clear(minus); value_clear(comp);
    00205       return(q);
    00206     }
    00207     else {
    00208       value_clear(minus); value_clear(comp);
    00209       return(numero);
    00210     }
    00211   }
    00212 } /* petit_l */
    00213
    00214 /*----------------------------------------------------------------------
    00215         trouve le numero de ligne du plus petit element non nul de
    00216         la colonne q, d'indice superieur a q, de la matrice A,  mais
    00217         renvoie zero si tous les elements sont nuls sauf le qieme.
    00218
    00219         find the row number (greater than q) of the smallest non
    00220         null element of column q . it returns
    00221         0 if all the last elements of column q are null except the qth
    00222
    00223 ----------------------------------------------------------------------*/
    00224
    00225 static int petit_c(Value *a,int n,int p,int q) {
    00226
    00227   int numero=0, k, tousnuls;
    00228   Value minus, comp;
    00229   Value *c;
    00230
    00231   value_init(minus); value_init(comp);
    00232   c = a+q-1+p*(n-1);
    00233   tousnuls=1;
    00234   for(k=n;k>q;k--) {
    00235     value_absolute(comp,*c);
    00236     if (value_notzero_p(comp)) {
    00237       if (tousnuls==1) {
    00238         value_assign(minus,comp);
    00239         numero=k;
    00240         tousnuls=0;
    00241       }
    00242       else if (value_ge(minus,comp)) {
    00243         value_assign(minus,comp);
    00244         numero=k;
    00245       }
    00246     }
    00247     c=c-p;
    00248   }
    00249
    00250   if (tousnuls==1) {
    00251     value_clear(minus); value_clear(comp);
    00252     return(0);
    00253   }
    00254   else {
    00255     value_absolute(comp,*c);
    00256     if ((value_notzero_p(comp)) && (value_ge(minus,comp))) {
    00257       value_clear(minus); value_clear(comp);
    00258       return(q);
    00259     }
    00260     else {
    00261       value_clear(minus); value_clear(comp);
    00262       return(numero);
    00263     }
    00264   }
    00265 } /* petit_c */
    00266
    00267 /*-----------------------------------------------------------------------
    00268         A est initialisee a une matrice "identite" de taille n*p
    00269         A is initialized to an "identity" matrix of size n*p
    00270 -----------------------------------------------------------------------*/
    00271
    00272 static void identite(Value *a,int n,int p) {
    00273
    00274   int i,j;
    00275   Value *b;
    00276
    00277   b = a;
    00278   for(i=1;i<=n;i++) {
    00279     for(j=1;j<=p;j++) {
    00280       if (i==j)
    00281         value_set_si(*b,1);
    00282       else
    00283         value_set_si(*b,0);
    00284       b++;
    00285     }
    00286   }
    00287   return;
    00288 } /* identite */
    00289
    00290 /*-----------------------------------------------------------------------
    00291   transpose la sous-matrice de A dont les indices sont
    00292   superieurs ou egaux a q
    00293   transposition of the sub-matrix of A composed of the elements
    00294   whose indices are greater or equal to q
    00295 -----------------------------------------------------------------------*/
    00296
    00297 static void transpose(Value *a,int n,int q) {
    00298
    00299   int i;
    00300   Value val;
    00301   Value *b,*c;
    00302
    00303   value_init(val);
    00304   if (q<n) {
    00305     b=a+(q-1)+(q-1)*n;
    00306     c=b;
    00307     for(i=q+1;i<=n;i++) {
    00308       b++;
    00309       c=c+n;
    00310       value_assign(val,*b);
    00311       value_assign(*b,*c);
    00312       value_assign(*c,val);
    00313     }
    00314     transpose(a,n,q+1);
    00315   }
    00316   value_clear(val);
    00317   return;
    00318 } /* transpose */
    00319
    00320 /*----------------------------------------------------------------------
    00321         trouve le numero de colonne du premier element non divisible
    00322         par val dans la sous-matrice d'indices > q mais renvoie 0 sinon
    00323
    00324         find the column number of the first non-divisible by val element
    00325         in the sub-matrix of a composed of the elements of indices >q.
    00326         Return 0 is there is no such element
    00327 ----------------------------------------------------------------------*/
    00328
    00329 static int encore(Value *a,int n,int p,int q,Value val) {
    00330
    00331   int k,l;
    00332   Value comp, tmp;
    00333   Value *c;
    00334
    00335   if ((q>=n)||(q>=p)) return(0);
    00336
    00337   value_init(comp); value_init(tmp);
    00338   c=a+q*p+q;
    00339   k=q+1;
    00340   l=q+1;
    00341   while (k<=n) {
    00342     value_absolute(comp,*c);
    00343     if (value_zero_p(val)) {
    00344       if (value_notzero_p(comp)) {
    00345         value_clear(comp);
    00346         value_clear(tmp);
    00347         return(l);
    00348       }
    00349     }
    00350     else {
    00351       value_modulus(tmp,comp,val);
    00352       if (value_notzero_p(tmp)) {
    00353         value_clear(comp);
    00354         value_clear(tmp);
    00355         return(l);
    00356       }
    00357     }
    00358     if (l==p) {
    00359       k=k+1;
    00360       l=q+1;
    00361       c=c+q+1;
    00362     }
    00363     else {
    00364       l++;
    00365       c++;
    00366     }
    00367   }
    00368   value_clear(comp);
    00369   value_clear(tmp);
    00370   return(0);
    00371 } /* encore */
    00372
    00373 /*----------------------------------------------------------------------
    00374         transforme la matrice A (de taille n*p), a partir de la position
    00375         q*q en sa forme de smith, les matrices b et c subissant les memes
    00376         transformations respectivement sur les lignes et colonnes
    00377
    00378         transform the matrix A (size n*p), from position (q,q) into
    00379         its smith normal form. the same transformations are applied to
    00380         matrices b and c, respectively on rows and on columns
    00381 ----------------------------------------------------------------------*/
    00382
    00383 static void smith(Value *a,Value *b,Value *c,Value *b_inverse,Value *c_inverse,int n,int p,int q) {
    00384
    00385   int i,k,fini;
    00386   Value x, pivot, tmp, x_inv;
    00387   Value *f;
    00388
    00389   value_init(pivot); value_init(tmp);
    00390   value_init(x); value_init(x_inv);
    00391
    00392   if ((q<=n)&&(q<=p)) {
    00393     fini = 1;
    00394
    00395     while (fini!=0) {
    00396       i=petit_c(a,n,p,q);
    00397       while (i!=0) {
    00398         if (i!=q) {
    00399           echange_l(a,i,q,n,p);
    00400           echange_l(b,i,q,n,n);
    00401           echange_c(b_inverse,i,q,n,n);
    00402         }
    00403         f=a+(q-1)+(q-1)*p;
    00404         value_assign(pivot,*f);
    00405         if (value_neg_p(pivot)) {
    00406           moins_l(a,q,n,p);
    00407           moins_l(b,q,n,n);
    00408           moins_c(b_inverse,q,n,n);
    00409           value_oppose(pivot,pivot);
    00410         }
    00411         for(k=q+1;k<=n;k++) {
    00412           f=f+p;
    00413           if (value_notzero_p(*f)) {
    00414             value_division(x,*f,pivot);
    00415             value_modulus(tmp,*f,pivot);
    00416             if (value_neg_p(tmp))
    00417               value_decrement(x,x);
    00418             value_oppose(x_inv,x);
    00419             ligne(a,k,q,x_inv,n,p);
    00420             ligne(b,k,q,x_inv,n,n);
    00421             colonne(b_inverse,q,k,x,n,n);
    00422           }
    00423         }
    00424         i=petit_c(a,n,p,q);
    00425       }
    00426       fini=0;
    00427       i=petit_l(a,n,p,q);
    00428       while (i!=0) {
    00429         if (i!=q) {
    00430           echange_c(a,i,q,n,p);
    00431           echange_c(c,i,q,p,p);
    00432           echange_l(c_inverse,i,q,p,p);
    00433           fini=1;
    00434         }
    00435         f=a+(q-1)+(q-1)*p;
    00436         value_assign(pivot,*f);
    00437         if (value_neg_p(pivot)) {
    00438           moins_c(a,q,n,p);
    00439           moins_c(c,q,p,p);
    00440           moins_l(c_inverse,q,p,p);
    00441           value_oppose(pivot,pivot);
    00442         }
    00443         for(k=q+1;k<=p;k++) {
    00444           f++;
    00445           if (value_notzero_p(*f)) {
    00446             value_division(x,*f,pivot);
    00447             value_modulus(tmp,*f,pivot);
    00448             if (value_neg_p(tmp))
    00449               value_decrement(x,x);
    00450             value_oppose(x_inv,x);
    00451             colonne(a,k,q,x_inv,n,p);
    00452             colonne(c,k,q,x_inv,p,p);
    00453             ligne(c_inverse,q,k,x,p,p);
    00454           }
    00455         }
    00456         i=petit_l(a,n,p,q);
    00457       }
    00458     }
    00459     value_assign(pivot,*(a+(q-1)+(q-1)*p));
    00460     if (value_neg_p(pivot)) {
    00461       moins_l(a,q,n,p);
    00462       moins_l(b,q,n,n);
    00463       moins_c(b_inverse,q,n,n);
    00464       value_oppose(pivot,pivot);
    00465     }
    00466
    00467     i=encore(a,n,p,q,pivot);
    00468     if (i!=0) {
    00469       value_set_si(x,1);
    00470       value_set_si(x_inv,-1);
    00471       colonne(a,q,i,x,n,p);
    00472       colonne(c,q,i,x,p,p);
    00473       ligne(c_inverse,i,q,x_inv,p,p);
    00474       smith(a,b,c,b_inverse,c_inverse,n,p,q);
    00475     }
    00476     else smith(a,b,c,b_inverse,c_inverse,n,p,q+1);
    00477   }
    00478   value_clear(pivot); value_clear(tmp);
    00479   value_clear(x); value_clear(x_inv);
    00480
    00481   return;
    00482 } /* smith */
    00483
    00484 /*----------------------------------------------------------------------
    00485         decompose la matrice A en le produit d'une matrice B
    00486         unimodulaire et d'une matrice triangulaire superieure
    00487         D est l'inverse de B
    00488         Decompose the matrix A in the product of a matrix B unimodular
    00489         and a matrix upper triangular, D is the inverse of B
    00490 ----------------------------------------------------------------------*/
    00491
    00492 static void hermite(Value *a,Value *b,Value *d,int n,int p,int q) {
    00493
    00494   int i,k;
    00495   Value x, pivot, x_inv, tmp;
    00496   Value *c1;
    00497
    00498   value_init(pivot);  value_init(tmp);
    00499   value_init(x); value_init(x_inv);
    00500
    00501   if ((q<=p)&&(q<=n)) {
    00502     i=petit_c(a,n,p,q);
    00503     while (i!=0) {
    00504       if (i!=q) {
    00505         echange_l(a,i,q,n,p);
    00506         echange_c(b,i,q,n,n);
    00507         echange_l(d,i,q,n,n);
    00508       }
    00509
    00510       c1=a+(q-1)+(q-1)*p;
    00511       value_assign(pivot,*c1);
    00512       if (value_neg_p(pivot)) {
    00513         moins_l(a,q,n,p);
    00514         moins_l(d,q,n,n);
    00515         moins_c(b,q,n,n);
    00516         value_oppose(pivot,pivot);
    00517       }
    00518       for(k=q+1;k<=n;k++) {
    00519         c1=c1+p;
    00520         if (value_notzero_p(*c1)) {
    00521           value_division(x,*c1,pivot);
    00522           value_modulus(tmp,*c1,pivot);
    00523           if (value_neg_p(tmp))
    00524             value_decrement(x,x);
    00525           value_oppose(x_inv,x);
    00526           ligne(a,k,q,x_inv,n,p);
    00527           colonne(b,q,k,x,n,n);
    00528           ligne(d,k,q,x_inv,n,n);
    00529         }
    00530       }
    00531       i=petit_c(a,n,p,q);
    00532     }
    00533     c1=a+(q-1);
    00534     value_assign(pivot,*(c1+(q-1)*p));
    00535     if (value_neg_p(pivot)) {
    00536       moins_l(a,q,n,p);
    00537       moins_l(d,q,n,n);
    00538       moins_c(b,q,n,n);
    00539       value_oppose(pivot,pivot);
    00540     }
    00541     if (value_notzero_p(pivot)) {
    00542       for(k=1;k<q;k++) {
    00543         if (value_notzero_p(*c1)) {
    00544           value_division(x,*c1,pivot);
    00545           value_modulus(tmp,*c1,pivot);
    00546           if (value_neg_p(tmp))
    00547             value_decrement(x,x);
    00548           value_oppose(x_inv,x);
    00549           ligne(a,k,q,x_inv,n,p);
    00550           colonne(b,q,k,x,n,n);
    00551           ligne(d,k,q,x_inv,n,n);
    00552         }
    00553         c1=c1+p;
    00554       }
    00555     }
    00556     hermite(a,b,d,n,p,q+1);
    00557   }
    00558   value_clear(pivot); value_clear(tmp);
    00559   value_clear(x); value_clear(x_inv);
    00560   return;
    00561 } /* hermite */
    00562
    00563 /*----------------------------------------------------------------------
    00564   B est une g_base de dimension n dont les p premiers vecteurs
    00565   colonnes sont colineaires aux vecteurs colonnes de A
    00566   C est l'invers de B
    00567
    00568   B is an integral (g_base ?) of dimension n whose p first columns
    00569   vectors are proportionnal to the column vectors of A. C is the
    00570   inverse of B.
    00571   ----------------------------------------------------------------------*/
    00572
    00573 /** Convert PolmattoDarmat :
    00574 ***  This function converts the matrix of a Polylib to a int * as necessary
    00575 ***    for the functions in Darte's implementation.
    00576 ***
    00577 ***  Input  : A Polylib Matrix ( a pointer to it );
    00578 ***  Output : An int * with the matrix copied into it
    00579 **/
    00580 static Value *ConvertPolMattoDarMat(Matrix *A ) {
    00581
    00582   int i,j;
    00583   Value *result;
    00584
    00585   result = (Value *)malloc(sizeof(Value) * A->NbRows * A->NbColumns);
    00586   for(i=0;i<A->NbRows * A->NbColumns;i++)
    00587     value_init(result[i]);
    00588
    00589   for (i = 0; i < A->NbRows; i++)
    00590     for (j = 0 ;  j < A->NbColumns; j++)
    00591       value_assign(result[i*A->NbColumns + j],A->p[i][j]);
    00592   return result;
    00593 } /* ConvertPolMattoDarMat */
    00594
    00595 /** Convert DarmattoPolmat
    00596 ***   This function converts the matrix from Darte representation to a matrix
    00597 ***    in PolyLib.
    00598 ***
    00599 ***   Input  : The matrix (a pointer to it),  number of Rows, number of columns
    00600 ***   Output : The matrix of the PolyLib
    00601 ***
    00602 **/
    00603
    00604 static Matrix *ConvertDarMattoPolMat (Value *A, int NbRows, int NbCols) {
    00605
    00606   int i,j;
    00607   Matrix *result;
    00608
    00609   result = Matrix_Alloc(NbRows, NbCols);
    00610
    00611   for (i = 0; i < NbRows; i ++)
    00612     for (j = 0; j < NbCols; j ++)
    00613       value_assign(result->p[i][j],A[i*NbCols + j]);
    00614   return result;
    00615 } /* ConvertDarMattoPolMat */
    00616
    00617 /**
    00618 *** Smith : This function takes a Matrix A of dim n * l as its input
    00619 ***         and returns the three matrices U, V and Product such that
    00620 ***         A = U * Product * V, where U is an unimodular matrix of dimension
    00621 ***         n * n and V is an unimodular matrix of dimension l * l.
    00622 ***         Product is a diagonal matrix of dimension n * l.
    00623 ***
    00624 ***         We use Alan Darte's implementation of Smith for computing
    00625 ***         the Smith Normal Form
    00626 **/
    00627 void Smith(Matrix *A, Matrix **U, Matrix **V, Matrix **Product)
    00628 {
    00629   int i;
    00630   Matrix *u, *v;
    00631
    00632   u = Identity(A->NbRows);
    00633   v = Identity(A->NbColumns);
    00634
    00635   *U = Identity(A->NbRows);
    00636   *V = Identity(A->NbColumns);
    00637
    00638   *Product = Matrix_Copy(A);
    00639   smith((*Product)->p_Init, u->p_Init, v->p_Init, (*U)->p_Init, (*V)->p_Init,
    00640         A->NbRows, A->NbColumns, 1);
    00641
    00642   Matrix_Free(u);
    00643   Matrix_Free(v);
    00644 } /* Smith */
    00645
    00646 /** Hermite :
    00647 ***   This function takes a Matrix as its input and finds its HNF
    00648 ***    ( Left form )
    00649 ***
    00650 ***   Input  : A Matrix A (The Matrix A is not necessarily a Polylib matrix.
    00651 ***             It is just a matrix as far as Hermite is concerned. It
    00652 ***             does not even check if the matrix is a Polylib matrix or not)
    00653 ***   Output : The Hnf matrix H and the Unimodular matrix U such that
    00654 ***               A = H * U.
    00655 ***
    00656 ***   We use Alan Darte's implementation of Hermite to compute the HNF.
    00657 ***   Alan Darte's implementation computes the Upper Triangular HNF.
    00658 ***   So We work on the fact that if A = H * U then
    00659 ***       A (transpose) = U(transpose) * H (transpose)
    00660 ***       There are a set of interface functions written in Interface.c
    00661 ***        which convert a matrix from Polylib representationt to that of
    00662 ***        Alan Darte's and vice versa.
    00663 ***
    00664 ***   This Function Does the Following
    00665 ***    Step 1 : Given the matrix A it finds its Transpose.
    00666 ***    Step 2 : Finds the HNF (Right Form) using Alan Darte's Algorithm.
    00667 ***    Step 3 : The H1 and U1 obtained in Step2 are both Transposed to get
    00668 ***              the actual H and U such that A = HU.
    00669 **/
    00670 void Hermite (Matrix *A, Matrix **H, Matrix **U) {
    00671
    00672   int i;
    00673   Matrix *transpose, *tempH, *tempU ;
    00674   Value *darte_matA, *darte_identite, *darte_id_inv;
    00675
    00676   transpose = Transpose(A);
    00677   darte_matA = ConvertPolMattoDarMat(transpose);
    00678
    00679   darte_identite = (Value *)malloc(sizeof(Value) * A->NbColumns* A->NbColumns);
    00680   darte_id_inv = (Value *) malloc(sizeof(Value) * A->NbColumns*A->NbColumns);
    00681   for (i=0; i< A->NbColumns * A->NbColumns; i++)
    00682     value_init(darte_identite[i]);
    00683   for (i=0; i< A->NbColumns * A->NbColumns; i++)
    00684     value_init(darte_id_inv[i]);
    00685
    00686   identite(darte_identite, transpose->NbRows, transpose->NbRows);
    00687   identite(darte_id_inv, transpose->NbRows, transpose->NbRows);
    00688   hermite(darte_matA, darte_identite, darte_id_inv,A->NbColumns,A->NbRows, 1);
    00689   Matrix_Free (transpose);
    00690   transpose = ConvertDarMattoPolMat(darte_matA, A->NbColumns, A->NbRows);
    00691   tempU = ConvertDarMattoPolMat(darte_identite, A->NbColumns, A->NbColumns);
    00692
    00693   /* Finding H Transpose */
    00694   tempH = Transpose(transpose);
    00695   Matrix_Free(transpose);
    00696
    00697   /* Finding U Transpose */
    00698   transpose = Transpose(tempU);
    00699
    00700   H[0] = Matrix_Copy(tempH);
    00701   U[0] = Matrix_Copy(transpose);
    00702
    00703   Matrix_Free (tempH);
    00704   Matrix_Free (transpose);
    00705   Matrix_Free (tempU);
    00706
    00707   for (i=0; i< A->NbRows * A->NbColumns; i++)
    00708     value_clear(darte_matA[i]);
    00709   for (i=0; i< A->NbColumns * A->NbColumns; i++)
    00710     value_clear(darte_identite[i]);
    00711   for (i=0; i< A->NbColumns * A->NbColumns; i++)
    00712     value_clear(darte_id_inv[i]);
    00713   free (darte_matA);
    00714   free (darte_identite);
    00715   free (darte_id_inv);
    00716   return;
    00717 } /* Hermite */
    00718
    00719