2 #include <polylib/polylib.h>
4 /* computes c = lcm(a,b) using Gcd(a,b,&c) */
5 void Lcm3(Value a
, Value b
, Value
*c
)
13 if (value_zero_p(b
)) {
18 value_multiply(tmp
, a
, b
);
19 value_absolute(tmp
, tmp
);
21 value_division(*c
, tmp
, *c
);
26 * Return the lcm of 'i' and 'j'
28 Value
*Lcm (Value i
, Value j
)
32 tmp
= (Value
*) malloc (sizeof(Value
));
39 * Return an identity matrix of size 'size'.
41 Matrix
*Identity(unsigned size
)
46 A
= Matrix_Alloc(size
, size
);
47 for (i
= 0; i
< size
; i
++)
48 value_set_si(A
->p
[i
][i
], 1);
53 * Exchange the rows 'Row1' and 'Row2' of the matrix 'M'
55 void ExchangeRows(Matrix
*M
, int Row1
, int Row2
) {
61 for (i
= 0; i
< (int)M
->NbColumns
; i
++) {
62 value_assign(temp
,M
->p
[Row1
][i
]);
63 value_assign(M
->p
[Row1
][i
],M
->p
[Row2
][i
]);
64 value_assign(M
->p
[Row2
][i
],temp
);
71 * Exchange the columns 'Column1' and 'Column2' of the matrix 'M'
73 void ExchangeColumns(Matrix
*M
, int Column1
, int Column2
) {
77 for (i
= 0; i
< M
->NbRows
; i
++)
78 value_swap(M
->p
[i
][Column1
],M
->p
[i
][Column2
]);
81 } /* ExchangeColumns */
84 * Return the Transpose of a matrix 'A'
86 Matrix
*Transpose (Matrix
*A
) {
91 transpose
= Matrix_Alloc (A
->NbColumns
, A
->NbRows
);
92 for (i
= 0; i
< (int)A
->NbRows
; i
++)
93 for (j
= 0; j
< (int)A
->NbColumns
; j
++)
94 value_assign(transpose
->p
[j
][i
],A
->p
[i
][j
]);
99 * Return a copy of the contents of a matrix 'Src'.
101 Matrix
*Matrix_Copy(Matrix
const *Src
)
106 Dst
= Matrix_Alloc(Src
->NbRows
, Src
->NbColumns
);
108 for (i
= 0; i
< Src
->NbRows
; i
++)
109 for (j
= 0; j
< Src
->NbColumns
; j
++)
110 value_assign(Dst
->p
[i
][j
],Src
->p
[i
][j
]);
115 * Test if the input matrix is integral or not.
117 Bool
isIntegral (Matrix
*A
) {
122 value_init(divisor
); value_init(tmp
);
123 value_assign(divisor
,A
->p
[A
->NbRows
-1][A
->NbColumns
-1]);
125 for (i
= 0; i
< A
->NbRows
; i
++)
126 for (j
= 0; j
< A
->NbColumns
; j
++) {
127 value_modulus(tmp
,A
->p
[i
][j
],divisor
);
128 if (value_notzero_p(tmp
)) {
129 value_clear(divisor
); value_clear(tmp
);
133 value_clear(divisor
); value_clear(tmp
);
138 * Check if the matrix 'A' is in Hermite normal form or not.
140 Bool
isinHnf(Matrix
*A
) {
147 temp
= Homogenise(A
,True
) ;
148 for (i
= 0; i
< temp
->NbRows
; i
++) {
149 value_assign(rem
,temp
->p
[i
][i
]);
150 for (j
= 0; j
< i
; j
++)
151 if (value_ge(temp
->p
[i
][j
],rem
)) {
156 for (j
= i
+1; j
< temp
->NbColumns
; j
++)
157 if (value_notzero_p(temp
->p
[i
][j
])) {
169 * Remove the row 'Rownumber' and place it at the end of the matrix 'X'
171 void PutRowLast (Matrix
*X
, int Rownumber
) {
176 if (Rownumber
== X
->NbRows
-1)
180 for (j
= 0; j
< X
->NbColumns
; j
++) {
181 value_assign(temp
,X
->p
[Rownumber
][j
]);
182 for (i
= Rownumber
; i
< X
->NbRows
-1; i
++)
183 value_assign(X
->p
[i
][j
],X
->p
[i
+1][j
]);
184 value_assign(X
->p
[i
][j
],temp
);
191 * Remove the row 'Rownumber' and place it at the begining of the matrix 'X'
193 void PutRowFirst(Matrix
*X
, int Rownumber
) {
199 for (j
= 0; j
< X
->NbColumns
; j
++) {
200 value_assign(temp
,X
->p
[Rownumber
][j
]);
201 for (i
= Rownumber
; i
> 0; i
--)
202 value_assign(X
->p
[i
][j
],X
->p
[i
-1][j
]);
203 value_assign(X
->p
[i
][j
],temp
);
210 * Remove the column 'Columnnumber' and place it at the begining of the matrix
213 void PutColumnFirst (Matrix
*X
, int Columnnumber
) {
219 for (i
= 0; i
< X
->NbRows
; i
++) {
220 value_assign(temp
,X
->p
[i
][Columnnumber
]);
221 for (j
= Columnnumber
; j
> 0; j
--)
222 value_assign(X
->p
[i
][j
],X
->p
[i
][j
-1]);
223 value_assign(X
->p
[i
][0],temp
);
227 } /* PutColumnFirst */
230 * Remove the column 'Columnnumber' and place it at the end of the matrix 'X'
232 void PutColumnLast (Matrix
*X
, int Columnnumber
) {
238 for (i
= 0; i
< X
->NbRows
; i
++) {
239 value_assign(temp
,X
->p
[i
][Columnnumber
]);
240 for (j
= Columnnumber
; j
< X
->NbColumns
-1; j
++)
241 value_assign(X
->p
[i
][j
],X
->p
[i
][j
+1]);
242 value_assign(X
->p
[i
][X
->NbColumns
-1],temp
);
246 } /* PutColumnLast */
249 * Add a row of zeros at the end of the matrix 'M' and return the new matrix
251 Matrix
*AddANullRow (Matrix
*M
) {
256 Result
= Matrix_Alloc(M
->NbRows
+1,M
->NbColumns
);
257 for (i
= 0;i
< M
->NbRows
; i
++)
258 for (j
= 0; j
< M
->NbColumns
; j
++)
259 value_assign(Result
->p
[i
][j
],M
->p
[i
][j
]);
260 for (j
= 0; j
< M
->NbColumns
; j
++)
261 value_set_si(Result
->p
[i
][j
],0);
266 * Add a column of zeros at the end of the matrix 'M' and return the new
269 Matrix
*AddANullColumn(Matrix
*M
) {
274 Result
= Matrix_Alloc(M
->NbRows
, M
->NbColumns
+1);
275 for (i
= 0;i
< M
->NbRows
; i
++)
276 for (j
= 0; j
< M
->NbColumns
; j
++)
277 value_assign(Result
->p
[i
][j
],M
->p
[i
][j
]);
278 for (i
= 0; i
< M
->NbRows
; i
++)
279 value_set_si(Result
->p
[i
][M
->NbColumns
],0);
281 } /* AddANullColumn */
284 * Remove a row 'Rownumber' from matrix 'M' and return the new matrix.
286 Matrix
*RemoveRow(Matrix
*M
, int Rownumber
) {
291 Result
= Matrix_Alloc(M
->NbRows
-1, M
->NbColumns
);
293 for (i
= 0; i
< Rownumber
; i
++)
294 Vector_Copy(M
->p
[i
], Result
->p
[i
], M
->NbColumns
);
295 for ( ; i
< Result
->NbRows
; i
++)
296 Vector_Copy(M
->p
[i
+1], Result
->p
[i
], M
->NbColumns
);
302 * Remove NumColumns columns starting at column number 'FirstColumnnumber' from matrix 'M'
303 * and return the new matrix.
305 Matrix
*RemoveNColumns (Matrix
*M
, int FirstColumnnumber
, int NumColumns
) {
310 Result
= Matrix_Alloc (M
->NbRows
, M
->NbColumns
-NumColumns
);
312 for (i
= 0; i
< Result
->NbRows
; i
++) {
313 Vector_Copy(M
->p
[i
], Result
->p
[i
], FirstColumnnumber
);
314 Vector_Copy(M
->p
[i
]+FirstColumnnumber
+NumColumns
, Result
->p
[i
]+FirstColumnnumber
,
315 M
->NbColumns
-NumColumns
-FirstColumnnumber
);
321 * Remove a column 'Columnnumber' from matrix 'M' and return the new matrix.
323 Matrix
*RemoveColumn (Matrix
*M
, int Columnnumber
) {
328 Result
= Matrix_Alloc (M
->NbRows
, M
->NbColumns
-1);
330 for (i
= 0; i
< Result
->NbRows
; i
++) {
331 Vector_Copy(M
->p
[i
], Result
->p
[i
], Columnnumber
);
332 Vector_Copy(M
->p
[i
]+Columnnumber
+1, Result
->p
[i
]+Columnnumber
,
333 M
->NbColumns
-1-Columnnumber
);
339 * Given a Matrix M of dimesnion n * l and rank l1, find a unimodular matrix
340 * 'Result' such that the Vector Space spanned by M is the subset of the vector
341 * Space spanned by the first l1 Rows of Result. The function returns the rank
342 * l1 and the Matrix Result.
344 int findHermiteBasis(Matrix
*M
, Matrix
**Result
) {
347 Matrix
*C
, *curMat
, *temp1
, *temp2
;
350 int dim
, curDim
, curVect
,rank
;
352 if (M
->NbRows
== 0) {
353 Result
[0] = Identity (M
->NbColumns
);
357 if (M
->NbRows
<= M
->NbColumns
) {
360 for (i
= 0; i
< H
->NbRows
; i
++)
361 if (value_zero_p(H
->p
[i
][i
]))
364 if (i
== H
->NbRows
) {
365 Result
[0] = Transpose(U
);
374 /* Eliminating the Zero Rows */
377 for (i
= 0; i
< C
->NbRows
; i
++) {
378 for (j
= 0; j
< C
->NbColumns
; j
++)
379 if (value_notzero_p(C
->p
[i
][j
]))
381 if (j
== C
->NbColumns
) {
383 temp
= RemoveRow(C
, i
);
385 C
= Matrix_Copy(temp
);
391 /* Eliminating the Redundant Rows */
397 curMat
= Matrix_Alloc(1,C
->NbColumns
);
398 for (i
= 0; i
< C
->NbColumns
; i
++)
399 value_assign(curMat
->p
[0][i
],C
->p
[0][i
]);
401 while((curVect
< C
->NbRows
) && (curDim
< dim
)) {
403 temp
= AddANullRow(curMat
);
404 for (i
= 0; i
< C
->NbColumns
; i
++)
405 value_assign(temp
->p
[temp
->NbRows
-1][i
],C
->p
[curVect
][i
]);
407 temp1
= AddANullRow(temp
);
408 temp2
= AddANullColumn(temp1
);
409 rank
= SolveDiophantine(temp2
, &U
, &V
);
410 if (rank
== temp
->NbRows
) {
412 curMat
= Matrix_Copy(temp
);
424 Hermite(curMat
, &H
, &U
);
425 rank
= curMat
->NbRows
;
428 Result
[0] = Transpose (U
);
432 } /* findHermiteBasis */