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

Matop.c

Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <polylib/polylib.h>
00003 
00004 /* computes c = lcm(a,b) using Gcd(a,b,&c) */
00005 void Lcm3(Value a, Value b, Value *c)
00006 {
00007   Value tmp;
00008 
00009   if (value_zero_p(a)) {
00010     value_assign(*c, b);
00011     return;
00012   }
00013   if (value_zero_p(b)) {
00014     value_assign(*c, a);
00015     return;
00016   }
00017   value_init(tmp);
00018   value_multiply(tmp, a, b);
00019   value_absolute(tmp, tmp);
00020   Gcd(a,b,c);
00021   value_division(*c, tmp, *c);
00022   value_clear(tmp);
00023 }
00024 
00025 /*
00026  * Return the lcm of 'i' and 'j' 
00027  */ 
00028 Value *Lcm (Value i, Value j)
00029 {
00030   Value *tmp;
00031   
00032   tmp = (Value *) malloc (sizeof(Value));
00033   value_init(*tmp);
00034   Lcm3(i, j, tmp);
00035   return tmp;
00036 } /* Lcm */
00037 
00038 /* 
00039  * Return an identity matrix of size 'size'. 
00040  */
00041 Matrix *Identity(unsigned size)
00042 {
00043   unsigned i;
00044   Matrix *A;
00045   
00046   A = Matrix_Alloc(size, size);
00047   for (i = 0; i < size; i++)  
00048     value_set_si(A->p[i][i], 1);
00049   return A;
00050 } /* Identity */
00051 
00052 /*
00053  * Exchange the rows 'Row1' and 'Row2' of the matrix 'M'
00054  */
00055 void ExchangeRows(Matrix *M, int Row1, int Row2) {
00056   
00057   int i;
00058   Value temp;
00059   
00060   value_init(temp);
00061   for (i = 0; i < (int)M->NbColumns;  i++) {
00062     value_assign(temp,M->p[Row1][i]);
00063     value_assign(M->p[Row1][i],M->p[Row2][i]);
00064     value_assign(M->p[Row2][i],temp);
00065   }  
00066   value_clear(temp);
00067   return ;
00068 } /* ExchangeRows */
00069 
00070 /*
00071  * Exchange the columns 'Column1' and 'Column2' of the matrix 'M'
00072  */
00073 void ExchangeColumns(Matrix *M, int Column1, int Column2) {
00074   
00075   int i;
00076   
00077   for (i = 0; i < M->NbRows; i++)
00078     value_swap(M->p[i][Column1],M->p[i][Column2]);
00079 
00080   return;
00081 } /* ExchangeColumns */
00082 
00083 /* 
00084  * Return the Transpose of a matrix 'A' 
00085  */
00086 Matrix *Transpose (Matrix *A) {
00087   
00088   int i,j;
00089   Matrix *transpose;
00090   
00091   transpose = Matrix_Alloc (A->NbColumns, A->NbRows);
00092   for (i = 0; i < (int)A->NbRows; i++)
00093     for (j = 0; j < (int)A->NbColumns; j++)
00094       value_assign(transpose->p[j][i],A->p[i][j]);
00095   return transpose;
00096 } /* Transpose */
00097 
00098 /*
00099  * Return a copy of the contents of a matrix 'Src'.
00100  */
00101 Matrix *Matrix_Copy(Matrix const *Src )
00102 {
00103   Matrix *Dst;
00104   unsigned i, j;
00105   
00106   Dst = Matrix_Alloc(Src->NbRows, Src->NbColumns);
00107   
00108   for (i = 0; i < Src->NbRows; i++)
00109     for (j = 0; j < Src->NbColumns; j++)
00110       value_assign(Dst->p[i][j],Src->p[i][j]);
00111   return Dst;
00112 } /* Matrix_copy */
00113 
00114 /* 
00115  * Test if the input matrix is integral or not. 
00116  */
00117 Bool isIntegral (Matrix *A) {
00118   
00119   unsigned i, j;
00120   Value divisor, tmp;
00121   
00122   value_init(divisor); value_init(tmp);
00123   value_assign(divisor,A->p[A->NbRows-1][A->NbColumns-1]);
00124 
00125   for (i = 0; i < A->NbRows ; i++)
00126     for (j = 0; j < A->NbColumns ; j++) {
00127       value_modulus(tmp,A->p[i][j],divisor);
00128       if (value_notzero_p(tmp)) {
00129         value_clear(divisor); value_clear(tmp);
00130           return False;  
00131       }   
00132     }
00133   value_clear(divisor); value_clear(tmp);
00134   return True ;
00135 } /* isIntegral */
00136 
00137 /*
00138  * Check if the matrix 'A' is in Hermite normal form or not. 
00139  */
00140 Bool isinHnf(Matrix *A) {
00141  
00142   Matrix *temp ;
00143   unsigned i, j ;
00144   Value rem;
00145   
00146   value_init(rem); 
00147   temp = Homogenise(A,True) ;
00148   for (i = 0; i < temp->NbRows; i++) {
00149     value_assign(rem,temp->p[i][i]);
00150     for (j = 0; j < i ; j++)
00151       if (value_ge(temp->p[i][j],rem)) {
00152         Matrix_Free(temp);
00153         value_clear(rem);
00154         return False ;
00155       }
00156     for (j = i+1; j < temp->NbColumns ; j++)
00157       if (value_notzero_p(temp->p[i][j])) {
00158         Matrix_Free(temp);
00159         value_clear(rem);
00160         return False ;
00161       }
00162   }
00163   Matrix_Free(temp);
00164   value_clear(rem);
00165   return True ;
00166 } /* isinHnf */
00167 
00168 /*
00169  * Remove the row 'Rownumber' and place it at the end of the matrix 'X'  
00170  */ 
00171 void PutRowLast (Matrix *X, int Rownumber) {
00172   
00173   int i, j ;
00174   Value temp;
00175  
00176   if (Rownumber == X->NbRows-1)
00177     return;
00178   
00179   value_init(temp);
00180   for (j = 0; j < X->NbColumns; j++) {
00181     value_assign(temp,X->p[Rownumber][j]);
00182     for (i = Rownumber; i < X->NbRows-1; i++)
00183       value_assign(X->p[i][j],X->p[i+1][j]);
00184     value_assign(X->p[i][j],temp);
00185   }
00186   value_clear(temp);
00187   return;
00188 } /* PutRowLast */
00189 
00190 /* 
00191  * Remove the row 'Rownumber' and place it at the begining of the matrix 'X' 
00192  */ 
00193 void PutRowFirst(Matrix *X, int Rownumber) {
00194   
00195   int i, j ;
00196   Value temp;
00197 
00198   value_init(temp);
00199   for (j = 0; j < X->NbColumns; j++) {
00200     value_assign(temp,X->p[Rownumber][j]);
00201     for (i = Rownumber; i > 0; i--)
00202       value_assign(X->p[i][j],X->p[i-1][j]);
00203     value_assign(X->p[i][j],temp);
00204   }
00205   value_clear(temp);
00206   return;
00207 } /* PutRowFirst */
00208 
00209 /*
00210  * Remove the column 'Columnnumber' and place it at the begining of the matrix
00211  * 'X'
00212  */
00213 void PutColumnFirst (Matrix *X, int Columnnumber) {
00214   
00215   int i, j ;
00216   Value temp;
00217 
00218   value_init(temp);
00219   for (i = 0; i < X->NbRows; i ++) {
00220     value_assign(temp,X->p[i][Columnnumber]);
00221     for (j = Columnnumber; j > 0; j --)
00222       value_assign(X->p[i][j],X->p[i][j-1]);
00223     value_assign(X->p[i][0],temp);
00224   }
00225   value_clear(temp);
00226   return ;
00227 } /* PutColumnFirst */
00228 
00229 /*
00230  * Remove the column 'Columnnumber' and place it at the end of the matrix 'X'
00231  */
00232 void PutColumnLast (Matrix *X, int Columnnumber) {
00233   
00234   int i, j ;
00235   Value temp;
00236 
00237   value_init(temp);
00238   for (i = 0; i < X->NbRows; i++) {
00239     value_assign(temp,X->p[i][Columnnumber]);
00240     for (j = Columnnumber; j < X->NbColumns-1; j++)
00241       value_assign(X->p[i][j],X->p[i][j+1]);
00242     value_assign(X->p[i][X->NbColumns-1],temp);
00243   }
00244   value_clear(temp);
00245   return ;
00246 } /* PutColumnLast */
00247 
00248 /*
00249  * Add a row of zeros at the end of the matrix 'M' and return the new matrix 
00250  */
00251 Matrix *AddANullRow (Matrix *M) {
00252   
00253   int i,j;
00254   Matrix *Result;
00255   
00256   Result = Matrix_Alloc(M->NbRows+1,M->NbColumns);
00257   for (i = 0;i < M->NbRows; i++)
00258     for (j = 0; j < M->NbColumns ; j++)
00259       value_assign(Result->p[i][j],M->p[i][j]);
00260   for (j = 0; j < M->NbColumns; j++)
00261     value_set_si(Result->p[i][j],0);  
00262   return Result;
00263 } /* AddANullRow */
00264 
00265 /* 
00266  * Add a column of zeros at the end of the matrix 'M' and return the new 
00267  * matrix
00268  */   
00269 Matrix *AddANullColumn(Matrix *M) {
00270   
00271   int i,j;
00272   Matrix *Result;
00273   
00274   Result = Matrix_Alloc(M->NbRows, M->NbColumns+1);
00275   for (i = 0;i < M->NbRows; i++)
00276     for (j = 0; j < M->NbColumns ; j++)
00277       value_assign(Result->p[i][j],M->p[i][j]);
00278   for (i = 0; i < M->NbRows; i++)
00279     value_set_si(Result->p[i][M->NbColumns],0);
00280   return Result;
00281 } /* AddANullColumn */
00282 
00283 /*
00284  * Remove a row 'Rownumber' from matrix 'M' and return the new matrix.
00285  */
00286 Matrix *RemoveRow(Matrix *M, int Rownumber) {
00287   
00288   Matrix *Result;
00289   int i;
00290   
00291   Result = Matrix_Alloc(M->NbRows-1, M->NbColumns);
00292   
00293   for (i = 0; i < Rownumber; i++)
00294     Vector_Copy(M->p[i], Result->p[i], M->NbColumns);
00295   for ( ; i < Result->NbRows; i++)
00296     Vector_Copy(M->p[i+1], Result->p[i], M->NbColumns);
00297 
00298   return Result;
00299 } /* RemoveRow */
00300 
00301 /*
00302  * Remove NumColumns columns starting at column number 'FirstColumnnumber' from matrix 'M'
00303  * and return the new matrix.
00304  */
00305 Matrix *RemoveNColumns (Matrix *M, int FirstColumnnumber, int NumColumns) {
00306   
00307   Matrix *Result;
00308   int i;
00309   
00310   Result = Matrix_Alloc (M->NbRows, M->NbColumns-NumColumns);
00311   
00312   for (i = 0; i < Result->NbRows; i++) {
00313     Vector_Copy(M->p[i], Result->p[i], FirstColumnnumber);
00314     Vector_Copy(M->p[i]+FirstColumnnumber+NumColumns, Result->p[i]+FirstColumnnumber, 
00315                 M->NbColumns-NumColumns-FirstColumnnumber);
00316   }
00317   return Result;
00318 } /* RemoveColumn */
00319 
00320 /*
00321  * Remove a column 'Columnnumber' from matrix 'M' and return the new matrix.
00322  */
00323 Matrix *RemoveColumn (Matrix *M, int Columnnumber) {
00324   
00325   Matrix *Result;
00326   int i;
00327   
00328   Result = Matrix_Alloc (M->NbRows, M->NbColumns-1);
00329   
00330   for (i = 0; i < Result->NbRows; i++) {
00331     Vector_Copy(M->p[i], Result->p[i], Columnnumber);
00332     Vector_Copy(M->p[i]+Columnnumber+1, Result->p[i]+Columnnumber, 
00333                 M->NbColumns-1-Columnnumber);
00334   }
00335   return Result;
00336 } /* RemoveColumn */
00337 
00338 /* 
00339  * Given a Matrix M of dimesnion n * l and rank l1, find a unimodular matrix
00340  * 'Result' such that the Vector Space spanned by M is the subset of the vector
00341  * Space spanned by the first l1 Rows of Result. The function returns the rank
00342  * l1 and the Matrix Result.  
00343  */
00344 int findHermiteBasis(Matrix *M, Matrix **Result) {
00345   
00346   int i, j;
00347   Matrix *C, *curMat, *temp1, *temp2;
00348   Matrix *H, *U;
00349   Vector *V;
00350   int dim, curDim, curVect,rank;
00351   
00352   if (M->NbRows == 0) {
00353     Result[0] = Identity (M->NbColumns);
00354     return 0;
00355   }
00356   
00357   if (M->NbRows <= M->NbColumns) {
00358     Hermite(M, &H, &U);
00359     
00360     for (i = 0; i < H->NbRows; i++)
00361       if (value_zero_p(H->p[i][i]))
00362         break;
00363     
00364     if (i == H->NbRows) {
00365       Result[0] = Transpose(U);
00366       Matrix_Free(H);
00367       Matrix_Free(U);
00368       return(i);
00369     }
00370     Matrix_Free (H);
00371     Matrix_Free (U);
00372   } 
00373   
00374   /* Eliminating the Zero Rows  */
00375   
00376   C = Matrix_Copy (M);
00377   for (i = 0; i < C->NbRows; i++) {
00378     for (j = 0; j < C->NbColumns; j++)
00379       if (value_notzero_p(C->p[i][j]))
00380         break;
00381     if (j == C->NbColumns) {
00382       Matrix *temp;
00383       temp = RemoveRow(C, i); 
00384       Matrix_Free(C);
00385       C = Matrix_Copy(temp);
00386       Matrix_Free(temp);
00387       i --;
00388     }
00389   }
00390   
00391   /* Eliminating the Redundant Rows */
00392   
00393   curDim = 1;
00394   curVect = 1;
00395   dim = C->NbColumns;
00396   
00397   curMat = Matrix_Alloc(1,C->NbColumns);
00398   for (i = 0; i < C->NbColumns; i ++)
00399     value_assign(curMat->p[0][i],C->p[0][i]); 
00400   
00401   while((curVect < C->NbRows) && (curDim < dim)) {
00402     Matrix *temp;
00403     temp = AddANullRow(curMat);
00404     for (i = 0; i < C->NbColumns; i++)
00405       value_assign(temp->p[temp->NbRows-1][i],C->p[curVect][i]);
00406     
00407     temp1 = AddANullRow(temp);
00408     temp2 = AddANullColumn(temp1);
00409     rank = SolveDiophantine(temp2, &U, &V);
00410     if (rank == temp->NbRows) {
00411       Matrix_Free(curMat);
00412       curMat = Matrix_Copy(temp);
00413       curDim ++;
00414     }    
00415     curVect ++;    
00416     Matrix_Free (U);
00417     Vector_Free (V);
00418     Matrix_Free (temp1);
00419     Matrix_Free (temp);
00420     Matrix_Free (temp2);
00421   }
00422   Matrix_Free(C);
00423   
00424   Hermite(curMat, &H, &U);
00425   rank = curMat->NbRows;
00426   Matrix_Free(curMat);
00427   
00428   Result[0] = Transpose (U);
00429   Matrix_Free (H);
00430   Matrix_Free (U);
00431   return (rank);
00432 } /* findHermiteBasis */
00433 
00434 
00435 
00436 

Generated on Mon Apr 23 19:23:52 2007 for polylib by doxygen 1.3.5