polylib: Matop.c Source File

- Main Page
- Classes
- Files

- File List
- File Members

# Matop.c

Go to the documentation of this file.

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