polylib: NormalForms.c Source File

- Main Page
- Classes
- Files

# NormalForms.c

Go to the documentation of this file.

    00001 #include <stdlib.h>
    00002 #include <polylib/polylib.h>
    00003
    00004 /* nota bene: on stocke les matrices par lignes */
    00005 /* nota bene: matrices are stored in row major order */
    00006
    00007 /*------------------------------------------------------------------------
    00008         change les signes de la ligne i de la matrice A
    00009         change the sign of row i of matrix A
    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 } /* moins_l */
    00025
    00026 /*------------------------------------------------------------------------
    00027         change les signes de la colonne i de la matrice A
    00028         change the sign of column i of matrix A
    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 } /* moins_c */
    00044
    00045 /*------------------------------------------------------------------------
    00046         echange les lignes i et j de la matrice A
    00047         exchange row i and j of matrix A
    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 } /* echange_l */
    00070
    00071 /*------------------------------------------------------------------------
    00072         echange les colonnes i et j de la matrice A
    00073         exchange columns i and j of matrix A
    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 } /* echange_c */
    00096
    00097 /*------------------------------------------------------------------------
    00098         A est une matrice de taille n*p
    00099         on ajoute a la ligne i, x fois la ligne j
    00100         A is a matrix of size n*p
    00101         we add x times the row j to the row i
    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 } /* ligne */
    00120
    00121 /*------------------------------------------------------------------------
    00122         A est une matrice de taille n*p
    00123         on ajoute a la colonne i, x fois la colonne j
    00124         A is a matrix of size n*p
    00125         we add x times the column j to the column i
    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 } /* colonne */
    00144
    00145 /*----------------------------------------------------------------------
    00146         trouve le numero de colonne du plus petit element non nul de
    00147         la ligne q, d'indice superieur a q, de la matrice A,  mais
    00148         renvoie zero si tous les elements sont nuls sauf le qieme.
    00149
    00150         find the column number (greater than q) of the smallest non
    00151         null element of row q . it returns
    00152         0 if all the last elements of row q are null except the qth
    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 } /* petit_l */
    00196
    00197 /*----------------------------------------------------------------------
    00198         trouve le numero de ligne du plus petit element non nul de
    00199         la colonne q, d'indice superieur a q, de la matrice A,  mais
    00200         renvoie zero si tous les elements sont nuls sauf le qieme.
    00201
    00202         find the row number (greater than q) of the smallest non
    00203         null element of column q . it returns
    00204         0 if all the last elements of column q are null except the qth
    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 } /* petit_c */
    00249
    00250 /*-----------------------------------------------------------------------
    00251         A est initialisee a une matrice "identite" de taille n*p
    00252         A is initialized to an "identity" matrix of size n*p
    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 } /* identite */
    00272
    00273 /*-----------------------------------------------------------------------
    00274   transpose la sous-matrice de A dont les indices sont
    00275   superieurs ou egaux a q
    00276   transposition of the sub-matrix of A composed of the elements
    00277   whose indices are greater or equal to q
    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 } /* transpose */
    00302
    00303 /*----------------------------------------------------------------------
    00304         trouve le numero de colonne du premier element non divisible
    00305         par val dans la sous-matrice d'indices > q mais renvoie 0 sinon
    00306
    00307         find the column number of the first non-divisible by val element
    00308         in the sub-matrix of a composed of the elements of indices >q.
    00309         Return 0 is there is no such element
    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 } /* encore */
    00355
    00356 /*----------------------------------------------------------------------
    00357         transforme la matrice A (de taille n*p), a partir de la position
    00358         q*q en sa forme de smith, les matrices b et c subissant les memes
    00359         transformations respectivement sur les lignes et colonnes
    00360
    00361         transform the matrix A (size n*p), from position (q,q) into
    00362         its smith normal form. the same transformations are applied to
    00363         matrices b and c, respectively on rows and on columns
    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 } /* smith */
    00466
    00467 /*----------------------------------------------------------------------
    00468         decompose la matrice A en le produit d'une matrice B
    00469         unimodulaire et d'une matrice triangulaire superieure
    00470         D est l'inverse de B
    00471         Decompose the matrix A in the product of a matrix B unimodular
    00472         and a matrix upper triangular, D is the inverse of B
    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 } /* hermite */
    00545
    00546 /*----------------------------------------------------------------------
    00547   B est une g_base de dimension n dont les p premiers vecteurs
    00548   colonnes sont colineaires aux vecteurs colonnes de A
    00549   C est l'invers de B
    00550
    00551   B is an integral (g_base ?) of dimension n whose p first columns
    00552   vectors are proportionnal to the column vectors of A. C is the
    00553   inverse of B.
    00554   ----------------------------------------------------------------------*/
    00555
    00556 /** Convert PolmattoDarmat :
    00557 ***  This function converts the matrix of a Polylib to a int * as necessary
    00558 ***    for the functions in Darte's implementation.
    00559 ***
    00560 ***  Input  : A Polylib Matrix ( a pointer to it );
    00561 ***  Output : An int * with the matrix copied into it
    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 } /* ConvertPolMattoDarMat */
    00577
    00578 /** Convert DarmattoPolmat
    00579 ***   This function converts the matrix from Darte representation to a matrix
    00580 ***    in PolyLib.
    00581 ***
    00582 ***   Input  : The matrix (a pointer to it),  number of Rows, number of columns
    00583 ***   Output : The matrix of the PolyLib
    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 } /* ConvertDarMattoPolMat */
    00599
    00600 /**
    00601 *** Smith : This function takes a Matrix A of dim n * l as its input
    00602 ***         and returns the three matrices U, V and Product such that
    00603 ***         A = U * Product * V, where U is an unimodular matrix of dimension
    00604 ***         n * n and V is an unimodular matrix of dimension l * l.
    00605 ***         Product is a diagonal matrix of dimension n * l.
    00606 ***
    00607 ***         We use Alan Darte's implementation of Smith for computing
    00608 ***         the Smith Normal Form
    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 } /* Smith */
    00628
    00629 /** Hermite :
    00630 ***   This function takes a Matrix as its input and finds its HNF
    00631 ***    ( Left form )
    00632 ***
    00633 ***   Input  : A Matrix A (The Matrix A is not necessarily a Polylib matrix.
    00634 ***             It is just a matrix as far as Hermite is concerned. It
    00635 ***             does not even check if the matrix is a Polylib matrix or not)
    00636 ***   Output : The Hnf matrix H and the Unimodular matrix U such that
    00637 ***               A = H * U.
    00638 ***
    00639 ***   We use Alan Darte's implementation of Hermite to compute the HNF.
    00640 ***   Alan Darte's implementation computes the Upper Triangular HNF.
    00641 ***   So We work on the fact that if A = H * U then
    00642 ***       A (transpose) = U(transpose) * H (transpose)
    00643 ***       There are a set of interface functions written in Interface.c
    00644 ***        which convert a matrix from Polylib representationt to that of
    00645 ***        Alan Darte's and vice versa.
    00646 ***
    00647 ***   This Function Does the Following
    00648 ***    Step 1 : Given the matrix A it finds its Transpose.
    00649 ***    Step 2 : Finds the HNF (Right Form) using Alan Darte's Algorithm.
    00650 ***    Step 3 : The H1 and U1 obtained in Step2 are both Transposed to get
    00651 ***              the actual H and U such that A = HU.
    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   /* Finding H Transpose */
    00677   tempH = Transpose(transpose);
    00678   Matrix_Free(transpose);
    00679
    00680   /* Finding U Transpose */
    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 } /* Hermite */
    00701
    00702