polylib: Matop.c Source File

- Main Page
- Classes
- Files

# 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