polylib 7.01
NewLattice.c
Go to the documentation of this file.
1#include <polylib/polylib.h>
2#include <stdlib.h>
3
4// #define LATINTER_DEBUG 1
5#define LATDIF_DEBUG 1
6
7typedef struct {
8 int count;
9 int *fac;
10} factor;
11
12
13static factor allfactors(int num);
14static LatticeUnion* generate_lattice_union_line(int line_nb, Vector* diag_A, Vector* diag_Inter, Lattice* Intersection, LatticeUnion *Result);
15/*
16 * Print the contents of a list of Lattices 'Head'
17 */
18void PrintLatticeUnion(FILE *fp, char *format, LatticeUnion *Head) {
19
20 LatticeUnion *temp;
21
22 for (temp = Head; temp != NULL; temp = temp->next)
23 Matrix_Print(fp, format, (Matrix *)temp->M);
24 return;
25} /* PrintLatticeUnion */
26
27/*
28 * Free the memory allocated to a list of lattices 'Head'
29 */
31
32 LatticeUnion *temp;
33
34 while (Head != NULL) {
35 temp = Head;
36 Head = temp->next;
37 Matrix_Free(temp->M);
38 free(temp);
39 }
40 return;
41} /* LatticeUnion_Free */
42
43/*
44 * Allocate a heads for a list of Lattices
45 */
47
48 LatticeUnion *temp;
49
50 temp = (LatticeUnion *)malloc(sizeof(LatticeUnion));
51 temp->M = NULL;
52 temp->next = NULL;
53 return temp;
54} /* LatticeUnion_Alloc */
55
56/*
57 * Given two Lattices 'A' and 'B', return True if they have the same affine
58 * part (the last column) otherwise return 'False'.
59 */
60Bool sameAffinepart(Lattice *A, Lattice *B) {
61
62 int i;
63
64#ifdef DOMDEBUG
65 FILE *fp;
66 fp = fopen("_debug", "a");
67 fprintf(fp, "\nEntered SAMEAFFINEPART \n");
68 fclose(fp);
69#endif
70
71 for (i = 0; i < A->NbRows; i++)
72 if (value_ne(A->p[i][A->NbColumns - 1], B->p[i][B->NbColumns - 1]))
73 return False;
74 return True;
75} /* sameAffinepart */
76
77/*
78 * Return an empty lattice of dimension 'dimension-1'. An empty lattice is
79 * represented as [[0 0 ... 0] .... [0 ... 0][0 0.....0 1]].
80 */
81Lattice *EmptyLattice(int dimension) {
82
83 Lattice *result;
84 int j;
85
86#ifdef DOMDEBUG
87 FILE *fp;
88 fp = fopen("_debug", "a");
89 fprintf(fp, "\nEntered NULLATTICE \n");
90 fclose(fp);
91#endif
92
93 return NULL;
94 result = Matrix_Alloc(1, dimension);
95 for (j = 0; j < dimension; j++)
96 value_set_si(result->p[0][j], 0);
97 value_set_si(result->p[0][dimension-1], 1);
98 return result;
99} /* EmptyLattice */
100
101/*
102 * Return True if lattice 'A' is empty, otherwise return False.
103 * A has been normalized.
104 */
105Bool isEmptyLattice(Lattice *A) {
106
107 if(A == NULL || A->NbColumns == 0) {
108 return True;
109 }
110 // A is empty if there are only zero's in the first column
111 for (int j = 0; j < A->NbRows-1; j++) {
112 if (value_notzero_p(A->p[0][j])) {
113 return False;
114 }
115 }
116 return True;
117
118} /* isEmptyLattice */
119
120/*
121 * Given a Lattice 'A', check whether it is linear or not, i.e. whether the
122 * affine part is NULL or not. If affine part is empty, it returns True other-
123 * wise it returns False.
124 */
125Bool isLinear(Lattice *A) {
126
127 int i;
128
129#ifdef DOMDEBUG
130 FILE *fp;
131 fp = fopen("_debug", "a");
132 fprintf(fp, "\nEntered ISLINEAR \n");
133 fclose(fp);
134#endif
135
136 for (i = 0; i < A->NbRows - 1; i++)
137 if (value_notzero_p(A->p[i][A->NbColumns - 1])) {
138 return False;
139 }
140 return True;
141} /* isLinear */
142
143/*
144 * Return the affine Hermite normal form of the affine lattice 'A'. The unique
145 * affine Hermite form if a lattice is stored in 'H' and the unimodular matrix
146 * corresponding to 'A = H . U' is stored in the matrix 'U'.
147 * OLD Algorithm :
148 * 1) Check if the Lattice is Linear or not.
149 * 2) If it is not Linear, then Homogenise the Lattice.
150 * 3) Call Hermite.
151 * 4) If the Lattice was Homogenised, the HNF H must be
152 * Dehomogenised and also corresponding changes must
153 * be made to the Unimodular Matrix U.
154 * 5) Return.
155 * NEW algorithm:
156 * 1) move the homogeneous dimensions first (on top-left)
157 * 2) compute left_hermite
158 * 3) move back the homogeneous dimensions (bottom-right)
159 * -> works also on non square matrices (lattices having less row than columns)
160 */
161void AffineHermite(Lattice *A, Lattice **H, Matrix **U) {
162
163 // DEBUG
164 // printf("Entering AffineHermite: A= ");
165 // Matrix_Print(stdout, P_VALUE_FMT, A);
166
167 // for left hermite to include the constant, move it on top-left:
169 left_hermite(A, H, U, NULL);
171 if(U)
173 Matrix_Move_Homogeneous_Dim_Last(A); // restore A as it was
174
175 // OLD VERSION, working fine on square matrices, but not on non-square ones...
176 // Lattice *temp;
177 // Bool flag = True;
178
179 // #ifdef DOMDEBUG
180 // FILE *fp;
181 // fp = fopen("_debug", "a");
182 // fprintf(fp, "\nEntered AFFINEHERMITE \n");
183 // fclose(fp);
184 // #endif
185
186 // if (isLinear(A) == False)
187 // temp = Homogenise(A, True);
188 // else {
189 // flag = False;
190 // temp = Matrix_Copy(A);
191 // }
192 // Hermite(temp, H, U);
193 // if (flag == True) {
194 // Matrix_Free(temp);
195 // temp = Homogenise(H[0], False);
196 // Matrix_Free(H[0]);
197 // H[0] = Matrix_Copy(temp);
198 // Matrix_Free(temp);
199 // temp = Homogenise(U[0], False);
200 // Matrix_Free(U[0]);
201 // U[0] = Matrix_Copy(temp);
202 // }
203 // Matrix_Free(temp);
204
205
206 // DEBUG
207 // printf("Exit AffineHermite: H = ");
208 // Matrix_Print(stdout, P_VALUE_FMT, *H);
209 // printf(" U = ");
210 // Matrix_Print(stdout, P_VALUE_FMT, *U);
211
212 return;
213} /* AffineHermite */
214
215// /*
216// * Given a Polylib matrix 'A' that represents an affine function, return the
217// * affine Smith normal form 'Delta' of 'A' and unimodular matrices 'U' and 'V'
218// * such that 'A = U*Delta*V'.
219// * Algorithm:
220// * (1) Homogenize the Lattice.
221// * (2) Call Smith
222// * (3) The Smith Normal Form Delta must be Dehomogenized and also
223// * corresponding changes must be made to the Unimodular Matrices
224// * U and V.
225// * 4) Bring Delta into AffineSmith Form.
226// */
227// void AffineSmith(Lattice *A, Lattice **U, Lattice **V, Lattice **Diag) {
228
229// Lattice *temp;
230// Lattice *Uinv;
231// int i, j;
232// Value sum, quo, rem;
233
234// #ifdef DOMDEBUG
235// FILE *fp;
236// fp = fopen("_debug", "a");
237// fprintf(fp, "\nEntered AFFINESMITH \n");
238// fclose(fp);
239// #endif
240
241// value_init(sum);
242// value_init(quo);
243// value_init(rem);
244// temp = Homogenise(A, True);
245// Smith(temp, U, V, Diag);
246// Matrix_Free(temp);
247
248// temp = Homogenise(*U, False);
249// Matrix_Free(*U);
250// *U = temp;
251
252// temp = Homogenise(*V, False);
253// Matrix_Free(*V);
254// *V = temp;
255
256// temp = Homogenise(*Diag, False);
257// Matrix_Free(*Diag);
258// *Diag = temp;
259
260// temp = Matrix_Copy(*U);
261// Uinv = Matrix_Alloc((*U)->NbColumns, (*U)->NbRows);
262// Matrix_Inverse(temp, Uinv);
263// Matrix_Free(temp);
264
265// for (i = 0; i < U[0]->NbRows - 1; i++) {
266// value_set_si(sum, 0);
267// for (j = 0; j < U[0]->NbColumns - 1; j++) {
268// value_addmul(sum, Uinv->p[i][j], U[0]->p[j][U[0]->NbColumns - 1]);
269// }
270// value_assign(Diag[0]->p[i][j], sum);
271// }
272// Matrix_Free(Uinv);
273// for (i = 0; i < U[0]->NbRows - 1; i++)
274// value_set_si(U[0]->p[i][U[0]->NbColumns - 1], 0);
275// for (i = 0; i < Diag[0]->NbRows - 1; i++) {
276// value_division(quo, Diag[0]->p[i][Diag[0]->NbColumns - 1],
277// Diag[0]->p[i][i]);
278// value_modulus(rem, Diag[0]->p[i][Diag[0]->NbColumns - 1], Diag[0]->p[i][i]);
279
280// /* Apparently the % operator is strange when sign are different */
281// if (value_neg_p(rem)) {
282// value_addto(rem, rem, Diag[0]->p[i][i]);
283// value_decrement(quo, quo);
284// };
285// value_assign(Diag[0]->p[i][Diag[0]->NbColumns - 1], rem);
286// value_assign(V[0]->p[i][V[0]->NbColumns - 1], quo);
287// }
288// value_clear(sum);
289// value_clear(quo);
290// value_clear(rem);
291// return;
292// } /* AffineSmith */
293
294/*
295 * Given a lattice 'A' and a boolean variable 'Forward', homogenise the lattice
296 * if 'Forward' is True, otherwise if 'Forward' is False, dehomogenise the
297 * lattice 'A'.
298 * Algorithm:
299 * (1) If Forward == True
300 * Put the last row first.
301 * Put the last columns first.
302 * (2) Else
303 * Put the first row last.
304 * Put the first column last.
305 * (3) Return the result.
306 */
307Lattice *Homogenise(Lattice *A, Bool Forward) {
308
309 Lattice *result;
310
311#ifdef DOMDEBUG
312 FILE *fp;
313 fp = fopen("_debug", "a");
314 fprintf(fp, "\nEntered HOMOGENISE \n");
315 fclose(fp);
316#endif
317
318 result = Matrix_Copy(A);
319 if (Forward == True) {
320 PutColumnFirst(result, A->NbColumns - 1);
321 PutRowFirst(result, result->NbRows - 1);
322 } else {
323 PutColumnLast(result, 0);
324 PutRowLast(result, 0);
325 }
326 return result;
327} /* Homogenise */
328
329/*
330 * Given two lattices 'A' and 'B', verify if lattice 'A' is included in 'B' or
331 * not. If 'A' is included in 'B' the 'A' intersection 'B', will be 'A'. So,
332 * compute 'A' intersection 'B' and check if it is the same as 'A'.
333 */
334Bool LatticeIncludes(Lattice *A, Lattice *B) {
335
336 Lattice *temp, *HA;
337 Bool flag = False;
338
339#ifdef DOMDEBUG
340 FILE *fp;
341 fp = fopen("_debug", "a");
342 fprintf(fp, "\nEntered LATTICE INCLUDES \n");
343 fclose(fp);
344#endif
345
346 AffineHermite(A, &HA, NULL);
347 temp = LatticeIntersection(B, HA);
348 if(temp) {
349 if(sameLattice(temp, HA))
350 flag = True;
351 Matrix_Free(temp);
352 }
353
354 Matrix_Free(HA);
355 return flag;
356} /* LatticeIncludes */
357
358/*
359 * Given two lattices 'A' and 'B', verify if 'A' and 'B' are the same lattice.
360 * Algorithm:
361 * The Affine Hermite form of two full dimensional matrices are
362 * unique. So, take the Affine Hermite form of both 'A' and 'B' and compare the
363 * matrices. If they are equal, the function returns True, else it returns
364 * False.
365 */
366Bool sameLattice(Lattice *A, Lattice *B) {
367
368 Lattice *HA, *HB;
369 int i, j;
370 Bool result = True;
371
372#ifdef DOMDEBUG
373 FILE *fp;
374 fp = fopen("_debug", "a");
375 fprintf(fp, "\nEntered SAME LATTICE \n");
376 fclose(fp);
377#endif
378
379 if(A->NbRows != B->NbRows || A->NbColumns != B->NbColumns)
380 return (False);
381
382 AffineHermite(A, &HA, NULL);
383 AffineHermite(B, &HB, NULL);
384
385 for (i = 0; i < A->NbRows; i++)
386 for (j = 0; j < A->NbColumns; j++)
387 if (value_ne(HA->p[i][j], HB->p[i][j])) {
388 result = False;
389 break;
390 }
391
392 Matrix_Free(HA);
393 Matrix_Free(HB);
394
395 return result;
396} /* sameLattice */
397
398/*
399 * Given a matrix 'A' and an integer 'dimension', do the following:
400 * If dimension < A->dimension), output a (dimension * dimension) submatrix of
401 * A. Otherwise the output matrix is [A 0][0 ID]. The order if the identity
402 * matrix is (dimension - A->dimension). The input matrix is not necessarily
403 * a Polylib matrix but the output is a polylib matrix.
404 */
405Lattice *ChangeLatticeDimension(Lattice *A, int dimension) {
406
407 int i, j;
408 Lattice *Result;
409
410 Result = Matrix_Alloc(dimension, dimension);
411 if (dimension <= A->NbRows) {
412 for (i = 0; i < dimension; i++)
413 for (j = 0; j < dimension; j++)
414 value_assign(Result->p[i][j], A->p[i][j]);
415 return Result;
416 }
417 for (i = 0; i < A->NbRows; i++)
418 for (j = 0; j < A->NbRows; j++)
419 value_assign(Result->p[i][j], A->p[i][j]);
420
421 for (i = A->NbRows; i < dimension; i++)
422 for (j = 0; j < dimension; j++) {
423 value_set_si(Result->p[i][j], 0);
424 value_set_si(Result->p[j][i], 0);
425 }
426 for (i = A->NbRows; i < dimension; i++)
427 value_set_si(Result->p[i][i], 1);
428 return Result;
429} /* ChangeLatticeDimension */
430
431/*
432 * Given an affine lattice 'A', return a matrix of the linear part of the
433 * lattice.
434 */
435Lattice *ExtractLinearPart(Lattice *A) {
436
437 Lattice *Result;
438 int i, j;
439 Result = (Lattice *)Matrix_Alloc(A->NbRows - 1, A->NbColumns - 1);
440 for (i = 0; i < A->NbRows - 1; i++)
441 for (j = 0; j < A->NbColumns - 1; j++)
442 value_assign(Result->p[i][j], A->p[i][j]);
443 return Result;
444} /* ExtractLinearPart */
445
446// static Matrix *MakeDioEqforInter(Matrix *A, Matrix *B);
447
448// /*
449// * Given two lattices 'A' and 'B', return the intersection of the two lattcies.
450// * The dimension of 'A' and 'B' should be the same.
451// * Algorithm:
452// * (1) Verify if the lattcies 'A' and 'B' have the same affine part.
453// * If they have same affine part, then only their Linear parts
454// * need to be intersected. If they don't have the same affine
455// * part then the affine part has to be taken into consideration.
456// * For this, homogenise the lattices to get their Hermite Forms
457// * and then find their intersection.
458// *
459// * (2) Step(2) involves, solving the Diophantine Equations in order
460// * to extract the intersection of the Lattices. The Diophantine
461// * equations are formed taking into consideration whether the
462// * affine part has to be included or not.
463// *
464// * (3) Solve the Diophantine equations.
465// *
466// * (4) Extract the necessary information from the result.
467// *
468// * (5) If the lattices have different affine parts and they were
469// * homogenised, the result is dehomogenised.
470// */
471// Lattice *OldLatticeIntersection(Lattice *X, Lattice *Y) {
472
473// int i, j, exist;
474// Lattice *result = NULL, *U = NULL;
475// Lattice *A = NULL, *B = NULL, *H = NULL;
476// Matrix *fordio;
477// Vector *X1 = NULL;
478
479// #ifdef DOMDEBUG
480// FILE *fp;
481// fp = fopen("_debug", "a");
482// fprintf(fp, "\nEntered LATTICEINTERSECTION \n");
483// fclose(fp);
484// #endif
485
486// if (X->NbRows != X->NbColumns) {
487// fprintf(stderr, "\nIn LatticeIntersection : The Input Matrix X is a not a "
488// "well defined Lattice\n");
489// return EmptyLattice(X->NbRows);
490// }
491
492// if (Y->NbRows != Y->NbColumns) {
493// fprintf(stderr, "\nIn LatticeIntersection : The Input Matrix Y is a not a "
494// "well defined Lattice\n");
495// return EmptyLattice(X->NbRows);
496// }
497
498// if (Y->NbRows != X->NbRows) {
499// fprintf(stderr, "\nIn LatticeIntersection : the input lattices X and Y are "
500// "of incompatible dimensions\n");
501// return EmptyLattice(X->NbRows);
502// }
503
504// if (isNormalLattice(X))
505// A = (Lattice *)Matrix_Copy(X);
506// else {
507// AffineHermite(X, &H, &U);
508// A = (Lattice *)Matrix_Copy(H);
509// Matrix_Free((Matrix *)H);
510// Matrix_Free((Matrix *)U);
511// }
512
513// if (isNormalLattice(Y))
514// B = (Lattice *)Matrix_Copy(Y);
515// else {
516// AffineHermite(Y, &H, &U);
517// B = (Lattice *)Matrix_Copy(H);
518// Matrix_Free((Matrix *)H);
519// Matrix_Free((Matrix *)U);
520// }
521
522// if ((isEmptyLattice(A)) || (isEmptyLattice(B))) {
523// result = EmptyLattice(X->NbRows);
524// Matrix_Free((Matrix *)A);
525// Matrix_Free((Matrix *)B);
526// return result;
527// }
528// fordio = MakeDioEqforInter(A, B);
529// Matrix_Free(A);
530// Matrix_Free(B);
531// exist = SolveDiophantine(fordio, (Matrix **)&U, &X1);
532// if (exist < 0) { /* Intersection is NULL */
533// result = (EmptyLattice(X->NbRows));
534// return result;
535// }
536
537// result = (Lattice *)Matrix_Alloc(X->NbRows, X->NbColumns);
538// for (i = 0; i < result->NbRows - 1; i++)
539// for (j = 0; j < result->NbColumns - 1; j++)
540// value_assign(result->p[i][j], U->p[i][j]);
541
542// for (i = 0; i < result->NbRows - 1; i++)
543// value_assign(result->p[i][result->NbColumns - 1], X1->p[i]);
544// for (i = 0; i < result->NbColumns - 1; i++)
545// value_set_si(result->p[result->NbRows - 1][i], 0);
546// value_set_si(result->p[result->NbRows - 1][result->NbColumns - 1], 1);
547
548// Matrix_Free((Matrix *)U);
549// Vector_Free(X1);
550// Matrix_Free(fordio);
551
552// AffineHermite(result, &H, &U);
553// Matrix_Free((Matrix *)result);
554// result = (Lattice *)Matrix_Copy(H);
555
556// Matrix_Free((Matrix *)H);
557// Matrix_Free((Matrix *)U);
558
559// /* Check whether the Lattice is NULL or not */
560
561// if (isEmptyLattice(result)) {
562// Matrix_Free((Matrix *)result);
563// return (EmptyLattice(X->NbRows));
564// }
565// return result;
566// } /* LatticeIntersection */
567
568// static Matrix *MakeDioEqforInter(Lattice *A, Lattice *B) {
569
570// Matrix *Dio;
571// int i, j;
572
573// #ifdef DOMDEBUG
574// FILE *fp;
575// fp = fopen("_debug", "a");
576// fprintf(fp, "\nEntered MAKEDIOEQFORINTER \n");
577// fclose(fp);
578// #endif
579
580// Dio = Matrix_Alloc(2 * (A->NbRows - 1) + 1, 3 * (A->NbColumns - 1) + 1);
581
582// for (i = 0; i < Dio->NbRows; i++)
583// for (j = 0; j < Dio->NbColumns; j++)
584// value_set_si(Dio->p[i][j], 0);
585
586// for (i = 0; i < A->NbRows - 1; i++) {
587// value_set_si(Dio->p[i][i], 1);
588// value_set_si(Dio->p[i + A->NbRows - 1][i], 1);
589// }
590// for (i = 0; i < A->NbRows - 1; i++)
591// for (j = 0; j < A->NbRows - 1; j++) {
592// value_oppose(Dio->p[i][j + A->NbRows - 1], A->p[i][j]);
593// value_oppose(Dio->p[i + (A->NbRows - 1)][j + 2 * (A->NbRows - 1)],
594// B->p[i][j]);
595// }
596
597// /* Adding the affine part */
598
599// for (i = 0; i < A->NbColumns - 1; i++) {
600// value_oppose(Dio->p[i][Dio->NbColumns - 1], A->p[i][A->NbColumns - 1]);
601// value_oppose(Dio->p[i + A->NbRows - 1][Dio->NbColumns - 1],
602// B->p[i][A->NbColumns - 1]);
603// }
604// value_set_si(Dio->p[Dio->NbRows - 1][Dio->NbColumns - 1], 1);
605// return Dio;
606// } /* MakeDioEqforInter */
607
608static void AddLattice(LatticeUnion *, Matrix *, Matrix *, Value, int);
610
611/*
612 * The function is transforming a lattice X in a union of lattices based on a
613 starting lattice Y.
614 * Note1: If the intersection of X and Y lattices is empty the result is identic
615 with the first argument (X) because no operation can be made. *Note2: The
616 function is available only for simple Lattices and not for a union of Lattices.
617 *
618 * Theorem : Given Two Lattices L1 and L2, (L2 subset of L1) there exists a
619 * Basis B = {b1, b2,..bn} of L1 and integers {a1, a2...,an} such
620 * that a1 divides a2, a2 divides a3 and so on and {a1b1, a2b2 ,...,
621 * .., anbn} is a Basis of L2. So given this theorem we can express
622 * the Lattice L1 in terms of Union of Lattices Involving L2, such
623 * that Lattice L1 = B1 = Union of (B2 + i1b1 + i2b2 + .. inbn) such
624 * that 0 <= i1 < a1; 0 <= i2 < a2; ....... 0 <= in < an. We also
625 * know that A/B = A/(A Intersection B) and that (A Intersection B)
626 * is a subset of A. So, Making use of these two facts, we find the
627 * A/B. We Split The Lattice A in terms of Lattice (A Int B). From
628 * this Union of Lattices Delete the Lattice (A Int B).
629 *
630 * Step 1: Find Intersection = LatticeIntersection (A, B).
631 * Step 2: Extract the Linear Parts of the Lattices A and Intersection.
632 * (while dealing with Basis we only deal with the Linear Parts)
633 * Step 3: Let M1 = linear basis of A and M2 = linear basis of B.
634 * Let B1 and B2 be the Basis of A and B respectively,
635 * corresponding to the above Theorem.
636 * Then we Have B1 = M1 * U1 {a unimodular Matrix }
637 * and B2 = M2 * U2. M1 and M2 we know, they are the linear
638 * parts we obtained in Step 2. Our Task is now to find U1 and
639 * U2.
640 * We know that B1 * Delta = B2.
641 * i.e. M1 * U1 * Delta = M2 * U2
642 * or U1*Delta*U2Inverse = M1Inverse * M2.
643 * and Delta is the Diagonal Matrix which satisfies the
644 * above properties (in the Theorem).
645 * So Delta is nothing but the Smith Normal Form of
646 * M1Inverse * M2.
647 * So, first we have to find M1Inverse.
648 *
649 * This Step, involves finding the Inverse of the Matrix M1.
650 * We find the Inverse using the Polylib function
651 * Matrix_Inverse. There is a catch here, the result of this
652 * function is an integral matrix, not necessarily the exact
653 * Inverse (since M1 need not be Unimodular), but a multiple
654 * of the actual inverse. The number by which we have to divide
655 * the matrix, is not obtained here as the input matrix is not
656 * a Polylib matrix { We input only the Linear part }. Later I
657 * give a way for finding that number.
658 *
659 * M1Inverse = Matrix_Inverse ( M1 );
660 *
661 * Step 4 : MtProduct = Matrix_Product (M1Inverse, M2);
662 * Step 5 : SmithNormalFrom (MtProduct, Delta, U, V);
663 * U1 = U and U2Inverse = V.
664 * Step 6 : Find U2 = Matrix_Inverse (U2inverse). Here there is no prob
665 * as U1 and its inverse are unimodular.
666 *
667 * Step 7 : Compute B1 = M1 * U1;
668 * Step 8 : Compute B2 = M2 * U2;
669 * Step 9 : Earlier when we computed M1Inverse, we knew that it was not
670 * the exact inverse but a multiple of it. Now we find the
671 * number, such that ( M1Inverse / number ) would give us the
672 * exact inverse of M1.
673 * We know that B1 * Delta = B2.
674 * Let k = B2[0][0] / B1[0][0].
675 * Let number = Delta[0][0]/k;
676 * This 'number' is the number we want.
677 * We Divide the matrix Delta by this number, to get the actual
678 * Delta such that B1 * Delta = B2.
679 * Step 10 : Call Split Lattice (B1, B2, Delta ).
680 * This function returns the Union of Lattices in such a way
681 * that B2 is at the Head of this List.
682 *
683 *If the intersection between X and Y is empty then the result is NULL.
684 */
685
686LatticeUnion *Lattice2LatticeUnion(Lattice *X, Lattice *Y) {
687 Lattice *B1 = NULL, *B2 = NULL, *newB1 = NULL, *newB2 = NULL,
688 *Intersection = NULL;
689 Matrix *U = NULL, *M1 = NULL, *M2 = NULL, *M1Inverse = NULL,
690 *MtProduct = NULL;
691 Matrix *Vinv, *V, *temp, *DiagMatrix;
692
693 LatticeUnion *Head = NULL;
694 int i;
695 Value k;
696
697 Intersection = LatticeIntersection(X, Y);
698 #ifdef LATDIF_DEBUG
699 fprintf(stderr,"Lattice intersection = ");
700 Matrix_Print(stderr, P_VALUE_FMT, Intersection);
701 #endif
702 if (isEmptyLattice(Intersection)) {
703 #ifdef LATDIF_DEBUG
704 fprintf(stderr, "\nIn Lattice2LatticeUnion : the input lattices X and Y do "
705 "not have any common part\n");
706 #endif
707 Matrix_Free(Intersection);
708 return NULL;
709 }
710
711 value_init(k);
712 M1 = (Matrix *)ExtractLinearPart(X);
713 M2 = (Matrix *)ExtractLinearPart(Intersection);
714 #ifdef LATDIF_DEBUG
715 fprintf(stderr, "M1 = ");
716 Matrix_Print(stderr, P_VALUE_FMT, M1);
717 fprintf(stderr, "M2 = ");
718 Matrix_Print(stderr, P_VALUE_FMT, M2);
719 #endif
720
721 int maxdim = (M1->NbColumns > M1->NbRows)? M1->NbColumns : M1->NbRows;
722 // compute left(!) inverse of M1 using a dirty patch
723 M1Inverse = Matrix_Alloc(maxdim, maxdim);
724 // temp = Matrix_Copy(M1);
725
726 // complete temp with Id to make it square
727 temp = Matrix_Alloc(maxdim, maxdim);
728 for (i = 0; i < M1->NbRows; i++) {
729 int j;
730 for (j = 0; j < M1->NbColumns; j++)
731 value_assign(temp->p[i][j], M1->p[i][j]);
732 for( ; j < maxdim; j++)
733 value_set_si(temp->p[i][j], (i==j));
734 }
735 for( ; i < temp->NbColumns ; i++ )
736 for (int j = 0; j < M1->NbColumns; j++)
737 value_set_si(temp->p[i][j], (i==j));
738
739 Matrix_Inverse(temp, M1Inverse);
740 Matrix_Free(temp);
741
742 // get the right result: the rightmost columns of M1Inverse are just ignored :)
743 M1Inverse->NbColumns = M1->NbRows;
744 M1Inverse->NbRows = M1->NbColumns;
745 temp = Matrix_Copy(M1Inverse);
746 Matrix_Free(M1Inverse);
747 M1Inverse = temp;
748
749 #ifdef LATDIF_DEBUG
750 fprintf(stderr, "M1Inverse = ");
751 Matrix_Print(stderr, P_VALUE_FMT, M1Inverse);
752 #endif
753
754 MtProduct = Matrix_Alloc(M1Inverse->NbRows, M2->NbColumns);
755 Matrix_Product(M1Inverse, M2, MtProduct);
756 left_hermite(MtProduct, &DiagMatrix, &U, &Vinv);
757 V = Matrix_Alloc(Vinv->NbRows, Vinv->NbColumns);
758 Matrix_Inverse(Vinv, V);
759 Matrix_Free(Vinv);
760 B1 = Matrix_Alloc(M1->NbRows, U->NbColumns);
761 B2 = Matrix_Alloc(M2->NbRows, V->NbColumns);
762 Matrix_Product(M1, U, B1);
763 Matrix_Product(M2, V, B2);
764 Matrix_Free(M1);
765 Matrix_Free(M2);
766 value_division(k, B2->p[0][0], B1->p[0][0]);
767 value_division(k, DiagMatrix->p[0][0], k);
768 for (i = 0; i < DiagMatrix->NbRows; i++)
769 value_division(DiagMatrix->p[i][i], DiagMatrix->p[i][i], k);
770
771 #ifdef LATDIF_DEBUG
772 fprintf(stderr, "B1 = ");
773 Matrix_Print(stderr, P_VALUE_FMT, B1);
774 fprintf(stderr, "B2 = ");
775 Matrix_Print(stderr, P_VALUE_FMT, B2);
776 #endif
777
778 // previous method, supposed that B1 and B2 are square matrices:
779 // newB1 = ChangeLatticeDimension(B1, B1->NbRows + 1);
780 // Matrix_Free(B1);
781 // newB2 = ChangeLatticeDimension(B2, B2->NbRows + 1);
782 // Matrix_Free(B2);
783
784 // New method: add a row and a column to B1 and B2:
785 newB1 = Matrix_Alloc(B1->NbRows+1, B1->NbColumns+1);
786 newB2 = Matrix_Alloc(B2->NbRows+1, B2->NbColumns+1);
787 // copy the core of the matrix:
788 for(i=0 ; i<B1->NbRows; i++) {
789 for(int j=0 ; j<B1->NbColumns; j++) {
790 value_assign(newB1->p[i][j], B1->p[i][j]);
791 value_assign(newB2->p[i][j], B2->p[i][j]);
792 }
793 }
794 // complete the last row with zeroes:
795 for(int j=0 ; j<B1->NbColumns; j++) {
796 value_set_si(newB1->p[B1->NbRows][j], 0);
797 value_set_si(newB2->p[B1->NbRows][j], 0);
798 }
799 // complete last column (empty for B1, Intersection for B2):
800 for (i = 0; i < newB2->NbRows; i++)
801 {
802 value_set_si(newB1->p[i][newB2->NbColumns - 1], (i==newB2->NbColumns - 1));
803 value_assign(newB2->p[i][newB2->NbColumns - 1],
804 Intersection->p[i][Intersection->NbColumns - 1]);
805 }
806
807 #ifdef LATDIF_DEBUG
808 fprintf(stderr, "newB2 = ");
809 Matrix_Print(stderr, P_VALUE_FMT, newB2);
810 fprintf(stderr, "Diag = ");
811 Matrix_Print(stderr, P_VALUE_FMT, DiagMatrix);
812 #endif
813
814 Head = SplitLattice(newB1, newB2, DiagMatrix);
815 Matrix_Free(newB1);
816 Matrix_Free(MtProduct);
817 Matrix_Free(M1Inverse);
818 Matrix_Free(B1);
819 Matrix_Free(B2);
820 Matrix_Free(DiagMatrix);
821 Matrix_Free(U);
822 Matrix_Free(V);
823 Matrix_Free(Intersection);
824 value_clear(k);
825 return Head;
826}
827
828/*
829 * Return the Union of lattices that constitute the difference between
830 * two single lattices: A - B.
831 * The dimensions of A and B should be the same.
832 * If the difference is empty return NULL.
833 */
834LatticeUnion *LatticeDifference(Lattice *A, Lattice *B) {
835
836 LatticeUnion *Head = NULL;
837 Matrix *H, *X, *Y;
838
839#ifdef DOMDEBUG
840 FILE *fp;
841 fp = fopen("_debug", "a");
842 fprintf(fp, "\nEntered LATTICEDIFFERENCE \n");
843 fclose(fp);
844#endif
845
846 if (A->NbRows != B->NbRows) {
847 errormsg1("LatticeDifference", "dimincomp",
848 "input lattices A and B have incompatible dimensions (rows)");
849 return NULL;
850 }
851 if (A->NbColumns != B->NbColumns) {
852 errormsg1("LatticeDifference", "dimincomp",
853 "input lattices A and B have incompatible dimensions (columns)");
854 return NULL;
855 }
856
857 if (! isNormalLattice(A)) {
858 AffineHermite(A, &H, NULL);
859 X = H;
860 }
861 else {
862 X = Matrix_Copy(A);
863 }
864 if (isEmptyLattice(X)) {
865 Matrix_Free(X);
866 return(NULL);
867 }
868
869 if (! isNormalLattice(B)) {
870 AffineHermite(B, &H, NULL);
871 Y = H;
872 }
873 else {
874 Y = Matrix_Copy(B);
875 }
876 #ifdef LATDIF_DEBUG
877 fprintf(stderr, "Entering LatDiff. X = ");
878 Matrix_Print(stderr, P_VALUE_FMT, X);
879 fprintf(stderr, "Y = ");
880 Matrix_Print(stderr, P_VALUE_FMT, Y);
881 #endif
882 // allocating the lattice union
883 Head = LatticeUnion_Alloc();
884
885 //calculating intersection between X and Y
886 Lattice *Inter = LatticeIntersection(X, Y);
887 #ifdef LATDIF_DEBUG
888 fprintf(stderr, "Inter = ");
889 Matrix_Print(stderr, P_VALUE_FMT, Inter);
890 #endif
891 if(!Inter){
892 //if empty intersection return A
893 Matrix_Free(Y);
894 Head->M = X;
895 return Head;
896 }
897
898 // Matrix *DiagX = NULL, *XU = NULL, *XV = NULL;
899 // AffineSmith(X, &XU, &XV, &DiagX); // X = XU DiagX XV
900
901 // fprintf(stderr, "XU = ");
902 // Matrix_Print(stderr, P_VALUE_FMT, XU);
903 // fprintf(stderr, "DiagX = ");
904 // Matrix_Print(stderr, P_VALUE_FMT, DiagX);
905 // fprintf(stderr, "XV = ");
906 // Matrix_Print(stderr, P_VALUE_FMT, XV);
907
908 // Matrix *DiagInter = NULL, *U = NULL, *V = NULL;
909 // AffineSmith(Inter, &U, &V, &DiagInter); // Inter = U DiagInter V
910
911 // fprintf(stderr, "U = ");
912 // Matrix_Print(stderr, P_VALUE_FMT, U);
913 // fprintf(stderr, "DiagInter = ");
914 // Matrix_Print(stderr, P_VALUE_FMT, DiagInter);
915 // fprintf(stderr, "V = ");
916 // Matrix_Print(stderr, P_VALUE_FMT, V);
917
918
919 Head->M = Inter;
920
921 //get the diagonal coefficients of A and Inter
922 Vector *diag_X = get_pivots(X);
923 Vector *diag_Inter = get_pivots(Inter);
924 for (int line = 0; line < Inter->NbRows; line++) {
925 Head = generate_lattice_union_line(line, diag_X, diag_Inter, Inter, Head);
926 }
927
928 if(!Head->next){
929 //result is empty
930 #ifdef LATDIF_DEBUG
931 fprintf(stderr, "Empty result\n");
932 #endif
933 LatticeUnion_Free(Head);
934 return NULL;
935 }
936
937 LatticeUnion* tmp = Head;
938 //remove the last element of the list
939 while(tmp->next->next) {
940 tmp = tmp->next;
941 }
943 tmp->next = NULL;
944
945 #ifdef LATDIF_DEBUG
946 fprintf(stderr, "Raw result = ");
947 if(Head)
948 PrintLatticeUnion(stderr, P_VALUE_FMT, Head);
949 else
950 fprintf(stderr, "empty\n");
951 #endif
952
953 if ((Head != NULL)) {
954 Head = LatticeSimplify(Head);
955 #ifdef LATDIF_DEBUG
956 fprintf(stderr, "Simplified result = ");
957 PrintLatticeUnion(stderr, P_VALUE_FMT, Head);
958 #endif
959 }
960 Matrix_Free(X);
961 Matrix_Free(Y);
962 Vector_Free(diag_Inter);
963 Vector_Free(diag_X);
964
965 return Head;
966} /* LatticeDifference */
967
968/*
969 * Given a Lattice 'B1' and a Lattice 'B2' and a Diagonal Matrix 'C' such that
970 * 'B2' is a subset of 'B1' and C[0][0] divides C[1][1], C[1][1] divides C[2]
971 * [2] and so on, output the list of matrices whose union is B1. The function
972 * expresses the Lattice B1 in terms of B2 Unions of B1 = Union of {B2 + i0b0 +
973 * i1b1 + .... + inbn} where 0 <= i0 < C[0][0]; 0 <= i1 < C[1][1] and so on and
974 * {b0 ... bn} are the columns of Lattice B1. The list is so formed that the
975 * Lattice B2 is the Head of the list.
976 */
977LatticeUnion *SplitLattice(Lattice *B1, Lattice *B2, Matrix *C) {
978
979 int i;
980
981 LatticeUnion *Head = NULL;
982 Head = malloc(sizeof(LatticeUnion));
983 Head->M = B2;
984 Head->next = NULL;
985 for (i = 0; i < C->NbRows; i++)
986 AddLattice(Head, B1, B2, C->p[i][i], i);
987 return Head;
988} /* SplitLattice */
989
990/*
991 * Given lattices 'B1' and 'B2', an integer 'NumofTimes', a column number
992 * 'Colnumber' and a pointer to a list of lattices, the function does the
993 * following :-
994 * For every lattice in the list, it adds a set of lattices such that the
995 * affine part of the new lattices is greater than the original lattice by 0 to
996 * NumofTimes-1 * {the (ColumnNumber)-th column of B1}.
997 * Note :
998 * Three pointers are defined to point at various points of the list. They are:
999 * Head -> It always points to the head of the list.
1000 * tail -> It always points to the last element in the list.
1001 * marker -> It points to the element, which is the last element of the Input
1002 * list.
1003 */
1004static void AddLattice(LatticeUnion *Head, Matrix *B1, Matrix *B2,
1005 Value NumofTimes, int Colnumber) {
1006
1007 LatticeUnion *temp, *tail, *marker;
1008 int j;
1009 Value i, maxval;
1010
1011 // printf("Apply " P_VALUE_FMT "to column %d\n", NumofTimes, Colnumber);
1012 value_init(i);
1013 value_init(maxval);
1014 tail = Head;
1015 while (tail->next != NULL)
1016 tail = tail->next;
1017 marker = tail;
1018
1019 for (temp = Head; temp != NULL; temp = temp->next) {
1020 for (value_set_si(i, 1); value_lt(i, NumofTimes); value_increment(i, i)) {
1021 Lattice *tempMatrix, *H;
1022
1023 tempMatrix = Matrix_Copy(temp->M);
1024 for (j = 0; j < B2->NbRows; j++) {
1025 value_addmul(tempMatrix->p[j][B2->NbColumns - 1], i,
1026 B1->p[j][Colnumber]);
1027 if(value_notzero_p(B1->p[j][Colnumber])) {
1028 value_multiply(maxval, NumofTimes, B1->p[j][Colnumber]);
1029 // if(value_neg_p(tempMatrix->p[j][B2->NbColumns - 1])) {
1030
1031 // }
1032 // else {
1033 // value_print(stderr, P_VALUE_FMT, maxval);
1034 value_modulus(tempMatrix->p[j][B2->NbColumns - 1],
1035 tempMatrix->p[j][B2->NbColumns - 1], maxval);
1036 // }
1037 }
1038 }
1039 tail->next = malloc(sizeof(LatticeUnion));
1040 AffineHermite(tempMatrix, &H, NULL);
1041 Matrix_Free(tempMatrix);
1042 tail->next->M = H;
1043 tail->next->next = NULL;
1044 tail = tail->next;
1045 }
1046 if (temp == marker)
1047 break;
1048 }
1049 value_clear(i);
1050 value_clear(maxval);
1051 return;
1052} /* AddLattice */
1053
1054// /*
1055// * Given a polyhedron 'A', store the Hermite basis 'B' and return the true
1056// * dimension of the polyhedron 'A'.
1057// * Algorithm :
1058// *
1059// * 1) First we find all the vertices of the Polyhedron A.
1060// * Now suppose the vertices are [v1, v2...vn], then
1061// * a particular set of vectors governing the space of A are
1062// * given by [v1-v2, v1-v3, ... v1-vn] (let us say V).
1063// * So we initially calculate these vectors.
1064// * 2) Then there are the rays and lines which contribute to the
1065// * space in which A is going to lie.
1066// * So we append to the rays and lines. So now we get a matrix
1067// * {These are the rows} [ V ] [l1] [l2]...[lk]
1068// * where l1 to lk are either rays or lines of the Polyhedron A.
1069// * 3) The above matrix is the set of vectors which determine
1070// * the space in which A is going to lie.
1071// * Using this matrix we find a Basis which is such that
1072// * the first 'm' columns of it determine the space of A.
1073// * 4) But we also have to ensure that in the last 'n-m'
1074// * coordinates the Polyhedron is '0', this is done by
1075// * taking the image by B(inv) of A and finding the remaining
1076// * equalities, and composing it with the matrix B, so as
1077// * to get a new matrix which is the actual Hermite Basis of
1078// * the Polyhedron.
1079// */
1080// int FindHermiteBasisofDomain(Polyhedron *A, Matrix **B) {
1081
1082// int i, j;
1083// Matrix *temp, *temp1, *tempinv, *Newmat;
1084// Matrix *vert, *rays, *result;
1085// Polyhedron *Image;
1086// int rank, equcount;
1087// int noofvertices = 0, noofrays = 0;
1088// int vercount, raycount;
1089// Value lcm, fact;
1090
1091// #ifdef DOMDEBUG
1092// FILE *fp;
1093// fp = fopen("_debug", "a");
1094// fprintf(fp, "\nEntered FINDHERMITEBASISOFDOMAIN \n");
1095// fclose(fp);
1096// #endif
1097
1098// POL_ENSURE_FACETS(A);
1099// POL_ENSURE_VERTICES(A);
1100
1101// /* Checking is empty */
1102// if (emptyQ(A)) {
1103// B[0] = Identity(A->Dimension + 1);
1104// return (-1);
1105// }
1106
1107// value_init(lcm);
1108// value_init(fact);
1109// value_set_si(lcm, 1);
1110
1111// /* Finding the Vertices */
1112// for (i = 0; i < A->NbRays; i++)
1113// if ((value_notzero_p(A->Ray[i][0])) &&
1114// value_notzero_p(A->Ray[i][A->Dimension + 1]))
1115// noofvertices++;
1116// else
1117// noofrays++;
1118
1119// vert = Matrix_Alloc(noofvertices, A->Dimension + 1);
1120// rays = Matrix_Alloc(noofrays, A->Dimension);
1121// vercount = 0;
1122// raycount = 0;
1123
1124// for (i = 0; i < A->NbRays; i++) {
1125// if ((value_notzero_p(A->Ray[i][0])) &&
1126// value_notzero_p(A->Ray[i][A->Dimension + 1])) {
1127// for (j = 1; j < A->Dimension + 2; j++)
1128// value_assign(vert->p[vercount][j - 1], A->Ray[i][j]);
1129// value_lcm(lcm, lcm, A->Ray[i][j - 1]);
1130// vercount++;
1131// } else {
1132// for (j = 1; j < A->Dimension + 1; j++)
1133// value_assign(rays->p[raycount][j - 1], A->Ray[i][j]);
1134// raycount++;
1135// }
1136// }
1137
1138// /* Multiplying the rows by the lcm */
1139// for (i = 0; i < vert->NbRows; i++) {
1140// value_division(fact, lcm, vert->p[i][vert->NbColumns - 1]);
1141// for (j = 0; j < vert->NbColumns - 1; j++)
1142// value_multiply(vert->p[i][j], vert->p[i][j], fact);
1143// }
1144
1145// /* Drop the Last Columns */
1146// temp = RemoveColumn(vert, vert->NbColumns - 1);
1147// Matrix_Free(vert);
1148
1149// /* Getting the Vectors */
1150// vert = Matrix_Alloc(temp->NbRows - 1, temp->NbColumns);
1151// for (i = 1; i < temp->NbRows; i++)
1152// for (j = 0; j < temp->NbColumns; j++)
1153// value_subtract(vert->p[i - 1][j], temp->p[0][j], temp->p[i][j]);
1154
1155// Matrix_Free(temp);
1156
1157// /* Add the Rays and Lines */
1158// /* Combined Matrix */
1159// result = Matrix_Alloc(vert->NbRows + rays->NbRows, vert->NbColumns);
1160// for (i = 0; i < vert->NbRows; i++)
1161// for (j = 0; j < result->NbColumns; j++)
1162// value_assign(result->p[i][j], vert->p[i][j]);
1163
1164// for (; i < result->NbRows; i++)
1165// for (j = 0; j < result->NbColumns; j++)
1166// value_assign(result->p[i][j], rays->p[i - vert->NbRows][j]);
1167
1168// Matrix_Free(vert);
1169// Matrix_Free(rays);
1170
1171// rank = findHermiteBasis(result, &temp);
1172// temp1 = ChangeLatticeDimension(temp, temp->NbRows + 1);
1173
1174// Matrix_Free(result);
1175// Matrix_Free(temp);
1176
1177// /* Adding the Affine Part to take care of the Equalities */
1178// temp = Matrix_Copy(temp1);
1179// tempinv = Matrix_Alloc(temp->NbRows, temp->NbColumns);
1180// Matrix_Inverse(temp, tempinv);
1181// Matrix_Free(temp);
1182// Image = DomainImage(A, tempinv, MAXNOOFRAYS);
1183// Matrix_Free(tempinv);
1184// Newmat = Matrix_Alloc(temp1->NbRows, temp1->NbColumns);
1185// for (i = 0; i < rank; i++)
1186// for (j = 0; j < Newmat->NbColumns; j++)
1187// value_set_si(Newmat->p[i][j], 0);
1188// for (i = 0; i < rank; i++)
1189// value_set_si(Newmat->p[i][i], 1);
1190// equcount = 0;
1191// for (i = 0; i < Image->NbConstraints; i++)
1192// if (value_zero_p(Image->Constraint[i][0])) {
1193// for (j = 1; j < Image->Dimension + 2; j++)
1194// value_assign(Newmat->p[rank + equcount][j - 1],
1195// Image->Constraint[i][j]);
1196// ++equcount;
1197// }
1198// Domain_Free(Image);
1199// for (i = 0; i < Newmat->NbColumns - 1; i++)
1200// value_set_si(Newmat->p[Newmat->NbRows - 1][i], 0);
1201// value_set_si(Newmat->p[Newmat->NbRows - 1][Newmat->NbColumns - 1], 1);
1202// temp = Matrix_Alloc(Newmat->NbRows, Newmat->NbColumns);
1203// Matrix_Inverse(Newmat, temp);
1204// Matrix_Free(Newmat);
1205// B[0] = Matrix_Alloc(temp1->NbRows, temp->NbColumns);
1206
1207// Matrix_Product(temp1, temp, B[0]);
1208// Matrix_Free(temp1);
1209// Matrix_Free(temp);
1210// value_clear(lcm);
1211// value_clear(fact);
1212// return rank;
1213// } /* FindHermiteBasisofDomain */
1214
1215// /*
1216// * Return the image of a lattice 'A' by the invertible, affine, rational
1217// * function 'M'.
1218// */
1219// Lattice *LatticeImage(Lattice *A, Matrix *M) {
1220
1221// Lattice *Img, *temp, *Minv;
1222
1223// #ifdef DOMDEBUG
1224// FILE *fp;
1225// fp = fopen("_debug", "a");
1226// fprintf(fp, "\nEntered LATTICEIMAGE \n");
1227// fclose(fp);
1228// #endif
1229
1230// if ((A->NbRows != M->NbRows) || (M->NbRows != M->NbColumns))
1231// return (EmptyLattice(A->NbRows));
1232
1233// if (value_one_p(M->p[M->NbRows - 1][M->NbColumns - 1])) {
1234// Img = Matrix_Alloc(M->NbRows, A->NbColumns);
1235// Matrix_Product(M, A, Img);
1236// return Img;
1237// }
1238// temp = Matrix_Copy(M);
1239// Minv = Matrix_Alloc(temp->NbColumns, temp->NbRows);
1240// Matrix_Inverse(temp, Minv);
1241// Matrix_Free(temp);
1242
1243// Img = LatticePreimage(A, Minv);
1244// Matrix_Free(Minv);
1245// return Img;
1246// } /* LatticeImage */
1247
1248// /*
1249// * Return the preimage of a lattice 'L' by an affine, rational function 'G'.
1250// * Algorithm:
1251// * (1) Prepare Diophantine equation :
1252// * [Gl -Ll][x y] = [Ga -La]{"l-linear, a-affine"}
1253// * (2) Solve the Diophantine equations.
1254// * (3) If there is solution to the Diophantine eq., extract the
1255// * general solution and the particular solution of x and that
1256// * forms the preimage of 'L' by 'G'.
1257// */
1258// Lattice *LatticePreimage(Lattice *L, Matrix *G) {
1259
1260// Matrix *Dio, *U;
1261// Lattice *Result;
1262// Vector *X;
1263// int i, j;
1264// int rank;
1265// Value divisor, tmp;
1266
1267// #ifdef DOMDEBUG
1268// FILE *fp;
1269// fp = fopen("_debug", "a");
1270// fprintf(fp, "\nEntered LATTICEPREIMAGE \n");
1271// fclose(fp);
1272// #endif
1273
1274// /* Check for the validity of the function */
1275// if (G->NbRows != L->NbRows) {
1276// fprintf(stderr, "\nIn LatticePreimage: Incompatible types of Lattice and "
1277// "the function\n");
1278// return (EmptyLattice(G->NbColumns));
1279// }
1280
1281// value_init(divisor);
1282// value_init(tmp);
1283
1284// /* Making Diophantine Equations [g -L] */
1285// value_assign(divisor, G->p[G->NbRows - 1][G->NbColumns - 1]);
1286// Dio = Matrix_Alloc(G->NbRows, G->NbColumns + L->NbColumns - 1);
1287// for (i = 0; i < G->NbRows - 1; i++)
1288// for (j = 0; j < G->NbColumns - 1; j++)
1289// value_assign(Dio->p[i][j], G->p[i][j]);
1290
1291// for (i = 0; i < G->NbRows - 1; i++)
1292// for (j = 0; j < L->NbColumns - 1; j++) {
1293// value_multiply(tmp, divisor, L->p[i][j]);
1294// value_oppose(Dio->p[i][j + G->NbColumns - 1], tmp);
1295// }
1296
1297// for (i = 0; i < Dio->NbRows - 1; i++) {
1298// value_multiply(tmp, divisor, L->p[i][L->NbColumns - 1]);
1299// value_subtract(tmp, G->p[i][G->NbColumns - 1], tmp);
1300// value_assign(Dio->p[i][Dio->NbColumns - 1], tmp);
1301// }
1302// for (i = 0; i < Dio->NbColumns - 1; i++)
1303// value_set_si(Dio->p[Dio->NbRows - 1][i], 0);
1304
1305// value_set_si(Dio->p[Dio->NbRows - 1][Dio->NbColumns - 1], 1);
1306// rank = SolveDiophantine(Dio, &U, &X);
1307
1308// if (rank == -1)
1309// Result = EmptyLattice(G->NbColumns);
1310// else {
1311// Result = Matrix_Alloc(G->NbColumns, G->NbColumns);
1312// for (i = 0; i < Result->NbRows - 1; i++)
1313// for (j = 0; j < Result->NbColumns - 1; j++)
1314// value_assign(Result->p[i][j], U->p[i][j]);
1315
1316// for (i = 0; i < Result->NbRows - 1; i++)
1317// value_assign(Result->p[i][Result->NbColumns - 1], X->p[i]);
1318// Matrix_Free(U);
1319// Vector_Free(X);
1320// for (i = 0; i < Result->NbColumns - 1; i++)
1321// value_set_si(Result->p[Result->NbRows - 1][i], 0);
1322// value_set_si(Result->p[i][i], 1);
1323// }
1324// Matrix_Free(Dio);
1325// value_clear(divisor);
1326// value_clear(tmp);
1327// return Result;
1328// } /* LatticePreimage */
1329
1330/*
1331 * Return True if the matrix 'm' is a valid lattice, otherwise return False.
1332 * Note: A valid lattice has the last row as [0 0 0 ... 1].
1333 */
1335
1336 int i;
1337
1338#ifdef DOMDEBUG
1339 FILE *fp;
1340 fp = fopen("_debug", "a");
1341 fprintf(fp, "\nEntered ISLATTICE \n");
1342 fclose(fp);
1343#endif
1344
1345 /* Is it necessary to check if the lattice
1346 is fulldimensional or not here only? */
1347
1348 if (m->NbRows != m->NbColumns)
1349 return False;
1350
1351 for (i = 0; i < m->NbColumns - 1; i++)
1352 if (value_notzero_p(m->p[m->NbRows - 1][i]))
1353 return False;
1354 if (value_notone_p(m->p[i][i]))
1355 return False;
1356 return True;
1357} /* IsLattice */
1358
1359// /*
1360// * Check whether the matrix 'm' is full row-rank or not.
1361// */
1362// Bool isfulldim(Matrix *m) {
1363
1364// Matrix *h, *u;
1365// int i;
1366
1367// /*
1368// res = Hermite (m, &h, &u);
1369// if (res != m->NbRows)
1370// return False ;
1371// */
1372
1373// Hermite(m, &h, &u);
1374// for (i = 0; i < h->NbRows; i++)
1375// if (value_zero_p(h->p[i][i])) {
1376// Matrix_Free(h);
1377// Matrix_Free(u);
1378// return False;
1379// }
1380// Matrix_Free(h);
1381// Matrix_Free(u);
1382// return True;
1383// } /* isfulldim */
1384
1385/*
1386 * This function takes as input a lattice list in which the lattices have the
1387 * same linear part, and almost the same affinepart, i.e. if A and B are two
1388 * of the lattices in the above lattice list and [a1, .. , an] and [b1 .. bn]
1389 * are the affineparts of A and B respectively, then for 0 < i < n ai = bi and
1390 * 'an' may not be equal to 'bn'. These are not the affine parts in the n-th
1391 * dimension, but the lattices have been tranformed such that the value of the
1392 * elment in the dimension on which we are simplifying is in the last row and
1393 * also the lattices are in a sorted order.
1394 * This function also takes as input the dimension along which we
1395 * are simplifying and takes the diagonal element of the lattice along that
1396 * dimension and tries to find out the factors of that element and sees if the
1397 * list of lattices can be simplified using these factors. The output of this
1398 * function is the list of lattices in the simplified form and a flag to indic-
1399 * ate whether any form of simplification was actually done or not.
1400 */
1401static Bool Simplify(LatticeUnion **InputList, LatticeUnion **ResultList,
1402 int dim) {
1403
1404 int i;
1405 LatticeUnion *prev, *temp;
1406 factor allfac;
1407 Bool retval = False;
1408 int width;
1409 Value cnt, aux, k, fac, tmp, foobar; //, num
1410
1411 if ((*InputList == NULL) || (InputList[0]->next == NULL))
1412 return False;
1413
1414 value_init(aux);
1415 value_init(cnt);
1416 value_init(k);
1417 value_init(fac);
1418 // value_init(num);
1419 value_init(tmp);
1420 value_init(foobar);
1421
1422 width = InputList[0]->M->NbRows - 1;
1423 allfac = allfactors(VALUE_TO_INT(InputList[0]->M->p[dim][dim]));
1424 value_set_si(cnt, 0);
1425 for (temp = InputList[0]; temp != NULL; temp = temp->next)
1426 value_increment(cnt, cnt);
1427 for (i = 0; i < allfac.count; i++) {
1428 value_set_si(foobar, allfac.fac[i]);
1429 value_division(aux, InputList[0]->M->p[dim][dim], foobar);
1430 if (value_ge(cnt, aux))
1431 break;
1432 }
1433 if (i == allfac.count) {
1434 value_clear(cnt);
1435 value_clear(aux);
1436 value_clear(k);
1437 value_clear(fac);
1438 // value_clear(num);
1439 value_clear(tmp);
1440 value_clear(foobar);
1441 free(allfac.fac);
1442 return False;
1443 }
1444 for (; i < allfac.count; i++) {
1445 Bool Present = False;
1446 value_set_si(k, 0);
1447
1448 if (*InputList == NULL) {
1449 value_clear(cnt);
1450 value_clear(aux);
1451 value_clear(k);
1452 value_clear(fac);
1453 // value_clear(num);
1454 value_clear(tmp);
1455 value_clear(foobar);
1456 free(allfac.fac);
1457 return retval;
1458 }
1459 value_set_si(foobar, allfac.fac[i]);
1460 // value_division(num, InputList[0]->M->p[dim][dim], foobar);
1461 while (value_lt(k, foobar)) {
1462 Present = False;
1463 value_assign(fac, k);
1464 for (temp = *InputList; temp != NULL; temp = temp->next) {
1465 if (value_eq(temp->M->p[temp->M->NbRows - 1][temp->M->NbColumns - 1],
1466 fac)) {
1467 value_set_si(foobar, allfac.fac[i]);
1468 value_addto(fac, fac, foobar);
1469 if (value_ge(fac, (*InputList)->M->p[dim][dim])) {
1470 Present = True;
1471 break;
1472 }
1473 }
1474 if (value_gt(temp->M->p[temp->M->NbRows - 1][temp->M->NbColumns - 1],
1475 fac))
1476 break;
1477 }
1478 if (Present == True) {
1479 retval = True;
1480 if (*ResultList == NULL)
1481 *ResultList = temp = (LatticeUnion *)malloc(sizeof(LatticeUnion));
1482 else {
1483 for (temp = *ResultList; temp->next != NULL; temp = temp->next)
1484 ;
1485 temp->next = (LatticeUnion *)malloc(sizeof(LatticeUnion));
1486 temp = temp->next;
1487 }
1488 temp->M = Matrix_Copy(InputList[0]->M);
1489 temp->next = NULL;
1490 value_set_si(foobar, allfac.fac[i]);
1491 value_assign(temp->M->p[dim][dim], foobar);
1492 value_assign(temp->M->p[dim][width], k);
1493 value_set_si(temp->M->p[width][width], 1);
1494
1495 /* Deleting the Lattices from the curlist */
1496 value_assign(tmp, k);
1497 prev = NULL;
1498 temp = InputList[0];
1499 while (temp != NULL) {
1500 if (value_eq(temp->M->p[width][width], tmp)) {
1501 if (temp == InputList[0]) {
1502 prev = temp;
1503 temp = InputList[0] = temp->next;
1504 Matrix_Free(prev->M);
1505 free(prev);
1506 } else {
1507 prev->next = temp->next;
1508 Matrix_Free(temp->M);
1509 free(temp);
1510 temp = prev->next;
1511 }
1512 value_set_si(foobar, allfac.fac[i]);
1513 value_addto(tmp, tmp, foobar);
1514 } else {
1515 prev = temp;
1516 temp = temp->next;
1517 }
1518 }
1519 }
1520 value_increment(k, k);
1521 }
1522 }
1523 free(allfac.fac);
1524 value_clear(cnt);
1525 value_clear(aux);
1526 value_clear(k);
1527 value_clear(fac);
1528 // value_clear(num);
1529 value_clear(tmp);
1530 value_clear(foobar);
1531 return retval;
1532} /* Simplify */
1533
1534/*
1535 * This function is used in the qsort function in sorting the lattices. Given
1536 * two lattices 'A' and 'B', both in HNF, where A = [ [a11 0], [a21, a22, 0] .
1537 * .... [an1, .., ann] ] and B = [ [b11 0], [b21, b22, 0] ..[bn1, .., bnn] ],
1538 * then A < B, if there exists a pair <i,j> such that [aij < bij] and for every
1539 * other pair <i1, j1>, 0<=i1<i, 0<=j1<j [ai1j1 = bi1j1].
1540 */
1541static int LinearPartCompare(const void *A, const void *B) {
1542
1543 Lattice **L1, **L2;
1544 int i, j;
1545
1546 L1 = (Lattice **)A;
1547 L2 = (Lattice **)B;
1548
1549 for (i = 0; i < L1[0]->NbRows - 1; i++)
1550 for (j = 0; j <= i; j++) {
1551 if (value_gt(L1[0]->p[i][j], L2[0]->p[i][j]))
1552 return 1;
1553 if (value_lt(L1[0]->p[i][j], L2[0]->p[i][j]))
1554 return -1;
1555 }
1556 return 0;
1557} /* LinearPartCompare */
1558
1559/*
1560 * This function takes as input a List of Lattices and sorts them on the basis
1561 * of their Linear parts. It sorts in place, as a result of which the input
1562 * list is modified to the sorted order.
1563 */
1564static void LinearPartSort(LatticeUnion *Head) {
1565
1566 int cnt;
1567 Lattice **Latlist;
1568 LatticeUnion *temp;
1569
1570 cnt = 0;
1571 for (temp = Head; temp != NULL; temp = temp->next)
1572 cnt++;
1573
1574 Latlist = (Lattice **)malloc(sizeof(Lattice *) * cnt);
1575
1576 cnt = 0;
1577 for (temp = Head; temp != NULL; temp = temp->next)
1578 Latlist[cnt++] = temp->M;
1579
1580 qsort(Latlist, cnt, sizeof(Lattice *), LinearPartCompare);
1581
1582 cnt = 0;
1583 for (temp = Head; temp != NULL; temp = temp->next)
1584 temp->M = Latlist[cnt++];
1585
1586 free(Latlist);
1587 return;
1588} /* LinearPartSort */
1589
1590/*
1591 * This function is used in 'AfiinePartSort' in sorting the lattices with the
1592 * same linear part. GIven two lattices 'A' and 'B' with affineparts [a1 .. an]
1593 * and [b1 ... bn], then A < B if for some 0 < i <= n, ai < bi and for 0 < i1 <
1594 * i, ai1 = bi1.
1595 */
1596static int AffinePartCompare(const void *A, const void *B) {
1597
1598 int i;
1599 Lattice **L1, **L2;
1600
1601 L1 = (Lattice **)A;
1602 L2 = (Lattice **)B;
1603
1604 for (i = 0; i < L1[0]->NbRows; i++) {
1605 if (value_gt(L1[0]->p[i][L1[0]->NbColumns - 1],
1606 L2[0]->p[i][L2[0]->NbColumns - 1]))
1607 return 1;
1608
1609 if (value_lt(L1[0]->p[i][L1[0]->NbColumns - 1],
1610 L2[0]->p[i][L2[0]->NbColumns - 1]))
1611 return -1;
1612 }
1613 return 0;
1614} /* AffinePartCompare */
1615
1616/*
1617 * This function takes a list of lattices with the same linear part and sorts
1618 * them on the basis of their affine part. The sorting is done in place.
1619 */
1620static void AffinePartSort(LatticeUnion *List) {
1621
1622 int cnt;
1623 Lattice **LatList;
1624 LatticeUnion *tmp;
1625
1626 cnt = 0;
1627 for (tmp = List; tmp != NULL; tmp = tmp->next)
1628 cnt++;
1629
1630 LatList = malloc(sizeof(Lattice *) * cnt);
1631
1632 cnt = 0;
1633 for (tmp = List; tmp != NULL; tmp = tmp->next)
1634 LatList[cnt++] = tmp->M;
1635
1636 qsort(LatList, cnt, sizeof(Lattice *), AffinePartCompare);
1637
1638 cnt = 0;
1639 for (tmp = List; tmp != NULL; tmp = tmp->next)
1640 tmp->M = LatList[cnt++];
1641 free(LatList);
1642 return;
1643} /* AffinePartSort */
1644
1646
1647 int i;
1648
1649 if ((A == NULL) || (B == NULL))
1650 return False;
1651
1652 for (i = 0; i < A->M->NbRows - 1; i++)
1653 if (value_ne(A->M->p[i][A->M->NbColumns - 1],
1654 B->M->p[i][A->M->NbColumns - 1]))
1655 return False;
1656 return True;
1657} /* AlmostSameAffinePart */
1658
1659/*
1660 * This function takes a list of lattices having the same linear part and tries
1661 * to simplify these lattices. This may not be the only way of simplifying the
1662 * lattices. The function returns a list of partially simplified lattices and
1663 * also a flag to tell whether any simplification was performed at all.
1664 */
1666
1667 int i;
1668 Value aux;
1669 LatticeUnion *temp, *curr, *next;
1670 LatticeUnion *nextlist;
1671 Bool change = False, chng;
1672
1673 if (curlist == NULL)
1674 return False;
1675
1676 if (curlist->next == NULL) {
1677 curlist->next = newlist[0];
1678 newlist[0] = curlist;
1679 return False;
1680 }
1681
1682 value_init(aux);
1683 for (i = 0; i < curlist->M->NbRows - 1; i++) {
1684
1685 /* Interchanging the elements of the Affine part for easy computation
1686 of the sort (using qsort) */
1687
1688 for (temp = curlist; temp != NULL; temp = temp->next) {
1689 value_assign(aux,
1690 temp->M->p[temp->M->NbRows - 1][temp->M->NbColumns - 1]);
1691 value_assign(temp->M->p[temp->M->NbRows - 1][temp->M->NbColumns - 1],
1692 temp->M->p[i][temp->M->NbColumns - 1]);
1693 value_assign(temp->M->p[i][temp->M->NbColumns - 1], aux);
1694 }
1695 AffinePartSort(curlist);
1696 nextlist = NULL;
1697 curr = curlist;
1698 while (curr != NULL) {
1699 next = curr->next;
1700 if (!AlmostSameAffinePart(curr, next)) {
1701 curr->next = NULL;
1702 chng = Simplify(&curlist, newlist, i);
1703 if (nextlist == NULL)
1704 nextlist = curlist;
1705 else {
1706 LatticeUnion *tmp;
1707 for (tmp = nextlist; tmp->next; tmp = tmp->next)
1708 ;
1709 tmp->next = curlist;
1710 }
1711 change = (Bool)(change | chng);
1712 curlist = next;
1713 }
1714 curr = next;
1715 }
1716 curlist = nextlist;
1717
1718 /* Interchanging the elements of the Affine part for easy computation
1719 of the sort (using qsort) */
1720
1721 for (temp = curlist; temp != NULL; temp = temp->next) {
1722 value_assign(aux,
1723 temp->M->p[temp->M->NbRows - 1][temp->M->NbColumns - 1]);
1724 value_assign(temp->M->p[temp->M->NbRows - 1][temp->M->NbColumns - 1],
1725 temp->M->p[i][temp->M->NbColumns - 1]);
1726 value_assign(temp->M->p[i][temp->M->NbColumns - 1], aux);
1727 }
1728 if (curlist == NULL)
1729 break;
1730 }
1731 if (*newlist == NULL)
1732 *newlist = nextlist;
1733 else {
1734 for (curr = *newlist; curr->next != NULL; curr = curr->next)
1735 ;
1736 curr->next = nextlist;
1737 }
1738 value_clear(aux);
1739 return change;
1740} /* AffinePartSimplify */
1741
1743
1744 int i, j;
1745 if ((A == NULL) || (B == NULL))
1746 return False;
1747 for (i = 0; i < A->M->NbRows - 1; i++)
1748 for (j = 0; j <= i; j++)
1749 if (value_ne(A->M->p[i][j], B->M->p[i][j]))
1750 return False;
1751
1752 return True;
1753} /* SameLinearPart */
1754
1755/*
1756 * Given a union of lattices, return a simplified list of lattices.
1757 */
1759 // fprintf(stderr, "Entering LatticeSimplify with:");
1760 // PrintLatticeUnion(stderr, P_VALUE_FMT, latlist);
1761 LatticeUnion *curlist, *nextlist;
1762 LatticeUnion *curr, *next;
1763 Bool change = True;
1764
1765 curlist = latlist;
1766 while (change == True) {
1767 change = False;
1768 LinearPartSort(curlist);
1769 curr = curlist;
1770 nextlist = NULL;
1771 while (curr != NULL) {
1772 next = curr->next;
1773 if (!SameLinearPart(curr, next)) {
1774 curr->next = NULL;
1775 change |= AffinePartSimplify(curlist, &nextlist);
1776 curlist = next;
1777 }
1778 curr = next;
1779 }
1780 curlist = nextlist;
1781 }
1782 return curlist;
1783} /* LatticeSimplify */
1784
1785int intcompare(const void *a, const void *b) {
1786
1787 int *i, *j;
1788
1789 i = (int *)a;
1790 j = (int *)b;
1791 if (*i > *j)
1792 return 1;
1793 if (*i < *j)
1794 return -1;
1795 return 0;
1796} /* intcompare */
1797
1798// compute the prime factors of n, including n itself if it is prime.
1800{
1801 int tabsize = 10;
1802 int div = 2;
1803 int rest = n;
1804 factor result;
1805
1806 // result init
1807 result.count = 0;
1808 result.fac = malloc(tabsize * sizeof(int));
1809
1810 while(div*div <= rest)
1811 {
1812 if(rest % div == 0)
1813 {
1814 // double the size of the array if necessary
1815 if(result.count == tabsize)
1816 {
1817 tabsize *= 2;
1818 result.fac = realloc(result.fac, tabsize * sizeof(int));
1819 }
1820 // add div to the result
1821 result.fac[result.count++] = div;
1822 rest /= div;
1823 }
1824 else
1825 div += (1 + (1&div)); // 2, 3, 5, 7, 9, ...
1826 }
1827 if(rest != 1)
1828 {
1829 // add rest
1830 if(result.count == tabsize)
1831 {
1832 tabsize += 1;
1833 result.fac = realloc(result.fac, tabsize * sizeof(int));
1834 }
1835 result.fac[result.count++] = rest;
1836 }
1837 return result;
1838}
1839
1840
1842{
1843 // compute the prime decomposition (including n if it is prime)
1844 factor primes = prime_factors(n);
1845 factor result;
1846
1847 int size = (1<<(primes.count)); // max size of result = 2^(prime.count)
1848 result.count = 1;
1849 result.fac = malloc(size * sizeof(int));
1850 result.fac[0] = 1;
1851
1852 for(int mask=1; mask < size; mask++) {
1853 // multiply the prime factors for the bits that are 1 in the mask :)
1854 int val = 1;
1855 for(int bits=0, rest=mask; rest ; bits++, rest>>=1) {
1856 if((rest & 1))
1857 val *= primes.fac[bits];
1858 }
1859 // add val to res.fac only if it is not already there
1860 // (this will suppress duplicates, in case a prime factor is there several times)
1861 if(val > result.fac[result.count-1]) {
1862 result.fac[result.count++] = val;
1863 }
1864 }
1865 // always remove the last one, that is n.
1866 result.count--;
1867
1868 free(primes.fac);
1869 return result;
1870}
1871
1872
1873
1874// static factor allfactors(int num) {
1875
1876// int i, j, tmp;
1877// int noofelmts = 1;
1878// int *list, *newlist;
1879// int count;
1880// factor result;
1881// printf("%d\n",num);
1882
1883// list = (int *)malloc(sizeof(int));
1884// list[0] = 1;
1885
1886// tmp = num;
1887// for (i = 2; i <= polylib_sqrt(tmp); i++) {
1888// if ((tmp % i) == 0) {
1889// newlist = (int *)malloc(sizeof(int) * 2 * (noofelmts + 1));
1890// for (j = 0; j < noofelmts; j++)
1891// newlist[j] = list[j];
1892// newlist[j] = i;
1893// for (j = 0; j < noofelmts; j++)
1894// newlist[j + noofelmts + 1] = i * list[j];
1895// free(list);
1896// list = newlist;
1897// noofelmts = 2 * noofelmts + 1;
1898// tmp = tmp / i;
1899// i = 1;
1900// }
1901// }
1902
1903// if ((tmp != 0) && (tmp != num)) {
1904// newlist = (int *)malloc(sizeof(int) * 2 * (noofelmts + 1));
1905// for (j = 0; j < noofelmts; j++)
1906// newlist[j] = list[j];
1907// newlist[j] = tmp;
1908// for (j = 0; j < noofelmts; j++)
1909// newlist[j + noofelmts + 1] = tmp * list[j];
1910// free(list);
1911// list = newlist;
1912// noofelmts = 2 * noofelmts + 1;
1913// }
1914// qsort(list, noofelmts, sizeof(int), intcompare);
1915// count = 1;
1916// for (i = 1; i < noofelmts; i++)
1917// if (list[i] != list[i - 1])
1918// list[count++] = list[i];
1919// if (list[count - 1] == num)
1920// count--;
1921
1922// result.fac = (int *)malloc(sizeof(int) * count);
1923// result.count = count;
1924// for (i = 0; i < count; i++)
1925// result.fac[i] = list[i];
1926// free(list);
1927// return result;
1928// } /* allfactors */
1929
1930
1931/*
1932 * Takes into parameters two lattices A and B of the form:
1933 * A = A' | a B = B' | b
1934 * 0..0 | 1 0..0 | 1
1935 *
1936 * Copies them in a matrix (Tmp), used to calculate the left hermite,
1937 * the Lattice of size A->Nbrows x min(A->NbCols, B->NbCols) is the
1938 * intersection of A and B.
1939 *
1940 * If the result is empty return NULL.
1941 *
1942 */
1943Lattice* LatticeIntersection(Lattice* A, Lattice* B) {
1944 Lattice *Tmp, *H, *Res;
1945 if(A->NbRows != B->NbRows){
1946 errormsg1("LatticeIntersection", "dimincomp", "incompatible dimensions!");
1947 return NULL;
1948 }
1949 #ifdef LATINTER_DEBUG
1950 fprintf(stderr,"---Entering LatInter---\nMatrix A = ");
1951 Matrix_Print(stderr, P_VALUE_FMT, A);
1952 fprintf(stderr,"Matrix B = ");
1953 Matrix_Print(stderr, P_VALUE_FMT, B);
1954 #endif
1955
1956 // Tmp will be in the form:
1957 //
1958 // 1 0...0 | 1 0...0
1959 // a A' | b B'
1960 // -------------------------------
1961 // 1 0...0 | 0 .. 0
1962 // a A' | 0 .. 0
1963
1964 Tmp = Matrix_Alloc(A->NbRows*2, A->NbColumns+B->NbColumns);
1965
1966 if (!Tmp) {
1967 errormsg1("LatticeIntersection", "outofmem", "Not enough memory space!");
1968 return NULL;
1969 }
1970
1971 //copying A in Tmp:
1972
1973 // initalizing the top-left 1
1974 value_assign(Tmp->p[0][0], A->p[A->NbRows-1][A->NbColumns-1]);
1975 value_assign(Tmp->p[A->NbRows][0], A->p[A->NbRows-1][A->NbColumns-1]);
1976
1977 //copy of the constant vector a
1978 for(int i=1; i<A->NbRows; i++) {
1979 value_assign(Tmp->p[i][0], A->p[i-1][A->NbColumns-1]);
1980 value_assign(Tmp->p[i+A->NbRows][0], A->p[i-1][A->NbColumns-1]);
1981 }
1982 //copy of the matrix kernel A'
1983 for(int i = 1 ; i < A->NbRows; i++) {
1984 for(int j = 1; j < A->NbColumns; j++){
1985 value_assign(Tmp->p[i][j], A->p[i-1][j-1]);
1986 value_assign(Tmp->p[i+A->NbRows][j], A->p[i-1][j-1]);
1987 }
1988 }
1989
1990 // copying B into tmp:
1991 value_assign(Tmp->p[0][A->NbColumns], B->p[B->NbRows-1][B->NbColumns-1]);
1992
1993 //the constant b (last col of lattice)
1994 for (int i = 1; i < B->NbRows; i++) {
1995 value_assign(Tmp->p[i][A->NbColumns], B->p[i-1][B->NbColumns-1]);
1996 }
1997
1998 for (int i = 1; i < B->NbRows; i++){
1999 for (int j = 1; j < B->NbColumns; j++) {
2000 value_assign(Tmp->p[i][j+A->NbColumns], B->p[i-1][j-1]);
2001 }
2002 }
2003
2004 #ifdef LATINTER_DEBUG
2005 fprintf(stderr,"H init = ");
2006 Matrix_Print(stderr,P_VALUE_FMT, Tmp);
2007 #endif
2008
2009
2010 // left_hermite of the TMP
2011 // H is the matrix that contains the solution. it is of the form:
2012 //
2013 // H = D | 0 D is a square matrix
2014 // -----------------
2015 // X | 1 0.0
2016 // | r R
2017 //
2018 // with R r
2019 // 0..0 1 being our result
2020 // if the number above r is not 1 then the intersection is not integer
2021 // (no solution to the intersection)
2022
2023 left_hermite(Tmp, &H, NULL, NULL);
2024
2025
2026 #ifdef LATINTER_DEBUG
2027 fprintf(stderr,"\nH = ");
2028 Matrix_Print(stderr,P_VALUE_FMT,H);
2029 #endif
2030 Matrix_Free(Tmp);
2031
2032 // get the result. if the value on top-left of R is not 1 then we have an empty solution.
2033
2034 // what is the number of columns of zeros on the first NbRows Rows of H?
2035 // the matrix has A->NbColumns + B-> NbColumns columns.
2036 int nbcol = 0;
2037 for(int col_num = H->NbColumns-1 ; col_num >= 0; col_num--) {
2038 int i;
2039 for(i = 0; i < A->NbRows; i++) {
2040 if(value_notzero_p(H->p[i][col_num]))
2041 break;
2042 }
2043 if(i != A->NbRows) {
2044 // there is a non-zero value
2045 break;
2046 }
2047 nbcol++;
2048 }
2049
2050 if(value_notone_p(H->p[A->NbRows][H->NbColumns-nbcol])) {
2051 #ifdef LATINTER_DEBUG
2052 fprintf(stderr,"\nEmpty intersection\n");
2053 #endif
2054 Matrix_Free(H);
2055 return NULL;
2056 }
2057
2058 Res = Matrix_Alloc(A->NbRows, nbcol);
2059 for (int i = 0; i < Res->NbRows; i++) {
2060 for (int j = 0; j < Res->NbColumns; j++) {
2061 value_assign(Res->p[i][j], H->p[i + H->NbRows - Res->NbRows][j + H->NbColumns - Res->NbColumns]);
2062 }
2063 }
2064 Matrix_Free(H);
2065 // put Res in the proper affine form (didn't want to write a loop, had a pre-written function.)
2067
2068 #ifdef LATINTER_DEBUG
2069 fprintf(stderr, "\nLatticeIntersection result = ");
2070 Matrix_Print(stderr, P_VALUE_FMT, Res);
2071 fprintf(stderr,"---Exiting LatInter---\n\n");
2072 #endif
2073
2074 return Res;
2075}
2076
2077/*
2078 * Moves the constant part (last line and last row) as first line and row
2079 * of the matrix.
2080 * This is useful to compute the HNF and keeping the affine part as top-left
2081 * non-nul result. The same function can be called again to get the result
2082 * of affine HNF.
2083 * A = A' | c -> z | 0..0
2084 * 0..0 | z c | A'
2085 */
2087 if(A->NbRows == 0 || A->NbColumns == 0)
2088 return;
2089
2090 Value tmp;
2091 value_init(tmp);
2092 // puts the last column first:
2093 for(int i=0; i<A->NbRows; i++) {
2094 // on row i
2095 value_assign(tmp, A->p[i][A->NbColumns-1]); // tmp = last col value
2096 for(int j = A->NbColumns-1; j > 0; j--) {
2097 value_assign(A->p[i][j], A->p[i][j-1]); // [j] <- [j-1]
2098 }
2099 value_assign(A->p[i][0], tmp); // [0]<- tmp
2100 }
2101 // then puts the last row first:
2102 for(int j = 0; j < A->NbColumns; j++) {
2103 value_assign(tmp, A->p[A->NbRows-1][j]); // tmp = last row value
2104 for(int i = A->NbRows-1; i > 0; i--) {
2105 value_assign(A->p[i][j], A->p[i-1][j]); // [i] <- [i-1]
2106 }
2107 value_assign(A->p[0][j], tmp); // [0]<- tmp
2108 }
2109 value_clear(tmp);
2110} /* Matrix_Move_Homogeneous_Dim_First */
2111
2112
2113/*
2114 * Moves the constant part on a homogenous matrix (first line and first row) as last line and last row
2115 * of the matrix.
2116 * This is useful to compute the HNF and keeping the affine part as top-left
2117 * non-nul result. The same function can be called again to get the result
2118 * of affine HNF.
2119 * A = A' | c -> z | 0..0
2120 * 0..0 | z c | A'
2121 */
2123 if(A->NbRows == 0 || A->NbColumns == 0)
2124 return;
2125
2126 Value tmp;
2127 value_init(tmp);
2128 // puts the first col in the end
2129 for (int i = 0; i < A->NbRows; i++) {
2130 value_assign(tmp,A->p[i][0]); // tmp = first col value
2131 for (int j = 0; j < A->NbColumns-1; j++) {
2132 value_assign(A->p[i][j],A->p[i][j+1]); // [i] <- [i+1]
2133 }
2134 value_assign(A->p[i][A->NbColumns-1],tmp); //[last] <- tmp
2135 }
2136 for (int j = 0; j < A->NbColumns; j++) {
2137 value_assign(tmp,A->p[0][j]); // tmp first row value
2138 for (int i = 0; i < A->NbRows-1; i++) {
2139 value_assign(A->p[i][j],A->p[i+1][j]);
2140 }
2141 value_assign(A->p[A->NbRows-1][j],tmp);
2142 }
2143 value_clear(tmp);
2144} /* Matrix_Move_Homogeneous_Dim_Last */
2145
2147 Vector* pivot = Vector_Alloc(A->NbRows);
2148 int j=0;
2149 for(int i=0; i < A->NbRows ; i++) {
2150 if(value_zero_p(A->p[i][j])){
2151 value_set_si(pivot->p[i],1);
2152 }else {
2153 value_assign(pivot->p[i],A->p[i][j]);
2154 j++;
2155 }
2156 }
2157
2158 return pivot;
2159}
2160
2161
2162static LatticeUnion* generate_lattice_union_line(int line_nb, Vector* diag_A, Vector* diag_Inter, Lattice* Intersection, LatticeUnion *Result){
2163 Value cst;
2164 value_init(cst);
2165 for(LatticeUnion *L = Result; L; L=L->next){
2166 for(value_assign(cst,diag_A->p[line_nb]); value_lt(cst,diag_Inter->p[line_nb]); value_addto(cst, cst, diag_A->p[line_nb])){
2167 LatticeUnion* newResult = malloc(sizeof(*newResult));
2168 newResult->M = Matrix_Copy(L->M);
2169 newResult->next = Result;
2170 value_addto(newResult->M->p[line_nb][newResult->M->NbColumns-1],
2171 newResult->M->p[line_nb][newResult->M->NbColumns-1], cst);
2172
2173 value_modulus(newResult->M->p[line_nb][newResult->M->NbColumns-1],
2174 newResult->M->p[line_nb][newResult->M->NbColumns-1], diag_Inter->p[line_nb]);
2175 Result=newResult;
2176 }
2177 }
2178 value_clear(cst);
2179 return Result;
2180}
Bool isNormalLattice(Matrix *A)
Definition: Lattice.c:136
void PutRowLast(Matrix *X, int Rownumber)
Definition: Matop.c:140
void PutColumnLast(Matrix *X, int Columnnumber)
Definition: Matop.c:201
void PutRowFirst(Matrix *X, int Rownumber)
Definition: Matop.c:162
void PutColumnFirst(Matrix *X, int Columnnumber)
Definition: Matop.c:182
Matrix * Matrix_Copy(Matrix const *Src)
Definition: Matop.c:98
Lattice * EmptyLattice(int dimension)
Definition: NewLattice.c:81
LatticeUnion * LatticeUnion_Alloc(void)
Definition: NewLattice.c:46
Lattice * ExtractLinearPart(Lattice *A)
Definition: NewLattice.c:435
static void LinearPartSort(LatticeUnion *Head)
Definition: NewLattice.c:1564
static factor prime_factors(int n)
Definition: NewLattice.c:1799
Bool IsLattice(Matrix *m)
Definition: NewLattice.c:1334
Lattice * LatticeIntersection(Lattice *A, Lattice *B)
Definition: NewLattice.c:1943
void Matrix_Move_Homogeneous_Dim_First(Matrix *A)
Definition: NewLattice.c:2086
Vector * get_pivots(Matrix *A)
Definition: NewLattice.c:2146
static Bool Simplify(LatticeUnion **InputList, LatticeUnion **ResultList, int dim)
Definition: NewLattice.c:1401
void AffineHermite(Lattice *A, Lattice **H, Matrix **U)
Definition: NewLattice.c:161
LatticeUnion * LatticeDifference(Lattice *A, Lattice *B)
Definition: NewLattice.c:834
Bool isLinear(Lattice *A)
Definition: NewLattice.c:125
static factor allfactors(int num)
Definition: NewLattice.c:1841
Bool sameAffinepart(Lattice *A, Lattice *B)
Definition: NewLattice.c:60
static int AffinePartCompare(const void *A, const void *B)
Definition: NewLattice.c:1596
Lattice * Homogenise(Lattice *A, Bool Forward)
Definition: NewLattice.c:307
Bool isEmptyLattice(Lattice *A)
Definition: NewLattice.c:105
static Bool SameLinearPart(LatticeUnion *A, LatticeUnion *B)
Definition: NewLattice.c:1742
Lattice * ChangeLatticeDimension(Lattice *A, int dimension)
Definition: NewLattice.c:405
LatticeUnion * Lattice2LatticeUnion(Lattice *X, Lattice *Y)
Definition: NewLattice.c:686
static Bool AffinePartSimplify(LatticeUnion *curlist, LatticeUnion **newlist)
Definition: NewLattice.c:1665
static Bool AlmostSameAffinePart(LatticeUnion *A, LatticeUnion *B)
Definition: NewLattice.c:1645
static LatticeUnion * generate_lattice_union_line(int line_nb, Vector *diag_A, Vector *diag_Inter, Lattice *Intersection, LatticeUnion *Result)
Definition: NewLattice.c:2162
static void AffinePartSort(LatticeUnion *List)
Definition: NewLattice.c:1620
int intcompare(const void *a, const void *b)
Definition: NewLattice.c:1785
static int LinearPartCompare(const void *A, const void *B)
Definition: NewLattice.c:1541
Bool LatticeIncludes(Lattice *A, Lattice *B)
Definition: NewLattice.c:334
static void AddLattice(LatticeUnion *, Matrix *, Matrix *, Value, int)
Definition: NewLattice.c:1004
LatticeUnion * SplitLattice(Matrix *, Matrix *, Matrix *)
LatticeUnion * LatticeSimplify(LatticeUnion *latlist)
Definition: NewLattice.c:1758
void LatticeUnion_Free(LatticeUnion *Head)
Definition: NewLattice.c:30
void PrintLatticeUnion(FILE *fp, char *format, LatticeUnion *Head)
Definition: NewLattice.c:18
Bool sameLattice(Lattice *A, Lattice *B)
Definition: NewLattice.c:366
void Matrix_Move_Homogeneous_Dim_Last(Matrix *A)
Definition: NewLattice.c:2122
#define value_gt(v1, v2)
Definition: arithmetique.h:507
#define VALUE_TO_INT(val)
Definition: arithmetique.h:304
#define value_notzero_p(val)
Definition: arithmetique.h:579
#define value_notone_p(val)
Definition: arithmetique.h:581
#define value_ne(v1, v2)
Definition: arithmetique.h:506
#define value_zero_p(val)
Definition: arithmetique.h:578
#define value_assign(v1, v2)
Definition: arithmetique.h:485
#define value_increment(ref, val)
Definition: arithmetique.h:543
int Value
Definition: arithmetique.h:294
#define value_set_si(val, i)
Definition: arithmetique.h:486
#define value_addmul(ref, val1, val2)
Definition: arithmetique.h:542
#define value_eq(v1, v2)
Definition: arithmetique.h:505
#define value_clear(val)
Definition: arithmetique.h:488
#define value_division(ref, val1, val2)
Definition: arithmetique.h:550
#define value_multiply(ref, val1, val2)
Definition: arithmetique.h:546
#define value_lt(v1, v2)
Definition: arithmetique.h:509
#define value_modulus(ref, val1, val2)
Definition: arithmetique.h:552
#define value_addto(ref, val1, val2)
Definition: arithmetique.h:540
#define value_ge(v1, v2)
Definition: arithmetique.h:508
#define value_init(val)
Definition: arithmetique.h:484
void errormsg1(const char *f, const char *msgname, const char *msg)
Definition: errormsg.c:25
void Matrix_Product(Matrix *Mat1, Matrix *Mat2, Matrix *Mat3)
Definition: matrix.c:880
Matrix * Matrix_Alloc(unsigned NbRows, unsigned NbColumns)
Definition: matrix.c:24
int Matrix_Inverse(Matrix *Mat, Matrix *MatInv)
Definition: matrix.c:925
void Matrix_Print(FILE *Dst, const char *Format, Matrix *Mat)
Definition: matrix.c:118
void left_hermite(Matrix *A, Matrix **Hp, Matrix **Qp, Matrix **Up)
Definition: matrix.c:523
void Matrix_Free(Matrix *Mat)
Definition: matrix.c:69
static int m
Definition: polyparam.c:276
static int n
Definition: polyparam.c:278
Definition: types.h:82
Value * p
Definition: types.h:84
Definition: factors.c:5
int * fac
Definition: factors.c:7
int count
Definition: factors.c:6
Matrix * M
Definition: types.h:239
struct lattice_union * next
Definition: types.h:240
Definition: types.h:88
unsigned NbRows
Definition: types.h:89
Value ** p
Definition: types.h:90
unsigned NbColumns
Definition: types.h:89
Bool
Definition: types.h:45
@ True
Definition: types.h:45
@ False
Definition: types.h:45
#define P_VALUE_FMT
Definition: types.h:42
void Vector_Free(Vector *vector)
Definition: vector.c:187
Vector * Vector_Alloc(unsigned length)
Definition: vector.c:134