00001 #include <stdlib.h>
00002 #include <polylib/polylib.h>
00003
00004
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
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 }
00037
00038
00039
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 }
00051
00052
00053
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 }
00069
00070
00071
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 }
00082
00083
00084
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 }
00097
00098
00099
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 }
00113
00114
00115
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 }
00136
00137
00138
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 }
00167
00168
00169
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 }
00189
00190
00191
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 }
00208
00209
00210
00211
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 }
00228
00229
00230
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 }
00247
00248
00249
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 }
00264
00265
00266
00267
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 }
00282
00283
00284
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 }
00300
00301
00302
00303
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 }
00319
00320
00321
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 }
00337
00338
00339
00340
00341
00342
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
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
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 }
00433
00434
00435
00436