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, 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 }
00054
00055
00056
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 }
00072
00073
00074
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 }
00090
00091
00092
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 }
00105
00106
00107
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 }
00121
00122
00123
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 }
00144
00145
00146
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 }
00174
00175
00176
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 }
00196
00197
00198
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 }
00215
00216
00217
00218
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 }
00235
00236
00237
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 }
00254
00255
00256
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 }
00271
00272
00273
00274
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 }
00289
00290
00291
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 }
00307
00308
00309
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 }
00325
00326
00327
00328
00329
00330
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
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
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 }
00421
00422
00423
00424