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 /*
00005  * Return the lcm of 'i' and 'j' 
00006  */ 
00007 Value *Lcm (Value i, Value j) {
00008   
00009   Value *tmp;
00010   Value aux;
00011   
00012   tmp = (Value *) malloc (sizeof(Value));
00013   value_init(aux); value_init(*tmp);
00014   Gcd(i,j,tmp);
00015   value_multiply(aux,i,j);
00016   value_division(*tmp,aux,*tmp);
00017   value_clear(aux);
00018   return tmp;
00019 } /* Lcm */
00020 
00021 /* 
00022  * Return an identity matrix of size 'size'. 
00023  */
00024 Matrix *Identity (unsigned size) {
00025   
00026   unsigned i, j;
00027   Matrix *A;
00028   
00029   A = Matrix_Alloc(size, size);
00030   for (i = 0;i < size; i ++)
00031     for (j = 0; j < size; j ++)
00032       value_set_si(A->p[i][j],0);
00033   for (i =0; i < size; i ++)  
00034     value_set_si(A->p[i][i],1);
00035   return A;
00036 } /* Identity */
00037 
00038 /*
00039  * Exchange the rows 'Row1' and 'Row2' of the matrix 'M'
00040  */
00041 void ExchangeRows(Matrix *M, int Row1, int Row2) {
00042   
00043   int i;
00044   Value *temp;
00045   
00046   temp = (Value *) malloc (sizeof(Value) * M->NbColumns);
00047   
00048   for (i = 0 ;i < (int)M->NbColumns; i++) {
00049     value_init(temp[i]);
00050     value_assign(temp[i],M->p[Row1][i]);
00051   }
00052   for (i = 0; i < (int)M->NbColumns;  i++) {
00053     value_assign(M->p[Row1][i],M->p[Row2][i]);
00054     value_assign(M->p[Row2][i],temp[i]);
00055     value_clear(temp[i]);
00056   }  
00057   free (temp);
00058   return ;
00059 } /* ExchangeRows */
00060 
00061 /*
00062  * Exchange the columns 'Column1' and 'Column2' of the matrix 'M'
00063  */
00064 void ExchangeColumns(Matrix *M, int Column1, int Column2) {
00065   
00066   int i;
00067   Value *temp;
00068   
00069   temp = (Value *) malloc(sizeof(Value) * M->NbRows);
00070   for (i = 0 ;i < (int) M->NbRows; i++) {
00071     value_init(temp[i]);
00072     value_assign(temp[i],M->p[i][Column1]);
00073   } 
00074   for (i = 0; i < (int)M->NbRows; i++) {
00075       value_assign(M->p[i][Column1],M->p[i][Column2]);
00076       value_assign(M->p[i][Column2],temp[i]);
00077       value_clear(temp[i]);
00078     }
00079   free (temp);
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 *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   value_clear(rem);
00164   return True ;
00165 } /* isinHnf */
00166 
00167 /*
00168  * Remove the row 'Rownumber' and place it at the end of the matrix 'X'  
00169  */ 
00170 void PutRowLast (Matrix *X, int Rownumber) {
00171   
00172   int i, j ;
00173   Value *vector;
00174  
00175   if (Rownumber == X->NbRows-1)
00176     return;
00177   vector = (Value *) malloc (sizeof(Value) * X->NbColumns); 
00178   
00179   for (i = 0; i < X->NbColumns; i++) {
00180     value_init(vector[i]);
00181     value_assign(vector[i],X->p[Rownumber][i]);
00182   }    
00183   for (i = Rownumber; i < X->NbRows-1; i++)
00184     for (j = 0; j < X->NbColumns; j++)
00185       value_assign(X->p[i][j],X->p[i+1][j]);
00186   
00187   for (j = 0; j < X->NbColumns ; j++) {
00188     value_assign(X->p[i][j],vector[j]);
00189     value_clear(vector[j]);
00190   }    
00191   free (vector);
00192   return;
00193 } /* PutRowLast */
00194 
00195 /* 
00196  * Remove the row 'Rownumber' and place it at the begining of the matrix 'X' 
00197  */ 
00198 void PutRowFirst(Matrix *X, int Rownumber) {
00199   
00200   int i, j ;
00201   Value *vector;
00202 
00203   vector = (Value *) malloc (sizeof(Value) * X->NbColumns); 
00204   
00205   for (i = 0; i < X->NbColumns; i++) {
00206     value_init(vector[i]);
00207     value_assign(vector[i],X->p[Rownumber][i]);
00208   }  
00209   for (i = Rownumber; i > 0; i--)
00210     for (j = 0; j < X->NbColumns; j++)
00211       value_assign(X->p[i][j],X->p[i-1][j]);
00212   
00213   for (j = 0; j < X->NbColumns ; j++) {
00214     value_assign(X->p[i][j],vector[j]);
00215     value_clear(vector[j]);
00216   } 
00217   free(vector);
00218   return;
00219 } /* PutRowFirst */
00220 
00221 /*
00222  * Remove the column 'Columnnumber' and place it at the begining of the matrix
00223  * 'X'
00224  */
00225 void PutColumnFirst (Matrix *X, int Columnnumber) {
00226   
00227   int i, j ;
00228   Value *vector;
00229 
00230   vector = (Value *)malloc(sizeof (Value) * X->NbRows); 
00231   
00232   for (i = 0; i < X->NbRows; i++) {
00233     value_init(vector[i]);
00234     value_assign(vector[i],X->p[i][Columnnumber]);
00235   }
00236   
00237   for (i = 0; i < X->NbRows; i ++)
00238     for (j = Columnnumber; j > 0; j --)
00239       value_assign(X->p[i][j],X->p[i][j-1]);
00240   
00241   for (i = 0; i < X->NbRows ; i ++) {
00242     value_assign(X->p[i][0],vector[i]);
00243     value_clear(vector[i]);
00244   }    
00245   free (vector);
00246   return ;
00247 } /* PutColumnFirst */
00248 
00249 /*
00250  * Remove the column 'Columnnumber' and place it at the end of the matrix 'X'
00251  */
00252 void PutColumnLast (Matrix *X, int Columnnumber) {
00253   
00254   int i, j ;
00255   Value *vector;
00256 
00257   vector = (Value *) malloc (sizeof (Value) * X->NbRows); 
00258   
00259   for (i = 0; i < X->NbRows; i++) {
00260     value_init(vector[i]);
00261     value_assign(vector[i],X->p[i][Columnnumber]);
00262   }    
00263   
00264   for (i = 0; i < X->NbRows; i++)
00265     for (j = Columnnumber; j < X->NbColumns-1; j++)
00266       value_assign(X->p[i][j],X->p[i][j+1]);
00267   
00268   for (i = 0; i < X->NbRows ; i++) {
00269     value_assign(X->p[i][X->NbColumns-1],vector[i]);
00270     value_clear(vector[i]);
00271   }  
00272   free (vector);
00273   return ;
00274 } /* PutColumnLast */
00275 
00276 /*
00277  * Add a row of zeros at the end of the matrix 'M' and return the new matrix 
00278  */
00279 Matrix *AddANullRow (Matrix *M) {
00280   
00281   int i,j;
00282   Matrix *Result;
00283   
00284   Result = Matrix_Alloc(M->NbRows+1,M->NbColumns);
00285   for (i = 0;i < M->NbRows; i++)
00286     for (j = 0; j < M->NbColumns ; j++)
00287       value_assign(Result->p[i][j],M->p[i][j]);
00288   for (j = 0; j < M->NbColumns; j++)
00289     value_set_si(Result->p[i][j],0);  
00290   return Result;
00291 } /* AddANullRow */
00292 
00293 /* 
00294  * Add a column of zeros at the end of the matrix 'M' and return the new 
00295  * matrix
00296  */   
00297 Matrix *AddANullColumn(Matrix *M) {
00298   
00299   int i,j;
00300   Matrix *Result;
00301   
00302   Result = Matrix_Alloc(M->NbRows, M->NbColumns+1);
00303   for (i = 0;i < M->NbRows; i++)
00304     for (j = 0; j < M->NbColumns ; j++)
00305       value_assign(Result->p[i][j],M->p[i][j]);
00306   for (i = 0; i < M->NbRows; i++)
00307     value_set_si(Result->p[i][M->NbColumns],0);
00308   return Result;
00309 } /* AddANullColumn */
00310 
00311 /*
00312  * Remove a row 'Rownumber' from matrix 'M' and return the new matrix.
00313  */
00314 Matrix *RemoveRow(Matrix *M, int Rownumber) {
00315   
00316   Matrix *temp, *Result;
00317   int i,j;
00318   
00319   temp = Matrix_Copy (M);
00320   PutRowLast(temp, Rownumber); 
00321   Result = Matrix_Alloc(temp->NbRows-1, temp->NbColumns);
00322   
00323   for (i = 0; i < Result->NbRows; i ++)
00324     for (j = 0; j < Result->NbColumns; j ++)
00325       value_assign(Result->p[i][j],temp->p[i][j]);   
00326   return Result;
00327 } /* RemoveRow */
00328 
00329 /*
00330  * Remove a column 'Columnnumber' from matrix 'M' and return the new matrix.
00331  */
00332 Matrix *RemoveColumn (Matrix *M, int Columnnumber) {
00333   
00334   Matrix *temp, *Result;
00335   int i,j;
00336   
00337   temp = Matrix_Copy(M);
00338   PutColumnLast(temp,Columnnumber); 
00339   Result = Matrix_Alloc (temp->NbRows, temp->NbColumns-1);
00340   
00341   for (i = 0; i < Result->NbRows; i ++)
00342     for (j = 0; j < Result->NbColumns; j ++)
00343       value_assign(Result->p[i][j],temp->p[i][j]);   
00344   return Result;
00345 } /* RemoveColumn */
00346 
00347 /* 
00348  * Given a Matrix M of dimesnion n * l and rank l1, find a unimodular matrix
00349  * 'Result' such that the Vector Space spanned by M is the subset of the vector
00350  * Space spanned by the first l1 Rows of Result. The function returns the rank
00351  * l1 and the Matrix Result.  
00352  */
00353 int findHermiteBasis(Matrix *M, Matrix **Result) {
00354   
00355   int i, j;
00356   Matrix *C, *curMat, *temp1, *temp2;
00357   Matrix *H, *U;
00358   Vector *V;
00359   int dim, curDim, curVect,rank;
00360   
00361   if (M->NbRows == 0) {
00362     Result[0] = Identity (M->NbColumns);
00363     return 0;
00364   }
00365   
00366   if (M->NbRows <= M->NbColumns) {
00367     Hermite(M, &H, &U);
00368     
00369     for (i = 0; i < H->NbRows; i++)
00370       if (value_zero_p(H->p[i][i]))
00371         break;
00372     
00373     if (i == H->NbRows) {
00374       Result[0] = Transpose(U);
00375       Matrix_Free(H);
00376       Matrix_Free(U);
00377       return(i);
00378     }
00379     Matrix_Free (H);
00380     Matrix_Free (U);
00381   } 
00382   
00383   /* Eliminating the Zero Rows  */
00384   
00385   C = Matrix_Copy (M);
00386   for (i = 0; i < C->NbRows; i++) {
00387     for (j = 0; j < C->NbColumns; j++)
00388       if (value_notzero_p(C->p[i][j]))
00389         break;
00390     if (j == C->NbColumns) {
00391       Matrix *temp;
00392       temp = RemoveRow(C, i); 
00393       Matrix_Free(C);
00394       C = Matrix_Copy(temp);
00395       Matrix_Free(temp);
00396       i --;
00397     }
00398   }
00399   
00400   /* Eliminating the Redundant Rows */
00401   
00402   curDim = 1;
00403   curVect = 1;
00404   dim = C->NbColumns;
00405   
00406   curMat = Matrix_Alloc(1,C->NbColumns);
00407   for (i = 0; i < C->NbColumns; i ++)
00408     value_assign(curMat->p[0][i],C->p[0][i]); 
00409   
00410   while((curVect < C->NbRows) && (curDim < dim)) {
00411     Matrix *temp;
00412     temp = AddANullRow(curMat);
00413     for (i = 0; i < C->NbColumns; i++)
00414       value_assign(temp->p[temp->NbRows-1][i],C->p[curVect][i]);
00415     
00416     temp1 = AddANullRow(temp);
00417     temp2 = AddANullColumn(temp1);
00418     rank = SolveDiophantine(temp2, &U, &V);
00419     if (rank == temp->NbRows) {
00420       Matrix_Free(curMat);
00421       curMat = Matrix_Copy(temp);
00422       curDim ++;
00423     }    
00424     curVect ++;    
00425     Matrix_Free (U);
00426     Vector_Free (V);
00427     Matrix_Free (temp1);
00428     Matrix_Free (temp);
00429     Matrix_Free (temp2);
00430   }
00431   
00432   Hermite(curMat, &H, &U);
00433   rank = curMat->NbRows;
00434   
00435   Result[0] = Transpose (U);
00436   Matrix_Free (H);
00437   Matrix_Free (U);
00438   return (rank);
00439 } /* findHermiteBasis */
00440 
00441 
00442 
00443 

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