Main Page | Class List | File List | Class Members | File Members

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   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 } /* ligne */
00124 
00125 /*------------------------------------------------------------------------
00126         A est une matrice de taille n*p
00127         on ajoute a la colonne i, x fois la colonne j
00128         A is a matrix of size n*p
00129         we add x times the column j to the column i
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 } /* colonne */
00152         
00153 /*----------------------------------------------------------------------
00154         trouve le numero de colonne du plus petit element non nul de 
00155         la ligne q, d'indice superieur a q, de la matrice A,  mais
00156         renvoie zero si tous les elements sont nuls sauf le qieme.
00157 
00158         find the column number (greater than q) of the smallest non
00159         null element of row q . it returns 
00160         0 if all the last elements of row q are null except the qth
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 } /* petit_l */ 
00204         
00205 /*----------------------------------------------------------------------
00206         trouve le numero de ligne du plus petit element non nul de 
00207         la colonne q, d'indice superieur a q, de la matrice A,  mais
00208         renvoie zero si tous les elements sont nuls sauf le qieme.
00209 
00210         find the row number (greater than q) of the smallest non
00211         null element of column q . it returns 
00212         0 if all the last elements of column q are null except the qth
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 } /* petit_c */
00257         
00258 /*-----------------------------------------------------------------------
00259         A est initialisee a une matrice "identite" de taille n*p
00260         A is initialized to an "identity" matrix of size n*p
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 } /* identite */
00280 
00281 /*-----------------------------------------------------------------------
00282   transpose la sous-matrice de A dont les indices sont
00283   superieurs ou egaux a q
00284   transposition of the sub-matrix of A composed of the elements 
00285   whose indices are greater or equal to q
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 } /* transpose */
00310 
00311 /*----------------------------------------------------------------------
00312         trouve le numero de colonne du premier element non divisible 
00313         par val dans la sous-matrice d'indices > q mais renvoie 0 sinon
00314         
00315         find the column number of the first non-divisible by val element
00316         in the sub-matrix of a composed of the elements of indices >q.
00317         Return 0 is there is no such element
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 } /* encore */
00363 
00364 /*----------------------------------------------------------------------
00365         transforme la matrice A (de taille n*p), a partir de la position 
00366         q*q en sa forme de smith, les matrices b et c subissant les memes 
00367         transformations respectivement sur les lignes et colonnes
00368 
00369         transform the matrix A (size n*p), from position (q,q) into 
00370         its smith normal form. the same transformations are applied to 
00371         matrices b and c, respectively on rows and on columns
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 } /* smith */ 
00474 
00475 /*----------------------------------------------------------------------
00476         decompose la matrice A en le produit d'une matrice B
00477         unimodulaire et d'une matrice triangulaire superieure
00478         D est l'inverse de B
00479         Decompose the matrix A in the product of a matrix B unimodular
00480         and a matrix upper triangular, D is the inverse of B
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 } /* hermite */
00553         
00554 /*----------------------------------------------------------------------
00555   B est une g_base de dimension n dont les p premiers vecteurs
00556   colonnes sont colineaires aux vecteurs colonnes de A
00557   C est l'invers de B
00558   
00559   B is an integral (g_base ?) of dimension n whose p first columns
00560   vectors are proportionnal to the column vectors of A. C is the
00561   inverse of B.
00562   ----------------------------------------------------------------------*/
00563 
00564 /** Convert PolmattoDarmat :
00565 ***  This function converts the matrix of a Polylib to a int * as necessary
00566 ***    for the functions in Darte's implementation.
00567 ***
00568 ***  Input  : A Polylib Matrix ( a pointer to it );
00569 ***  Output : An int * with the matrix copied into it
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 } /* ConvertPolMattoDarMat */
00585 
00586 /** Convert DarmattoPolmat
00587 ***   This function converts the matrix from Darte representation to a matrix
00588 ***    in PolyLib.
00589 ***
00590 ***   Input  : The matrix (a pointer to it),  number of Rows, number of columns
00591 ***   Output : The matrix of the PolyLib 
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 } /* ConvertDarMattoPolMat */
00607 
00608 /**
00609 *** Smith : This function takes a Matrix A of dim n * l as its input 
00610 ***         and returns the three matrices U, V and Product such that
00611 ***         A = U * Product * V, where U is an unimodular matrix of dimension
00612 ***         n * n and V is an unimodular matrix of dimension l * l.
00613 ***         Product is a diagonal matrix of dimension n * l.
00614 ***     
00615 ***         We use Alan Darte's implementation of Smith for computing
00616 ***         the Smith Normal Form 
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 } /* Smith */
00670 
00671 /** Hermite :
00672 ***   This function takes a Matrix as its input and finds its HNF 
00673 ***    ( Left form )
00674 ***
00675 ***   Input  : A Matrix A (The Matrix A is not necessarily a Polylib matrix.
00676 ***             It is just a matrix as far as Hermite is concerned. It
00677 ***             does not even check if the matrix is a Polylib matrix or not) 
00678 ***   Output : The Hnf matrix H and the Unimodular matrix U such that
00679 ***               A = H * U.
00680 ***
00681 ***   We use Alan Darte's implementation of Hermite to compute the HNF.
00682 ***   Alan Darte's implementation computes the Upper Triangular HNF.
00683 ***   So We work on the fact that if A = H * U then 
00684 ***       A (transpose) = U(transpose) * H (transpose)
00685 ***       There are a set of interface functions written in Interface.c
00686 ***        which convert a matrix from Polylib representationt to that of
00687 ***        Alan Darte's and vice versa.
00688 ***     
00689 ***   This Function Does the Following
00690 ***    Step 1 : Given the matrix A it finds its Transpose.
00691 ***    Step 2 : Finds the HNF (Right Form) using Alan Darte's Algorithm.
00692 ***    Step 3 : The H1 and U1 obtained in Step2 are both Transposed to get
00693 ***              the actual H and U such that A = HU.
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   /* Finding H Transpose */
00719   tempH = Transpose(transpose);  
00720   Matrix_Free(transpose);
00721   
00722   /* Finding U Transpose */
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 } /* Hermite */
00741 
00742 

Generated on Mon Sep 12 14:48:29 2005 for polylib by doxygen 1.3.5