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

Generated on Mon Sep 12 15:15:11 2005 for polylib by doxygen 1.3.5