polylib 5.22.8
Matop.c
Go to the documentation of this file.
1#include <polylib/polylib.h>
2#include <stdlib.h>
3
4/* computes c = lcm(a,b) using Gcd(a,b,&c) */
5void Lcm3(Value a, Value b, Value *c) {
6 Value tmp;
7
8 if (value_zero_p(a)) {
9 value_assign(*c, b);
10 return;
11 }
12 if (value_zero_p(b)) {
13 value_assign(*c, a);
14 return;
15 }
16 value_init(tmp);
17 value_multiply(tmp, a, b);
18 value_absolute(tmp, tmp);
19 Gcd(a, b, c);
20 value_division(*c, tmp, *c);
21 value_clear(tmp);
22}
23
24/*
25 * Return the lcm of 'i' and 'j'
26 */
27Value *Lcm(Value i, Value j) {
28 Value *tmp;
29
30 tmp = (Value *)malloc(sizeof(Value));
31 value_init(*tmp);
32 Lcm3(i, j, tmp);
33 return tmp;
34} /* Lcm */
35
36/*
37 * Return an identity matrix of size 'size'.
38 */
39Matrix *Identity(unsigned size) {
40 unsigned i;
41 Matrix *A;
42
43 A = Matrix_Alloc(size, size);
44 for (i = 0; i < size; i++)
45 value_set_si(A->p[i][i], 1);
46 return A;
47} /* Identity */
48
49/*
50 * Exchange the rows 'Row1' and 'Row2' of the matrix 'M'
51 */
52void ExchangeRows(Matrix *M, int Row1, int Row2) {
53
54 int i;
55 Value temp;
56
57 value_init(temp);
58 for (i = 0; i < (int)M->NbColumns; i++) {
59 value_assign(temp, M->p[Row1][i]);
60 value_assign(M->p[Row1][i], M->p[Row2][i]);
61 value_assign(M->p[Row2][i], temp);
62 }
63 value_clear(temp);
64 return;
65} /* ExchangeRows */
66
67/*
68 * Exchange the columns 'Column1' and 'Column2' of the matrix 'M'
69 */
70void ExchangeColumns(Matrix *M, int Column1, int Column2) {
71
72 int i;
73
74 for (i = 0; i < M->NbRows; i++)
75 value_swap(M->p[i][Column1], M->p[i][Column2]);
76
77 return;
78} /* ExchangeColumns */
79
80/*
81 * Return the Transpose of a matrix 'A'
82 */
84
85 int i, j;
87
89 for (i = 0; i < (int)A->NbRows; i++)
90 for (j = 0; j < (int)A->NbColumns; j++)
91 value_assign(transpose->p[j][i], A->p[i][j]);
92 return transpose;
93} /* Transpose */
94
95/*
96 * Return a copy of the contents of a matrix 'Src'.
97 */
99 Matrix *Dst;
100 unsigned i, j;
101
102 Dst = Matrix_Alloc(Src->NbRows, Src->NbColumns);
103
104 for (i = 0; i < Src->NbRows; i++)
105 for (j = 0; j < Src->NbColumns; j++)
106 value_assign(Dst->p[i][j], Src->p[i][j]);
107 return Dst;
108} /* Matrix_copy */
109
110/*
111 * Test if the input matrix is integral or not.
112 */
114
115 unsigned i, j;
116 Value divisor, tmp;
117
118 value_init(divisor);
119 value_init(tmp);
120 value_assign(divisor, A->p[A->NbRows - 1][A->NbColumns - 1]);
121
122 for (i = 0; i < A->NbRows; i++)
123 for (j = 0; j < A->NbColumns; j++) {
124 value_modulus(tmp, A->p[i][j], divisor);
125 if (value_notzero_p(tmp)) {
126 value_clear(divisor);
127 value_clear(tmp);
128 return False;
129 }
130 }
131 value_clear(divisor);
132 value_clear(tmp);
133 return True;
134} /* isIntegral */
135
136/*
137 * Check if the matrix 'A' is in Hermite normal form or not.
138 */
140
141 Matrix *temp;
142 unsigned i, j;
143 Value rem;
144
145 value_init(rem);
146 temp = Homogenise(A, True);
147 for (i = 0; i < temp->NbRows; i++) {
148 value_assign(rem, temp->p[i][i]);
149 for (j = 0; j < i; j++)
150 if (value_ge(temp->p[i][j], rem)) {
151 Matrix_Free(temp);
152 value_clear(rem);
153 return False;
154 }
155 for (j = i + 1; j < temp->NbColumns; j++)
156 if (value_notzero_p(temp->p[i][j])) {
157 Matrix_Free(temp);
158 value_clear(rem);
159 return False;
160 }
161 }
162 Matrix_Free(temp);
163 value_clear(rem);
164 return True;
165} /* isinHnf */
166
167/*
168 * Remove the row 'Rownumber' and place it at the end of the matrix 'X'
169 */
170void PutRowLast(Matrix *X, int Rownumber) {
171
172 int i, j;
173 Value temp;
174
175 if (Rownumber == X->NbRows - 1)
176 return;
177
178 value_init(temp);
179 for (j = 0; j < X->NbColumns; j++) {
180 value_assign(temp, X->p[Rownumber][j]);
181 for (i = Rownumber; i < X->NbRows - 1; i++)
182 value_assign(X->p[i][j], X->p[i + 1][j]);
183 value_assign(X->p[i][j], temp);
184 }
185 value_clear(temp);
186 return;
187} /* PutRowLast */
188
189/*
190 * Remove the row 'Rownumber' and place it at the begining of the matrix 'X'
191 */
192void PutRowFirst(Matrix *X, int Rownumber) {
193
194 int i, j;
195 Value temp;
196
197 value_init(temp);
198 for (j = 0; j < X->NbColumns; j++) {
199 value_assign(temp, X->p[Rownumber][j]);
200 for (i = Rownumber; i > 0; i--)
201 value_assign(X->p[i][j], X->p[i - 1][j]);
202 value_assign(X->p[i][j], temp);
203 }
204 value_clear(temp);
205 return;
206} /* PutRowFirst */
207
208/*
209 * Remove the column 'Columnnumber' and place it at the begining of the matrix
210 * 'X'
211 */
212void PutColumnFirst(Matrix *X, int Columnnumber) {
213
214 int i, j;
215 Value temp;
216
217 value_init(temp);
218 for (i = 0; i < X->NbRows; i++) {
219 value_assign(temp, X->p[i][Columnnumber]);
220 for (j = Columnnumber; j > 0; j--)
221 value_assign(X->p[i][j], X->p[i][j - 1]);
222 value_assign(X->p[i][0], temp);
223 }
224 value_clear(temp);
225 return;
226} /* PutColumnFirst */
227
228/*
229 * Remove the column 'Columnnumber' and place it at the end of the matrix 'X'
230 */
231void PutColumnLast(Matrix *X, int Columnnumber) {
232
233 int i, j;
234 Value temp;
235
236 value_init(temp);
237 for (i = 0; i < X->NbRows; i++) {
238 value_assign(temp, X->p[i][Columnnumber]);
239 for (j = Columnnumber; j < X->NbColumns - 1; j++)
240 value_assign(X->p[i][j], X->p[i][j + 1]);
241 value_assign(X->p[i][X->NbColumns - 1], temp);
242 }
243 value_clear(temp);
244 return;
245} /* PutColumnLast */
246
247/*
248 * Add a row of zeros at the end of the matrix 'M' and return the new matrix
249 */
251
252 int i, j;
253 Matrix *Result;
254
255 Result = Matrix_Alloc(M->NbRows + 1, M->NbColumns);
256 for (i = 0; i < M->NbRows; i++)
257 for (j = 0; j < M->NbColumns; j++)
258 value_assign(Result->p[i][j], M->p[i][j]);
259 for (j = 0; j < M->NbColumns; j++)
260 value_set_si(Result->p[i][j], 0);
261 return Result;
262} /* AddANullRow */
263
264/*
265 * Add a column of zeros at the end of the matrix 'M' and return the new
266 * matrix
267 */
269
270 int i, j;
271 Matrix *Result;
272
273 Result = Matrix_Alloc(M->NbRows, M->NbColumns + 1);
274 for (i = 0; i < M->NbRows; i++)
275 for (j = 0; j < M->NbColumns; j++)
276 value_assign(Result->p[i][j], M->p[i][j]);
277 for (i = 0; i < M->NbRows; i++)
278 value_set_si(Result->p[i][M->NbColumns], 0);
279 return Result;
280} /* AddANullColumn */
281
282/*
283 * Remove a row 'Rownumber' from matrix 'M' and return the new matrix.
284 */
285Matrix *RemoveRow(Matrix *M, int Rownumber) {
286
287 Matrix *Result;
288 int i;
289
290 Result = Matrix_Alloc(M->NbRows - 1, M->NbColumns);
291
292 for (i = 0; i < Rownumber; i++)
293 Vector_Copy(M->p[i], Result->p[i], M->NbColumns);
294 for (; i < Result->NbRows; i++)
295 Vector_Copy(M->p[i + 1], Result->p[i], M->NbColumns);
296
297 return Result;
298} /* RemoveRow */
299
300/*
301 * Remove NumColumns columns starting at column number 'FirstColumnnumber' from
302 * matrix 'M' and return the new matrix.
303 */
304Matrix *RemoveNColumns(Matrix *M, int FirstColumnnumber, int NumColumns) {
305
306 Matrix *Result;
307 int i;
308
309 Result = Matrix_Alloc(M->NbRows, M->NbColumns - NumColumns);
310
311 for (i = 0; i < Result->NbRows; i++) {
312 Vector_Copy(M->p[i], Result->p[i], FirstColumnnumber);
313 Vector_Copy(M->p[i] + FirstColumnnumber + NumColumns,
314 Result->p[i] + FirstColumnnumber,
315 M->NbColumns - NumColumns - FirstColumnnumber);
316 }
317 return Result;
318} /* RemoveColumn */
319
320/*
321 * Remove a column 'Columnnumber' from matrix 'M' and return the new matrix.
322 */
323Matrix *RemoveColumn(Matrix *M, int Columnnumber) {
324
325 Matrix *Result;
326 int i;
327
328 Result = Matrix_Alloc(M->NbRows, M->NbColumns - 1);
329
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);
334 }
335 return Result;
336} /* RemoveColumn */
337
338/*
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.
343 */
344int findHermiteBasis(Matrix *M, Matrix **Result) {
345
346 int i, j;
347 Matrix *C, *curMat, *temp1, *temp2;
348 Matrix *H, *U;
349 Vector *V;
350 int dim, curDim, curVect, rank;
351
352 if (M->NbRows == 0) {
353 Result[0] = Identity(M->NbColumns);
354 return 0;
355 }
356
357 if (M->NbRows <= M->NbColumns) {
358 Hermite(M, &H, &U);
359
360 for (i = 0; i < H->NbRows; i++)
361 if (value_zero_p(H->p[i][i]))
362 break;
363
364 if (i == H->NbRows) {
365 Result[0] = Transpose(U);
366 Matrix_Free(H);
367 Matrix_Free(U);
368 return (i);
369 }
370 Matrix_Free(H);
371 Matrix_Free(U);
372 }
373
374 /* Eliminating the Zero Rows */
375
376 C = Matrix_Copy(M);
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]))
380 break;
381 if (j == C->NbColumns) {
382 Matrix *temp;
383 temp = RemoveRow(C, i);
384 Matrix_Free(C);
385 C = Matrix_Copy(temp);
386 Matrix_Free(temp);
387 i--;
388 }
389 }
390
391 /* Eliminating the Redundant Rows */
392
393 curDim = 1;
394 curVect = 1;
395 dim = C->NbColumns;
396
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]);
400
401 while ((curVect < C->NbRows) && (curDim < dim)) {
402 Matrix *temp;
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]);
406
407 temp1 = AddANullRow(temp);
408 temp2 = AddANullColumn(temp1);
409 rank = SolveDiophantine(temp2, &U, &V);
410 if (rank == temp->NbRows) {
411 Matrix_Free(curMat);
412 curMat = Matrix_Copy(temp);
413 curDim++;
414 }
415 curVect++;
416 Matrix_Free(U);
417 Vector_Free(V);
418 Matrix_Free(temp1);
419 Matrix_Free(temp);
420 Matrix_Free(temp2);
421 }
422 Matrix_Free(C);
423
424 Hermite(curMat, &H, &U);
425 rank = curMat->NbRows;
426 Matrix_Free(curMat);
427
428 Result[0] = Transpose(U);
429 Matrix_Free(H);
430 Matrix_Free(U);
431 return (rank);
432} /* findHermiteBasis */
Lattice * Homogenise(Lattice *A, Bool Forward)
Definition: Lattice.c:297
Bool isinHnf(Matrix *A)
Definition: Matop.c:139
void PutRowLast(Matrix *X, int Rownumber)
Definition: Matop.c:170
Matrix * AddANullRow(Matrix *M)
Definition: Matop.c:250
void PutColumnLast(Matrix *X, int Columnnumber)
Definition: Matop.c:231
void Lcm3(Value a, Value b, Value *c)
Definition: Matop.c:5
Matrix * RemoveRow(Matrix *M, int Rownumber)
Definition: Matop.c:285
Matrix * Identity(unsigned size)
Definition: Matop.c:39
Matrix * Transpose(Matrix *A)
Definition: Matop.c:83
Value * Lcm(Value i, Value j)
Definition: Matop.c:27
Bool isIntegral(Matrix *A)
Definition: Matop.c:113
void PutRowFirst(Matrix *X, int Rownumber)
Definition: Matop.c:192
void PutColumnFirst(Matrix *X, int Columnnumber)
Definition: Matop.c:212
Matrix * RemoveColumn(Matrix *M, int Columnnumber)
Definition: Matop.c:323
void ExchangeRows(Matrix *M, int Row1, int Row2)
Definition: Matop.c:52
int findHermiteBasis(Matrix *M, Matrix **Result)
Definition: Matop.c:344
Matrix * AddANullColumn(Matrix *M)
Definition: Matop.c:268
Matrix * Matrix_Copy(Matrix const *Src)
Definition: Matop.c:98
Matrix * RemoveNColumns(Matrix *M, int FirstColumnnumber, int NumColumns)
Definition: Matop.c:304
void ExchangeColumns(Matrix *M, int Column1, int Column2)
Definition: Matop.c:70
static void transpose(Value *a, int n, int q)
Definition: NormalForms.c:282
void Hermite(Matrix *A, Matrix **H, Matrix **U)
Hermite : This function takes a Matrix as its input and finds its HNF ( Left form )
Definition: NormalForms.c:663
int SolveDiophantine(Matrix *M, Matrix **U, Vector **X)
Definition: SolveDio.c:64
#define value_swap(v1, v2)
Definition: arithmetique.h:488
#define value_notzero_p(val)
Definition: arithmetique.h:576
#define value_absolute(ref, val)
Definition: arithmetique.h:553
#define value_zero_p(val)
Definition: arithmetique.h:575
#define value_assign(v1, v2)
Definition: arithmetique.h:482
#define value_set_si(val, i)
Definition: arithmetique.h:483
#define value_clear(val)
Definition: arithmetique.h:485
#define value_division(ref, val1, val2)
Definition: arithmetique.h:547
#define value_multiply(ref, val1, val2)
Definition: arithmetique.h:543
#define value_modulus(ref, val1, val2)
Definition: arithmetique.h:549
#define value_ge(v1, v2)
Definition: arithmetique.h:505
#define value_init(val)
Definition: arithmetique.h:481
Matrix * Matrix_Alloc(unsigned NbRows, unsigned NbColumns)
Definition: matrix.c:24
void Matrix_Free(Matrix *Mat)
Definition: matrix.c:71
Definition: types.h:70
Definition: types.h:75
unsigned NbRows
Definition: types.h:76
Value ** p
Definition: types.h:77
unsigned NbColumns
Definition: types.h:76
Bool
Definition: types.h:218
@ True
Definition: types.h:218
@ False
Definition: types.h:218
void Vector_Free(Vector *vector)
Definition: vector.c:162
void Gcd(Value a, Value b, Value *result)
Definition: vector.c:99
void Vector_Copy(Value *p1, Value *p2, unsigned length)
Definition: vector.c:256