polylib 7.01
polyhedron.c
Go to the documentation of this file.
1/* polyhedron.c
2 COPYRIGHT
3 Both this software and its documentation are
4
5 Copyright 1993 by IRISA /Universite de Rennes I - France,
6 Copyright 1995,1996 by BYU, Provo, Utah
7 all rights reserved.
8
9*/
10
11/*
12
131997/12/02 - Olivier Albiez
14 Ce fichier contient les fonctions de la polylib de l'IRISA,
15 passees en 64bits.
16 La structure de la polylib a donc ete modifie pour permettre
17 le passage aux Value. La fonction Chernikova a ete reecrite.
18
19*/
20
21/*
22
231998/26/02 - Vincent Loechner
24 Ajout de nombreuses fonctions, a la fin de ce fichier,
25 pour les polyedres parametres 64 bits.
261998/16/03
27 #define DEBUG printf
28 tests out of memory
29 compatibilite avec la version de doran
30
31*/
32
33#undef POLY_DEBUG /* debug printf: general functions */
34#undef POLY_RR_DEBUG /* debug printf: Remove Redundants */
35#undef POLY_CH_DEBUG /* debug printf: Chernikova */
36
37#include <assert.h>
38#include <polylib/polylib.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
43#ifdef MAC_OS
44#define abs __abs
45#endif
46
47/* WSIZE is the number of bits in a word or int type */
48#define WSIZE (8 * sizeof(int))
49
50#define bexchange(a, b, l) \
51 { \
52 for(int _i = 0; _i < (l); _i++) { \
53 char _c; \
54 _c = *((char *)(a) + _i); \
55 *((char *)(a) + _i) = *((char *)(b) + _i); \
56 *((char *)(b) + _i) = _c; \
57 } \
58 }
59
60#define exchange(a, b, t) \
61 { \
62 (t) = (a); \
63 (a) = (b); \
64 (b) = (t); \
65 }
66
67/* errormsg1 is an external function which is usually supplied by the
68 calling program (e.g. Domlib.c, ReadAlpha, etc...).
69 See errormsg.c for an example of such a function. */
70
71void errormsg1(const char *f, const char *msgname, const char *msg);
72
73int Pol_status; /* error status after operations */
74
75/*
76 * The Saturation matrix is defined to be an integer (int type) matrix.
77 * It is a boolean matrix which has a row for every constraint and a column
78 * for every line or ray. The bits in the binary format of each integer in
79 * the stauration matrix stores the information whether the corresponding
80 * constraint is saturated by ray(line) or not.
81 */
82
83typedef struct {
84 unsigned int NbRows;
85 unsigned int NbColumns;
86 int **p;
87 int *p_init;
88} SatMatrix;
89
90/*
91 * Allocate memory space for a saturation matrix.
92 */
93static SatMatrix *SMAlloc(int rows, int cols) {
94 int **q, *p, i;
95 SatMatrix *result;
96
97 result = malloc(sizeof(SatMatrix));
98 if (!result) {
99 errormsg1("SMAlloc", "outofmem", "out of memory space");
100 return 0;
101 }
102 result->NbRows = rows;
103 result->NbColumns = cols;
104 if (rows == 0 || cols == 0) {
105 result->p = NULL;
106 result->p_init = NULL;
107 return result;
108 }
109 result->p = q = malloc(rows * sizeof(int *));
110 if (!result->p) {
111 errormsg1("SMAlloc", "outofmem", "out of memory space");
112 return 0;
113 }
114 result->p_init = p = malloc(rows * cols * sizeof(int));
115 if (!result->p_init) {
116 errormsg1("SMAlloc", "outofmem", "out of memory space");
117 return 0;
118 }
119 for (i = 0; i < rows; i++) {
120 *q++ = p;
121 p += cols;
122 }
123 return result;
124} /* SMAlloc */
125
126/*
127 * Free the memory space occupied by saturation matrix.
128 */
129static void SMFree(SatMatrix **matrix) {
130 SatMatrix *SM = *matrix;
131
132 if (SM) {
133 if (SM->p) {
134 free((char *)SM->p_init);
135 free((char *)SM->p);
136 }
137 free((char *)SM);
138 *matrix = NULL;
139 }
140} /* SMFree */
141
142/*
143 * Print the contents of a saturation matrix.
144 * This function is defined only for debugging purpose.
145 */
146#if defined(POLY_DEBUG) || defined(POLY_CH_DEBUG)
147static void SMPrint(SatMatrix *matrix) {
148
149 int *p;
150 int i, j;
151 unsigned NbRows, NbColumns;
152
153 fprintf(stderr, "%d %d\n", NbRows = matrix->NbRows,
154 NbColumns = matrix->NbColumns);
155 for (i = 0; i < NbRows; i++) {
156 p = *(matrix->p + i);
157 for (j = 0; j < NbColumns; j++)
158 fprintf(stderr, " %10X ", *p++);
159 fprintf(stderr, "\n");
160 }
161} /* SMPrint */
162#endif
163
164/*
165 * Compute the bitwise OR of two saturation matrices.
166 */
167static void SatVector_OR(int *p1, int *p2, int *p3, unsigned length) {
168
169 int *cp1, *cp2, *cp3;
170 int i;
171
172 cp1 = p1;
173 cp2 = p2;
174 cp3 = p3;
175 for (i = 0; i < length; i++) {
176 *cp3 = *cp1 | *cp2;
177 cp3++;
178 cp1++;
179 cp2++;
180 }
181} /* SatVector_OR */
182
183/*
184 * Copy a saturation matrix to another (macro definition).
185 */
186#define SMVector_Copy(p1, p2, length) \
187 memcpy((char *)(p2), (char *)(p1), (int)((length) * sizeof(int)))
188
189/*
190 * Initialize a saturation matrix with zeros (macro definition)
191 */
192#define SMVector_Init(p1, length) \
193 memset((char *)(p1), 0, (int)((length) * sizeof(int)))
194
195/*
196 * Defining operations on polyhedron --
197 */
198
199/*
200 * Vector p3 is a linear combination of two vectors (p1 and p2) such that
201 * p3[pos] is zero. First element of each vector (p1,p2,p3) is a status
202 * element and is not changed in p3. The value of 'pos' may be 0 however.
203 * The parameter 'length' does not include status element one.
204 */
205static void Combine(Value *p1, Value *p2, Value *p3, int pos, unsigned length) {
206
207 Value a1, a2, gcd;
208 Value abs_a1, abs_a2, neg_a1;
209
210 /* Initialize all the 'Value' variables */
211 value_init(a1);
212 value_init(a2);
213 value_init(gcd);
214 value_init(abs_a1);
215 value_init(abs_a2);
216 value_init(neg_a1);
217
218 /* a1 = p1[pos] */
219 value_assign(a1, p1[pos]);
220
221 /* a2 = p2[pos] */
222 value_assign(a2, p2[pos]);
223
224 /* a1_abs = |a1| */
225 value_absolute(abs_a1, a1);
226
227 /* a2_abs = |a2| */
228 value_absolute(abs_a2, a2);
229
230 /* gcd = Gcd(abs(a1), abs(a2)) */
231 value_gcd(gcd, abs_a1, abs_a2);
232
233 /* a1 = a1/gcd */
234 value_divexact(a1, a1, gcd);
235
236 /* a2 = a2/gcd */
237 value_divexact(a2, a2, gcd);
238
239 /* neg_a1 = -(a1) */
240 value_oppose(neg_a1, a1);
241
242 Vector_Combine(p1 + 1, p2 + 1, p3 + 1, a2, neg_a1, length);
243 Vector_Normalize(p3 + 1, length);
244
245 /* Clear all the 'Value' variables */
246 value_clear(a1);
247 value_clear(a2);
248 value_clear(gcd);
249 value_clear(abs_a1);
250 value_clear(abs_a2);
251 value_clear(neg_a1);
252
253 return;
254} /* Combine */
255
256/*
257 * Return the transpose of the saturation matrix 'Sat'. 'Mat' is a matrix
258 * of constraints and 'Ray' is a matrix of ray vectors and 'Sat' is the
259 * corresponding saturation matrix.
260 */
262
263 int i, j, sat_nbcolumns;
264 unsigned jx1, jx2, bx1, bx2;
265 SatMatrix *result;
266
267 if (Mat->NbRows != 0)
268 sat_nbcolumns = (Mat->NbRows - 1) / (sizeof(int) * 8) + 1;
269 else
270 sat_nbcolumns = 0;
271
272 result = SMAlloc(Ray->NbRows, sat_nbcolumns);
273 SMVector_Init(result->p_init, Ray->NbRows * sat_nbcolumns);
274
275 for (i = 0, jx1 = 0, bx1 = MSB; i < Ray->NbRows; i++) {
276 for (j = 0, jx2 = 0, bx2 = MSB; j < Mat->NbRows; j++) {
277 if (Sat->p[j][jx1] & bx1)
278 result->p[i][jx2] |= bx2;
279 NEXT(jx2, bx2);
280 }
281 NEXT(jx1, bx1);
282 }
283 return result;
284} /* TransformSat */
285
286/*
287 * Sort the rays (Ray, Sat) into three tiers as used in 'Chernikova' function:
288 * NbBid <= i < equal_bound : saturates the constraint
289 * equal_bound <= i < sup_bound : verifies the constraint
290 * sup_bound <= i < NbRay : does not verify
291 *
292 * 'Ray' is the matrix of rays and 'Sat' is the corresponding saturation
293 * matrix. (jx,bx) pair specify the constraint in the saturation matrix. The
294 * status element of the 'Ray' matrix holds the saturation value w.r.t the
295 * constraint specified by (jx,bx). Thus
296 * Ray->p[i][0] = 0 -> ray(i) saturates the constraint
297 * Ray->p[i][0] > 0 -> ray(i) verifies the constraint
298 * Ray->p[i][0] < 0 -> ray(i) doesn't verify the constraint
299 */
300static void RaySort(Matrix *Ray, SatMatrix *Sat, int NbBid, int NbRay,
301 int *equal_bound, int *sup_bound, unsigned RowSize1,
302 unsigned RowSize2, unsigned bx, unsigned jx) {
303 int inf_bound;
304 Value **uni_eq, **uni_sup, **uni_inf;
305 int **inc_eq, **inc_sup, **inc_inf;
306
307 /* 'uni_eq' points to the first ray in the ray matrix which verifies a
308 * constraint, 'inc_eq' is the corresponding pointer in saturation
309 * matrix. 'uni_inf' points to the first ray (from top) which doesn't
310 * verify a constraint, 'inc_inf' is the corresponding pointer in
311 * saturation matrix. 'uni_sup' scans the ray matrix and 'inc_sup' is
312 * the corresponding pointer in saturation matrix. 'inf_bound' holds the
313 * number of the first ray which does not verify the constraints.
314 */
315
316 *sup_bound = *equal_bound = NbBid;
317 uni_sup = uni_eq = Ray->p + NbBid;
318 inc_sup = inc_eq = Sat->p + NbBid;
319 inf_bound = NbRay;
320 uni_inf = Ray->p + NbRay;
321 inc_inf = Sat->p + NbRay;
322
323 while (inf_bound > *sup_bound) {
324 if (value_zero_p(**uni_sup)) { /* status = satisfy */
325 if (inc_eq != inc_sup) {
326 Vector_Exchange(*uni_eq, *uni_sup, RowSize1);
327 bexchange(*inc_eq, *inc_sup, RowSize2);
328 }
329 (*equal_bound)++;
330 uni_eq++;
331 inc_eq++;
332 (*sup_bound)++;
333 uni_sup++;
334 inc_sup++;
335 } else {
336 *((*inc_sup) + jx) |= bx;
337
338 /* if (**uni_sup<0) */
339 if (value_neg_p(**uni_sup)) { /* Status != verify */
340 inf_bound--;
341 uni_inf--;
342 inc_inf--;
343 if (inc_inf != inc_sup) {
344 Vector_Exchange(*uni_inf, *uni_sup, RowSize1);
345 bexchange(*inc_inf, *inc_sup, RowSize2);
346 }
347 } else { /* status == verify */
348 (*sup_bound)++;
349 uni_sup++;
350 inc_sup++;
351 }
352 }
353 }
354} /* RaySort */
355
356/*
357 * realloc a saturation matrix to a new size
358 */
359static void SatMatrix_Extend(SatMatrix *Sat, unsigned rows, unsigned cols)
360// static void SatMatrix_Extend(SatMatrix *Sat, Matrix *Mat, unsigned rows)
361{
362 int i;
363 // unsigned cols;
364 // cols = (Mat->NbRows - 1) / (sizeof(int) * 8) + 1;
365
366 Sat->p = realloc(Sat->p, rows * sizeof(int *));
367 if (!Sat->p) {
368 errormsg1("SatMatrix_Extend", "outofmem", "out of memory space");
369 return;
370 }
371 Sat->p_init = realloc(Sat->p_init, rows * cols * sizeof(int));
372 if (!Sat->p_init) {
373 errormsg1("SatMatrix_Extend", "outofmem", "out of memory space");
374 return;
375 }
376 for (i = 0; i < rows; ++i)
377 Sat->p[i] = Sat->p_init + (i * cols);
378 Sat->NbRows = rows;
379}
380
381/*
382 * Compute the dual of matrix 'Mat' and place it in matrix 'Ray'.'Mat'
383 * contains the constraints (equalities and inequalities) in rows and 'Ray'
384 * contains the ray space (lines and rays) in its rows. 'Sat' is a boolean
385 * saturation matrix defined as Sat(i,j)=0 if ray(i) saturates constraint(j),
386 * otherwise 1. The constraints in the 'Mat' matrix are processed starting at
387 * 'FirstConstraint', 'Ray' and 'Sat' matrices are changed accordingly.'NbBid'
388 * is the number of lines in the ray matrix and 'NbMaxRays' is the maximum
389 * number of rows (rays) permissible in the 'Ray' and 'Sat' matrix. Return 0
390 * if successful, otherwise return 1.
391 */
392static int Chernikova(Matrix *Mat, Matrix *Ray, SatMatrix *Sat, unsigned NbBid,
393 unsigned NbMaxRays, unsigned FirstConstraint,
394 unsigned dual) {
395 unsigned NbRay, Dimension, NbConstraints, RowSize1, RowSize2, sat_nbcolumns;
396 int sup_bound, equal_bound, index_non_zero, bound;
397 int i, j, k, l, redundant, rayonly, nbcommonconstraints;
398 int *Temp, aux;
399 int *ip1, *ip2;
400 unsigned bx, m, jx;
401 Value *p1, *p2, *p3;
402
403#ifdef POLY_CH_DEBUG
404 fprintf(stderr, "[Chernikova: Input]\nRay = ");
405 Matrix_Print(stderr, 0, Ray);
406 fprintf(stderr, "\nConstraints = ");
407 Matrix_Print(stderr, 0, Mat);
408 fprintf(stderr, "\nSat = ");
409 SMPrint(Sat);
410#endif
411
412 NbConstraints = Mat->NbRows;
413 NbRay = Ray->NbRows;
414 Dimension = Mat->NbColumns - 1; /* Homogeneous Dimension */
415 sat_nbcolumns = Sat->NbColumns;
416
417 RowSize1 = (Dimension + 1);
418 RowSize2 = sat_nbcolumns * sizeof(int);
419
420 Temp = malloc(RowSize2);
421 if (!Temp) {
422 errormsg1("Chernikova", "outofmem", "out of memory space");
423 return 0;
424 }
426
427 /*
428 * In case of overflow, free the allocated memory!
429 * Rethrow upwards the stack to forward the exception.
430 */
431 free(Temp);
432 RETHROW();
433 }
434 TRY {
435 jx = FirstConstraint / WSIZE;
436 bx = MSB;
437 bx >>= FirstConstraint % WSIZE;
438 for (k = FirstConstraint; k < NbConstraints; k++) {
439
440 /* Set the status word of each ray[i] to ray[i] dot constraint[k] */
441 /* This is equivalent to evaluating each ray by the constraint[k] */
442 /* 'index_non_zero' is assigned the smallest ray index which does */
443 /* not saturate the constraint. */
444
445 index_non_zero = NbRay;
446 for (i = 0; i < NbRay; i++) {
447 p1 = Ray->p[i] + 1;
448 p2 = Mat->p[k] + 1;
449 p3 = Ray->p[i];
450
451 /* *p3 = *p1 * *p2 */
452 value_multiply(*p3, *p1, *p2);
453 p1++;
454 p2++;
455 for (j = 1; j < Dimension; j++) {
456 /* *p3 += *p1 * *p2 */
457 value_addmul(*p3, *p1, *p2);
458 p1++;
459 p2++;
460 }
461 if (value_notzero_p(*p3) && (i < index_non_zero))
462 index_non_zero = i;
463 }
464
465#ifdef POLY_CH_DEBUG
466 fprintf(stderr, "[Chernikova: A]\nRay = ");
467 Matrix_Print(stderr, 0, Ray);
468 fprintf(stderr, "\nConstraints = ");
469 Matrix_Print(stderr, 0, Mat);
470 fprintf(stderr, "\nSat = ");
471 SMPrint(Sat);
472#endif
473
474 /* Find a bidirectional ray z such that cz <> 0 */
475 if (index_non_zero < NbBid) {
476 /* Discard index_non_zero bidirectional ray */
477 NbBid--;
478 if (NbBid != index_non_zero)
479 Vector_Exchange(Ray->p[index_non_zero], Ray->p[NbBid], RowSize1);
480
481#ifdef POLY_CH_DEBUG
482 fprintf(stderr, "************\n");
483 for (i = 0; i < RowSize1; i++) {
484 value_print(stderr, P_VALUE_FMT, Ray->p[index_non_zero][i]);
485 }
486 fprintf(stderr, "\n******\n");
487 for (i = 0; i < RowSize1; i++) {
488 value_print(stderr, P_VALUE_FMT, Ray->p[NbBid][i]);
489 }
490 fprintf(stderr, "\n*******\n");
491#endif
492
493 /* Compute the new lineality space */
494 for (i = 0; i < NbBid; i++)
495 if (value_notzero_p(Ray->p[i][0]))
496 Combine(Ray->p[i], Ray->p[NbBid], Ray->p[i], 0, Dimension);
497
498 /* Add the positive part of index_non_zero bidirectional ray to */
499 /* the set of unidirectional rays */
500
501 if (value_neg_p(Ray->p[NbBid][0])) {
502 p1 = Ray->p[NbBid];
503 for (j = 0; j < Dimension + 1; j++) {
504 /* *p1 = - *p1 */
505 value_oppose(*p1, *p1);
506 p1++;
507 }
508 }
509
510#ifdef POLY_CH_DEBUG
511 fprintf(stderr, "[Chernikova: B]\nRay = ");
512 Ray->NbRows = NbRay;
513 Matrix_Print(stderr, 0, Ray);
514 fprintf(stderr, "\nConstraints = ");
515 Matrix_Print(stderr, 0, Mat);
516 fprintf(stderr, "\nSat = ");
517 SMPrint(Sat);
518#endif
519
520 /* Compute the new pointed cone */
521 for (i = NbBid + 1; i < NbRay; i++)
522 if (value_notzero_p(Ray->p[i][0]))
523 Combine(Ray->p[i], Ray->p[NbBid], Ray->p[i], 0, Dimension);
524
525 /* Add the new ray */
526 if (value_notzero_p(Mat->p[k][0])) { /* Constraint is an inequality */
527 for (j = 0; j < sat_nbcolumns; j++) {
528 Sat->p[NbBid][j] = 0; /* Saturation vec for new ray */
529 }
530 /* The new ray saturates everything except last inequality */
531 Sat->p[NbBid][jx] |= bx;
532 } else { /* Constraint is an equality */
533 if (--NbRay != NbBid) {
534 Vector_Copy(Ray->p[NbRay], Ray->p[NbBid], Dimension + 1);
535 SMVector_Copy(Sat->p[NbRay], Sat->p[NbBid], sat_nbcolumns);
536 }
537 }
538
539#ifdef POLY_CH_DEBUG
540 fprintf(stderr, "[Chernikova: C]\nRay = ");
541 Ray->NbRows = NbRay;
542 Matrix_Print(stderr, 0, Ray);
543 fprintf(stderr, "\nConstraints = ");
544 Matrix_Print(stderr, 0, Mat);
545 fprintf(stderr, "\nSat = ");
546 SMPrint(Sat);
547#endif
548
549 } else { /* If the new constraint satisfies all the rays */
550 RaySort(Ray, Sat, NbBid, NbRay, &equal_bound, &sup_bound, RowSize1,
551 RowSize2, bx, jx);
552
553 /* Sort the unidirectional rays into R0, R+, R- */
554 /* Ray
555 NbRay-> bound-> ________
556 | R- | R- ==> ray.eq < 0 (outside domain)
557 sup-> |------|
558 | R+ | R+ ==> ray.eq > 0 (inside
559 domain) equal-> |------| | R0 | R0 ==> ray.eq = 0 (on face of
560 domain) NbBid-> |______|
561 */
562
563#ifdef POLY_CH_DEBUG
564 fprintf(stderr, "[Chernikova: D]\nRay = ");
565 Ray->NbRows = NbRay;
566 Matrix_Print(stderr, 0, Ray);
567 fprintf(stderr, "\nConstraints = ");
568 Matrix_Print(stderr, 0, Mat);
569 fprintf(stderr, "\nSat = ");
570 SMPrint(Sat);
571#endif
572
573 /* Compute only the new pointed cone */
574 bound = NbRay;
575 for (i = equal_bound; i < sup_bound;
576 i++) /* for all pairs of R- and R+ */
577 for (j = sup_bound; j < bound; j++) {
578 /*--------------------------------------------------------------*/
579 /* Count the set of constraints saturated by R+ and R- */
580 /* Includes equalities, inequalities and the positivity constraint
581 */
582 /*-----------------------------------------------------------------*/
583
584 nbcommonconstraints = 0;
585 for (l = 0; l < jx; l++) {
586 aux = Temp[l] = Sat->p[i][l] | Sat->p[j][l];
587 for (m = MSB; m != 0; m >>= 1)
588 if (!(aux & m))
589 nbcommonconstraints++;
590 }
591 aux = Temp[jx] = Sat->p[i][jx] | Sat->p[j][jx];
592 for (m = MSB; m != bx; m >>= 1)
593 if (!(aux & m))
594 nbcommonconstraints++;
595 rayonly = (value_zero_p(Ray->p[i][Dimension]) &&
596 value_zero_p(Ray->p[j][Dimension]) && (dual == 0));
597 if (rayonly)
598 nbcommonconstraints++; /* account for pos constr */
599
600 /*-----------------------------------------------------------------*/
601 /* Adjacency Test : is combination [R-,R+] a non redundant ray? */
602 /*-----------------------------------------------------------------*/
603 if (nbcommonconstraints + NbBid >=
604 Dimension - 2) { /* Dimensionality check*/
605 /* Check whether a ray m saturates the same set of constraints */
606 redundant = 0;
607 for (m = NbBid; m < bound; m++)
608 if ((m != i) && (m != j)) {
609 /* Two rays (r+ r-) are never made redundant by a vertex */
610 /* because the positivity constraint saturates both rays */
611 /* but not the vertex */
612 if (rayonly && value_notzero_p(Ray->p[m][Dimension]))
613 continue;
614
615 /* (r+ r-) is redundant if there doesn't exist an equation */
616 /* which saturates both r+ and r- but not rm. */
617
618 ip1 = Temp;
619 ip2 = Sat->p[m];
620 for (l = 0; l <= jx; l++, ip2++, ip1++)
621 if (*ip2 & ~*ip1)
622 break;
623 if (l > jx) {
624 redundant = 1;
625 break;
626 }
627 }
628
629#ifdef POLY_CH_DEBUG
630 fprintf(stderr, "[Chernikova: E]\nRay = ");
631 Ray->NbRows = NbRay;
632 Matrix_Print(stderr, 0, Ray);
633 fprintf(stderr, "\nConstraints = ");
634 Matrix_Print(stderr, 0, Mat);
635 fprintf(stderr, "\nSat = ");
636 SMPrint(Sat);
637#endif
638
639 /*------------------------------------------------------------*/
640 /* Add new ray generated by [R+,R-] */
641 /*------------------------------------------------------------*/
642
643 if (!redundant) {
644 if (NbRay == NbMaxRays) {
645 int nc;
646 NbMaxRays *= 2;
647 Ray->NbRows = NbRay;
648 Matrix_Extend(Ray, NbMaxRays);
649 nc = (Mat->NbRows - 1) / (sizeof(int) * 8) + 1;
650 SatMatrix_Extend(Sat, NbMaxRays, nc);
651 }
652
653 /* Compute the new ray */
654 Combine(Ray->p[j], Ray->p[i], Ray->p[NbRay], 0, Dimension);
655 SatVector_OR(Sat->p[j], Sat->p[i], Sat->p[NbRay],
656 sat_nbcolumns);
657 Sat->p[NbRay][jx] &= ~bx;
658 NbRay++;
659 }
660 }
661 }
662
663#ifdef POLY_CH_DEBUG
664 fprintf(stderr,
665 "[Chernikova: F]\n"
666 "sup_bound=%d\n"
667 "equal_bound=%d\n"
668 "bound=%d\n"
669 "NbRay=%d\n"
670 "Dimension = %d\n"
671 "Ray = ",
672 sup_bound, equal_bound, bound, NbRay, Dimension);
673#endif
674#ifdef POLY_CH_DEBUG
675 Ray->NbRows = NbRay;
676 fprintf(stderr, "[Chernikova: F]:\nRay = ");
677 Matrix_Print(stderr, 0, Ray);
678#endif
679
680 /* Eliminates all non extremal rays */
681 /* j = (Mat->p[k][0]) ? */
682
683 j = (value_notzero_p(Mat->p[k][0])) ? sup_bound : equal_bound;
684
685 i = NbRay;
686#ifdef POLY_CH_DEBUG
687 fprintf(stderr, "i = %d\nj = %d \n", i, j);
688#endif
689 while ((j < bound) && (i > bound)) {
690 i--;
691 Vector_Copy(Ray->p[i], Ray->p[j], Dimension + 1);
692 SMVector_Copy(Sat->p[i], Sat->p[j], sat_nbcolumns);
693 j++;
694 }
695
696#ifdef POLY_CH_DEBUG
697 fprintf(stderr, "i = %d\nj = %d \n", i, j);
698 fprintf(stderr,
699 "[Chernikova: F]\n"
700 "sup_bound=%d\n"
701 "equal_bound=%d\n"
702 "bound=%d\n"
703 "NbRay=%d\n"
704 "Dimension = %d\n"
705 "Ray = ",
706 sup_bound, equal_bound, bound, NbRay, Dimension);
707#endif
708#ifdef POLY_CH_DEBUG
709 Ray->NbRows = NbRay;
710 fprintf(stderr, "[Chernikova: G]\nRay = ");
711 Matrix_Print(stderr, 0, Ray);
712#endif
713 if (j == bound)
714 NbRay = i;
715 else
716 NbRay = j;
717 }
718 NEXT(jx, bx);
719 }
720 Ray->NbRows = NbRay;
721 Sat->NbRows = NbRay;
722
723 } /* End of TRY */
724
726 free(Temp);
727
728#ifdef POLY_CH_DEBUG
729 fprintf(stderr, "[Chernikova: Output]\nRay = ");
730 Matrix_Print(stderr, 0, Ray);
731 fprintf(stderr, "\nConstraints = ");
732 Matrix_Print(stderr, 0, Mat);
733 fprintf(stderr, "\nSat = ");
734 SMPrint(Sat);
735#endif
736
737 return 0;
738} /* Chernikova */
739
740static int Gauss4(Value **p, int NbEq, int NbRows, int Dimension) {
741 int i, j, k, pivot, Rank;
742 int *column_index = NULL;
743 Value gcd;
744
745 value_init(gcd);
746 column_index = malloc(Dimension * sizeof(int));
747 if (!column_index) {
748 errormsg1("Gauss", "outofmem", "out of memory space");
749 value_clear(gcd);
750 return 0;
751 }
752 Rank = 0;
753
755 if (column_index)
756 free(column_index);
757 value_clear(gcd);
758 RETHROW();
759 }
760 TRY {
761
762 for (j = 1; j <= Dimension; j++) { /* for each column (except status) */
763 for (i = Rank; i < NbEq; i++) /* starting at diagonal, look down */
764
765 /* if (Mat->p[i][j] != 0) */
766 if (value_notzero_p(p[i][j]))
767 break; /* Find the first non zero element */
768 if (i != NbEq) { /* If a non-zero element is found? */
769 if (i != Rank) /* If it is found below the diagonal*/
770 Vector_Exchange(p[Rank] + 1, p[i] + 1, Dimension);
771
772 /* Normalize the pivot row by dividing it by the gcd */
773 /* gcd = Vector_Gcd(p[Rank]+1,Dimension) */
774 Vector_Gcd(p[Rank] + 1, Dimension, &gcd);
775
776 if (value_cmp_si(gcd, 2) >= 0)
777 Vector_AntiScale(p[Rank] + 1, p[Rank] + 1, gcd, Dimension);
778
779 if (value_neg_p(p[Rank][j]))
780 Vector_Oppose(p[Rank] + 1, p[Rank] + 1, Dimension);
781
782 pivot = i;
783 for (i = pivot + 1; i < NbEq;
784 i++) { /* Zero out the rest of the column */
785
786 /* if (Mat->p[i][j] != 0) */
787 if (value_notzero_p(p[i][j]))
788 Combine(p[i], p[Rank], p[i], j, Dimension);
789 }
790
791 /* For each row with non-zero entry Mat->p[Rank], store the column */
792 /* number 'j' in 'column_index[Rank]'. This information will be */
793 /* useful in performing Gaussian elimination backward step. */
794 column_index[Rank] = j;
795 Rank++;
796 }
797 } /* end of Gaussian elimination forward step */
798
799 /* Back Substitution -- normalize the system of equations */
800 for (k = Rank - 1; k >= 0; k--) {
801 j = column_index[k];
802
803 /* Normalize the equations */
804 for (i = 0; i < k; i++) {
805
806 /* if (Mat->p[i][j] != 0) */
807 if (value_notzero_p(p[i][j]))
808 Combine(p[i], p[k], p[i], j, Dimension);
809 }
810
811 /* Normalize the inequalities */
812 for (i = NbEq; i < NbRows; i++) {
813
814 /* if (Mat->p[i][j] != 0) */
815 if (value_notzero_p(p[i][j]))
816 Combine(p[i], p[k], p[i], j, Dimension);
817 }
818 }
819 } /* end of TRY */
820
822 free(column_index), column_index = NULL;
823
824 value_clear(gcd);
825 return Rank;
826} /* Chernikova */
827
828/*
829 * Compute a minimal system of equations using Gausian elimination method.
830 * 'Mat' is a matrix of constraints in which the first 'Nbeq' constraints
831 * are equations. The dimension of the homogenous system is 'Dimension'.
832 * The function returns the rank of the matrix 'Mat'.
833 */
834int Gauss(Matrix *Mat, int NbEq, int Dimension) {
835 int Rank;
836
837#ifdef POLY_DEBUG
838 fprintf(stderr, "[Gauss : Input]\nRay =");
839 Matrix_Print(stderr, 0, Mat);
840#endif
841
842 Rank = Gauss4(Mat->p, NbEq, Mat->NbRows, Dimension);
843
844#ifdef POLY_DEBUG
845 fprintf(stderr, "[Gauss : Output]\nRay =");
846 Matrix_Print(stderr, 0, Mat);
847#endif
848
849 return Rank;
850}
851
852/*
853 * Given 'Mat' - a matrix of equations and inequalities, 'Ray' - a matrix of
854 * lines and rays, 'Sat' - the corresponding saturation matrix, and 'Filter'
855 * - an array to mark (with 1) the non-redundant equalities and inequalities,
856 * compute a polyhedron composed of 'Mat' as constraint matrix and 'Ray' as
857 * ray matrix after reductions. This function is usually called as a follow
858 * up to 'Chernikova' to remove redundant constraints or rays.
859 * Note: (1) 'Chernikova' ensures that there are no redundant lines and rays.
860 * (2) The same function can be used with constraint and ray matrix used
861 interchangbly.
862 */
864 unsigned *Filter) {
865
866 int i, j, k;
867 unsigned Dimension, sat_nbcolumns, NbRay, NbConstraints, RowSize2,
868 *Trace = NULL, *bx = NULL, *jx = NULL, Dim_RaySpace, b;
869 unsigned NbBid, NbUni, NbEq, NbIneq;
870 unsigned NbBid2, NbUni2, NbEq2, NbIneq2;
871 int Redundant;
872 int aux, *temp2 = NULL;
873 Polyhedron *Pol = NULL;
874 Vector *temp1 = NULL;
875 unsigned Status;
876
877 Dimension = Mat->NbColumns - 1; /* Homogeneous Dimension */
878 NbRay = Ray->NbRows;
879 sat_nbcolumns = Sat->NbColumns;
880 NbConstraints = Mat->NbRows;
881 RowSize2 = sat_nbcolumns * sizeof(int);
882
883 temp1 = Vector_Alloc(Dimension + 1);
884
885 if (Filter) {
886 temp2 = (int *)calloc(sat_nbcolumns, sizeof(int));
887 if (!temp2)
888 goto oom;
889 }
890
891 /* Introduce indirections into saturation matrix 'Sat' to simplify */
892 /* processing with 'Sat' and allow easy exchanges of columns. */
893 bx = malloc(NbConstraints * sizeof(unsigned));
894 if (!bx)
895 goto oom;
896 jx = malloc(NbConstraints * sizeof(unsigned));
897 if (!jx)
898 goto oom;
900
901 Vector_Free(temp1);
902 if (temp2)
903 free(temp2);
904 if (bx)
905 free(bx);
906 if (jx)
907 free(jx);
908 if (Trace)
909 free(Trace);
910 if (Pol)
911 Polyhedron_Free(Pol);
912
913 RETHROW();
914 }
915 TRY {
916
917 /* For each constraint 'j' following mapping is defined to facilitate */
918 /* data access from saturation matrix 'Sat' :- */
919 /* (1) jx[j] -> floor[j/(8*sizeof(int))] */
920 /* (2) bx[j] -> bin(00..10..0) where position of 1 = j%(8*sizeof(int)) */
921
922 i = 0;
923 b = MSB;
924 for (j = 0; j < NbConstraints; j++) {
925 jx[j] = i;
926 bx[j] = b;
927 NEXT(i, b);
928 }
929
930 /*
931 * STEP(0): Count the number of vertices among the rays while initializing
932 * the ray status count to 0. If no vertices are found, quit the procedure
933 * and return an empty polyhedron as the result.
934 */
935
936 /* Reset the status element of each ray to zero. Store the number of */
937 /* vertices in 'aux'. */
938 aux = 0;
939 for (i = 0; i < NbRay; i++) {
940
941 /* Ray->p[i][0] = 0 */
942 value_set_si(Ray->p[i][0], 0);
943
944 /* If ray(i) is a vertex of the Inhomogenous system */
945 if (value_notzero_p(Ray->p[i][Dimension]))
946 aux++;
947 }
948
949 /* If no vertices, return an empty polyhedron. */
950 if (!aux)
951 goto empty;
952
953#ifdef POLY_RR_DEBUG
954 fprintf(stderr, "[Remove_redundants : Init]\nConstraints =");
955 Matrix_Print(stderr, 0, Mat);
956 fprintf(stderr, "\nRays =");
957 Matrix_Print(stderr, 0, Ray);
958#endif
959
960 /*
961 * STEP(1): Compute status counts for both rays and inequalities. For each
962 * constraint, count the number of vertices/rays saturated by that
963 * constraint, and put the result in the status words. At the same time,
964 * for each vertex/ray, count the number of constraints saturated by it.
965 * Delete any positivity constraints, but give rays credit in their status
966 * counts for saturating the positivity constraint.
967 */
968
969 NbEq = 0;
970
971#ifdef POLY_RR_DEBUG
972 fprintf(stderr, " j = ");
973#endif
974
975 for (j = 0; j < NbConstraints; j++) {
976
977#ifdef POLY_RR_DEBUG
978 fprintf(stderr, " %i ", j);
979 fflush(stderr);
980#endif
981
982 /* If constraint(j) is an equality, mark '1' in array 'temp2' */
983 if (Filter && value_zero_p(Mat->p[j][0]))
984 temp2[jx[j]] |= bx[j];
985 /* Reset the status element of each constraint to zero */
986 value_set_si(Mat->p[j][0], 0);
987
988 /* Identify and remove the positivity constraint 1>=0 */
989 i = First_Non_Zero(Mat->p[j] + 1, Dimension - 1);
990
991#ifdef POLY_RR_DEBUG
992 fprintf(stderr, "[Remove_redundants : IntoStep1]\nConstraints =");
993 Matrix_Print(stderr, 0, Mat);
994 fprintf(stderr, " j = %i \n", j);
995#endif
996
997 /* Check if constraint(j) is a positivity constraint, 1 >= 0, or if it */
998 /* is 1==0. If constraint(j) saturates all the rays of the matrix 'Ray'*/
999 /* then it is an equality. in this case, return an empty polyhedron. */
1000
1001 if (i == -1) {
1002 for (i = 0; i < NbRay; i++)
1003 if (!(Sat->p[i][jx[j]] & bx[j])) {
1004
1005 /* Mat->p[j][0]++ */
1006 value_increment(Mat->p[j][0], Mat->p[j][0]);
1007 }
1008
1009 /* if ((Mat->p[j][0] == NbRay) && : it is an equality
1010 (Mat->p[j][Dimension] != 0)) : and its not 0=0 */
1011 if ((value_cmp_si(Mat->p[j][0], NbRay) == 0) &&
1012 (value_notzero_p(Mat->p[j][Dimension])))
1013 goto empty;
1014
1015 /* Delete the positivity constraint */
1016 NbConstraints--;
1017 if (j == NbConstraints)
1018 continue;
1019 Vector_Exchange(Mat->p[j], Mat->p[NbConstraints], temp1->Size);
1020 exchange(jx[j], jx[NbConstraints], aux);
1021 exchange(bx[j], bx[NbConstraints], aux);
1022 j--;
1023 continue;
1024 }
1025
1026 /* Count the number of vertices/rays saturated by each constraint. At */
1027 /* the same time, count the number of constraints saturated by each ray*/
1028 for (i = 0; i < NbRay; i++)
1029 if (!(Sat->p[i][jx[j]] & bx[j])) {
1030
1031 /* Mat->p[j][0]++ */
1032 value_increment(Mat->p[j][0], Mat->p[j][0]);
1033
1034 /* Ray->p[i][0]++ */
1035 value_increment(Ray->p[i][0], Ray->p[i][0]);
1036 }
1037
1038 /* if (Mat->p[j][0]==NbRay) then increment the number of eq. count */
1039 if (value_cmp_si(Mat->p[j][0], NbRay) == 0)
1040 NbEq++; /* all vertices/rays are saturated */
1041 }
1042 Mat->NbRows = NbConstraints;
1043
1044 NbBid = 0;
1045 for (i = 0; i < NbRay; i++) {
1046
1047 /* Give rays credit for saturating the positivity constraint */
1048 if (value_zero_p(Ray->p[i][Dimension]))
1049
1050 /* Ray->p[i][0]++ */
1051 value_increment(Ray->p[i][0], Ray->p[i][0]);
1052
1053 /* If ray(i) saturates all the constraints including positivity */
1054 /* constraint then it is a bi-directional ray or line. Increment */
1055 /* 'NbBid' by one. */
1056
1057 /* if (Ray->p[i][0]==NbConstraints+1) */
1058 if (value_cmp_si(Ray->p[i][0], NbConstraints + 1) == 0)
1059 NbBid++;
1060 }
1061
1062#ifdef POLY_RR_DEBUG
1063 fprintf(stderr, "[Remove_redundants : Step1]\nConstraints =");
1064 Matrix_Print(stderr, 0, Mat);
1065 fprintf(stderr, "\nRay =");
1066 Matrix_Print(stderr, 0, Ray);
1067#endif
1068
1069 /*
1070 * STEP(2): Sort equalities to the top of constraint matrix 'Mat'. Detect
1071 * implicit equations such as y>=3; y<=3. Keep Inequalities in same
1072 * relative order. (Note: Equalities are constraints which saturate all of
1073 * the rays)
1074 */
1075
1076 for (i = 0; i < NbEq; i++) {
1077
1078 /* If constraint(i) doesn't saturate some ray, then it is an inequality*/
1079 if (value_cmp_si(Mat->p[i][0], NbRay) != 0) {
1080
1081 /* Skip over inequalities and find an equality */
1082 for (k = i + 1;
1083 k < NbConstraints && value_cmp_si(Mat->p[k][0], NbRay) != 0; k++)
1084 ;
1085 if (k >= NbConstraints) /* If none found then error */
1086 break;
1087
1088 /* Slide inequalities down the array 'Mat' and move equality up to */
1089 /* position 'i'. */
1090 Vector_Copy(Mat->p[k], temp1->p, temp1->Size);
1091 aux = jx[k];
1092 j = bx[k];
1093 for (; k > i; k--) {
1094 Vector_Copy(Mat->p[k - 1], Mat->p[k], temp1->Size);
1095 jx[k] = jx[k - 1];
1096 bx[k] = bx[k - 1];
1097 }
1098 Vector_Copy(temp1->p, Mat->p[i], temp1->Size);
1099 jx[i] = aux;
1100 bx[i] = j;
1101 }
1102 }
1103
1104 /* for SIMPLIFY */
1105 if (Filter) {
1106 Value mone;
1107 value_init(mone);
1108 value_set_si(mone, -1);
1109 /* Normalize equalities to have lexpositive coefficients to
1110 * be able to detect identical equalities.
1111 */
1112 for (i = 0; i < NbEq; i++) {
1113 int pos = First_Non_Zero(Mat->p[i] + 1, Dimension);
1114 if (pos == -1)
1115 continue;
1116 if (value_neg_p(Mat->p[i][1 + pos]))
1117 Vector_Scale(Mat->p[i] + 1, Mat->p[i] + 1, mone, Dimension);
1118 }
1119 value_clear(mone);
1120 for (i = 0; i < NbEq; i++) {
1121 /* Detect implicit constraints such as y>=3 and y<=3 */
1122 Redundant = 0;
1123 for (j = i + 1; j < NbEq; j++) {
1124 /* Only check equalities, i.e., 'temp2' has entry 1 */
1125 if (!(temp2[jx[j]] & bx[j]))
1126 continue;
1127 /* Redundant if both are same `and' constraint(j) was equality. */
1128 if (Vector_Equal(Mat->p[i] + 1, Mat->p[j] + 1, Dimension)) {
1129 Redundant = 1;
1130 break;
1131 }
1132 }
1133
1134 /* Set 'Filter' entry to 1 corresponding to the irredundant equality*/
1135 if (!Redundant)
1136 Filter[jx[i]] |= bx[i]; /* set flag */
1137 }
1138 }
1139
1140#ifdef POLY_RR_DEBUG
1141 fprintf(stderr, "[Remove_redundants : Step2]\nConstraints =");
1142 Matrix_Print(stderr, 0, Mat);
1143 fprintf(stderr, "\nRay =");
1144 Matrix_Print(stderr, 0, Ray);
1145#endif
1146
1147 /*
1148 * STEP(3): Perform Gaussian elimiation on the list of equalities. Obtain
1149 * a minimal basis by solving for as many variables as possible. Use this
1150 * solution to reduce the inequalities by eliminating as many variables as
1151 * possible. Set NbEq2 to the rank of the system of equalities.
1152 */
1153
1154 NbEq2 = Gauss(Mat, NbEq, Dimension);
1155
1156 /* If number of equalities is not less then the homogenous dimension, */
1157 /* return an empty polyhedron. */
1158
1159 if (NbEq2 >= Dimension)
1160 goto empty;
1161
1162#ifdef POLY_RR_DEBUG
1163 fprintf(stderr, "[Remove_redundants : Step3]\nConstraints =");
1164 Matrix_Print(stderr, 0, Mat);
1165 fprintf(stderr, "\nRay =");
1166 Matrix_Print(stderr, 0, Ray);
1167#endif
1168
1169 /*
1170 * STEP(4): Sort lines to the top of ray matrix 'Ray', leaving rays
1171 * afterwards. Detect implicit lines such as ray(1,2) and ray(-1,-2).
1172 * (Note: Lines are rays which saturate all of the constraints including
1173 * the positivity constraint 1>=0.
1174 */
1175
1176 for (i = 0, k = NbRay; i < NbBid && k > i; i++) {
1177 /* If ray(i) doesn't saturate some constraint then it is not a line */
1178 if (value_cmp_si(Ray->p[i][0], NbConstraints + 1) != 0) {
1179
1180 /* Skip over rays and vertices and find a line (bi-directional rays) */
1181 while (--k > i && value_cmp_si(Ray->p[k][0], NbConstraints + 1) != 0)
1182 ;
1183
1184 /* Exchange positions of ray(i) and line(k), thus sorting lines to */
1185 /* the top of matrix 'Ray'. */
1186 Vector_Exchange(Ray->p[i], Ray->p[k], temp1->Size);
1187 bexchange(Sat->p[i], Sat->p[k], RowSize2);
1188 }
1189 }
1190
1191#ifdef POLY_RR_DEBUG
1192 fprintf(stderr, "[Remove_redundants : Step4]\nConstraints =");
1193 Matrix_Print(stderr, 0, Mat);
1194 fprintf(stderr, "\nRay =");
1195 Matrix_Print(stderr, 0, Ray);
1196#endif
1197
1198 /*
1199 * STEP(5): Perform Gaussian elimination on the lineality space to obtain
1200 * a minimal basis of lines. Use this basis to reduce the representation
1201 * of the uniderectional rays. Set 'NbBid2' to the rank of the system of
1202 * lines.
1203 */
1204
1205 NbBid2 = Gauss(Ray, NbBid, Dimension);
1206
1207#ifdef POLY_RR_DEBUG
1208 fprintf(stderr, "[Remove_redundants : After Gauss]\nRay =");
1209 Matrix_Print(stderr, 0, Ray);
1210#endif
1211
1212 /* If number of lines is not less then the homogenous dimension, return */
1213 /* an empty polyhedron. */
1214 if (NbBid2 >= Dimension) {
1215 errormsg1("RemoveRedundants", "rmrdt", "dimension error");
1216 goto empty;
1217 }
1218
1219 /* Compute dimension of non-homogenous ray space */
1220 Dim_RaySpace = Dimension - 1 - NbEq2 - NbBid2;
1221
1222#ifdef POLY_RR_DEBUG
1223 fprintf(stderr, "[Remove_redundants : Step5]\nConstraints =");
1224 Matrix_Print(stderr, 0, Mat);
1225 fprintf(stderr, "\nRay =");
1226 Matrix_Print(stderr, 0, Ray);
1227#endif
1228
1229 /*
1230 * STEP(6): Do a first pass filter of inequalities and equality identifi-
1231 * cation. New positivity constraints may have been created by step(3).
1232 * Check for and eliminate them. Count the irredundant inequalities and
1233 * store count in 'NbIneq'.
1234 */
1235
1236 NbIneq = 0;
1237 for (j = 0; j < NbConstraints; j++) {
1238
1239 /* Identify and remove the positivity constraint 1>=0 */
1240 i = First_Non_Zero(Mat->p[j] + 1, Dimension - 1);
1241
1242 /* Check if constraint(j) is a positivity constraint, 1>= 0, or if it */
1243 /* is 1==0. */
1244 if (i == -1) {
1245 /* if ((Mat->p[j][0]==NbRay) && : it is an equality
1246 (Mat->p[j][Dimension]!=0)) : and its not 0=0 */
1247 if ((value_cmp_si(Mat->p[j][0], NbRay) == 0) &&
1248 (value_notzero_p(Mat->p[j][Dimension])))
1249 goto empty;
1250
1251 /* Set the positivity constraint redundant by setting status element */
1252 /* equal to 2. */
1253 value_set_si(Mat->p[j][0], 2);
1254 continue;
1255 }
1256
1257 Status = VALUE_TO_INT(Mat->p[j][0]);
1258
1259 if (Status == 0)
1260 value_set_si(Mat->p[j][0], 2); /* constraint is redundant */
1261 else if (Status < Dim_RaySpace)
1262 value_set_si(Mat->p[j][0], 2); /* constraint is redundant */
1263 else if (Status == NbRay)
1264 value_set_si(Mat->p[j][0], 0); /* constraint is an equality */
1265 else {
1266 NbIneq++; /* constraint is an irredundant inequality */
1267 value_set_si(Mat->p[j][0], 1); /* inequality */
1268 }
1269 }
1270
1271#ifdef POLY_RR_DEBUG
1272 fprintf(stderr, "[Remove_redundants : Step6]\nConstraints =");
1273 Matrix_Print(stderr, 0, Mat);
1274 fprintf(stderr, "\nRay =");
1275 Matrix_Print(stderr, 0, Ray);
1276#endif
1277
1278 /*
1279 * STEP(7): Do a first pass filter of rays and identification of lines.
1280 * Count the irredundant Rays and store count in 'NbUni'.
1281 */
1282
1283 NbUni = 0;
1284 for (j = 0; j < NbRay; j++) {
1285 Status = VALUE_TO_INT(Ray->p[j][0]);
1286
1287 if (Status < Dim_RaySpace)
1288 value_set_si(Ray->p[j][0], 2); /* ray is redundant */
1289 else if (Status == NbConstraints + 1)
1290 value_set_si(Ray->p[j][0], 0); /* ray is a line */
1291 else {
1292 NbUni++; /* an irredundant unidirectional ray. */
1293 value_set_si(Ray->p[j][0], 1); /* ray */
1294 }
1295 }
1296
1297 /*
1298 * STEP(8): Create the polyhedron (using approximate sizes).
1299 * Number of constraints = NbIneq + NbEq2 + 1
1300 * Number of rays = NbUni + NbBid2
1301 * Partially fill the polyhedron structure with the lines computed in step
1302 * 3 and the equalities computed in step 5.
1303 */
1304
1305 Pol = Polyhedron_Alloc(Dimension - 1, NbIneq + NbEq2 + 1, NbUni + NbBid2);
1306 if (!Pol) {
1308 goto oom;
1309 }
1310 Pol->NbBid = NbBid2;
1311 Pol->NbEq = NbEq2;
1312
1313 /* Partially fill the polyhedron structure */
1314 if (NbBid2)
1315 Vector_Copy(Ray->p[0], Pol->Ray[0], (Dimension + 1) * NbBid2);
1316 if (NbEq2)
1317 Vector_Copy(Mat->p[0], Pol->Constraint[0], (Dimension + 1) * NbEq2);
1318
1319#ifdef POLY_RR_DEBUG
1320 fprintf(stderr, "[Remove_redundants : Step7]\nConstraints =");
1321 Matrix_Print(stderr, 0, Mat);
1322 fprintf(stderr, "\nRay =");
1323 Matrix_Print(stderr, 0, Ray);
1324#endif
1325
1326 /*
1327 * STEP(9): Final Pass filter of inequalities and detection of redundant
1328 * inequalities. Redundant inequalities include:
1329 * (1) Inequalities which are always true, such as 1>=0,
1330 * (2) Redundant inequalities such as y>=4 given y>=3, or x>=1 given x=2.
1331 * (3) Redundant inequalities such as x+y>=5 given x>=3 and y>=2.
1332 * Every 'good' inequality must saturate at least 'Dimension' rays and be
1333 * unique.
1334 */
1335
1336 /* 'Trace' is a (1 X sat_nbcolumns) row matrix to hold the union of all */
1337 /* rows (corresponding to irredundant rays) of saturation matrix 'Sat' */
1338 /* which saturate some constraint 'j'. See figure below:- */
1339 Trace = malloc(sat_nbcolumns * sizeof(unsigned));
1340 if (!Trace) {
1342 goto oom;
1343 }
1344
1345 /* NbEq NbConstraints
1346 |----------->
1347 ___________j____
1348 | | |
1349 | Mat | |
1350 |___________|___|
1351 |
1352 NbRay ^ ________ ____________|____
1353 | |-------|--------|-----------0---|t1
1354 |i|-------|--------|-----------0---|t2
1355 | | Ray | | Sat |
1356 NbBid - |-------|--------|-----------0---|tk
1357 |_______| |_______________|
1358 |
1359 |
1360 -OR- (of rows t1,t2,...,tk)
1361 ________|___|____
1362 |_____Trace_0___|
1363
1364 */
1365
1366 NbIneq2 = 0;
1367 for (j = NbEq; j < NbConstraints; j++) {
1368
1369 /* if (Mat->p[j][0]==1) : non-redundant inequality */
1370 if (value_one_p(Mat->p[j][0])) {
1371 for (k = 0; k < sat_nbcolumns; k++)
1372 Trace[k] = 0; /* init Trace */
1373
1374 /* Compute Trace: the union of all rows of Sat where constraint(j) */
1375 /* is saturated. */
1376 for (i = NbBid; i < NbRay; i++)
1377
1378 /* if (Ray->p[i][0]==1) */
1379 if (value_one_p(Ray->p[i][0])) {
1380 if (!(Sat->p[i][jx[j]] & bx[j]))
1381 for (k = 0; k < sat_nbcolumns; k++)
1382 Trace[k] |= Sat->p[i][k];
1383 }
1384
1385 /* Only constraint(j) should saturate this set of vertices/rays. */
1386 /* If another non-redundant constraint also saturates this set, */
1387 /* then constraint(j) is redundant */
1388 Redundant = 0;
1389 for (i = NbEq; i < NbConstraints; i++) {
1390
1391 /* if ((Mat->p[i][0] ==1) && (i!=j) && !(Trace[jx[i]] & bx[i]) ) */
1392 if (value_one_p(Mat->p[i][0]) && (i != j) &&
1393 !(Trace[jx[i]] & bx[i])) {
1394 Redundant = 1;
1395 break;
1396 }
1397 }
1398 if (Redundant) {
1399 value_set_si(Mat->p[j][0], 2);
1400 } else {
1401 Vector_Copy(Mat->p[j], Pol->Constraint[NbEq2 + NbIneq2],
1402 Dimension + 1);
1403 if (Filter)
1404 Filter[jx[j]] |= bx[j]; /* for SIMPLIFY */
1405 NbIneq2++;
1406 }
1407 }
1408 }
1409 free(Trace), Trace = NULL;
1410
1411#ifdef POLY_RR_DEBUG
1412 fprintf(stderr, "[Remove_redundants : Step8]\nConstraints =");
1413 Matrix_Print(stderr, 0, Mat);
1414 fprintf(stderr, "\nRay =");
1415 Matrix_Print(stderr, 0, Ray);
1416#endif
1417
1418 /*
1419 * Step(10): Final pass filter of rays and detection of redundant rays.
1420 * The final list of rays is written to polyhedron.
1421 */
1422
1423 /* Trace is a (NbRay x 1) column matrix to hold the union of all columns */
1424 /* (corresponding to irredundant inequalities) of saturation matrix 'Sat'*/
1425 /* which saturate some ray 'i'. See figure below:- */
1426
1427 Trace = malloc(NbRay * sizeof(unsigned));
1428 if (!Trace) {
1430 goto oom;
1431 }
1432
1433 /* NbEq NbConstraints
1434 |---------->
1435 ___________j_____
1436 | | | | |
1437 | Mat | |
1438 |______|_|___|__|
1439 | | |
1440NbRay ^ _________ _______|_|___|__ ___
1441 | | | | | | | | |T|
1442 | | Ray | | Sat| | | | |r|
1443 | | | | | | | | |a| Trace =
1444Union[col(t1,t2,..,tk)] |i|-------|------>i 0 0 0 | |c| NbBid - |
1445| | | | | | |e|
1446 |_______| |______|_|___|__| |_|
1447 t1 t2 tk
1448 */
1449
1450 NbUni2 = 0;
1451
1452 /* Let 'aux' be the number of rays not vertices */
1453 aux = 0;
1454 for (i = NbBid; i < NbRay; i++) {
1455
1456 /* if (Ray->p[i][0]==1) */
1457 if (value_one_p(Ray->p[i][0])) {
1458
1459 /* if (Ray->p[i][Dimension]!=0) : vertex */
1460 if (value_notzero_p(Ray->p[i][Dimension]))
1461 for (k = NbBid; k < NbRay; k++)
1462 Trace[k] = 0; /* init Trace */
1463 else /* for ray */
1464
1465 /* Include the positivity constraint incidences for rays. The */
1466 /* positivity constraint saturates all rays and no vertices */
1467
1468 for (k = NbBid; k < NbRay; k++)
1469
1470 /* Trace[k]=(Ray->p[k][Dimension]!=0); */
1471 Trace[k] = (value_notzero_p(Ray->p[k][Dimension]));
1472
1473 /* Compute Trace: the union of all columns of Sat where ray(i) is */
1474 /* saturated. */
1475 for (j = NbEq; j < NbConstraints; j++)
1476
1477 /* if (Mat->p[j][0]==1) : inequality */
1478 if (value_one_p(Mat->p[j][0])) {
1479 if (!(Sat->p[i][jx[j]] & bx[j]))
1480 for (k = NbBid; k < NbRay; k++)
1481 Trace[k] |= Sat->p[k][jx[j]] & bx[j];
1482 }
1483
1484 /* If ray i does not saturate any inequalities (other than the */
1485 /* the positivity constraint, then it is the case that there is */
1486 /* only one inequality and that ray is its orthogonal */
1487
1488 /* only ray(i) should saturate this set of inequalities. If */
1489 /* another non-redundant ray also saturates this set, then ray(i)*/
1490 /* is redundant */
1491
1492 Redundant = 0;
1493 for (j = NbBid; j < NbRay; j++) {
1494
1495 /* if ( (Ray->p[j][0]==1) && (i!=j) && !Trace[j] ) */
1496 if (value_one_p(Ray->p[j][0]) && (i != j) && !Trace[j]) {
1497 Redundant = 1;
1498 break;
1499 }
1500 }
1501 if (Redundant)
1502 value_set_si(Ray->p[i][0], 2);
1503 else {
1504 Vector_Copy(Ray->p[i], Pol->Ray[NbBid2 + NbUni2], Dimension + 1);
1505 NbUni2++; /* Increment number of uni-directional rays */
1506
1507 /* if (Ray->p[i][Dimension]==0) */
1508 if (value_zero_p(Ray->p[i][Dimension]))
1509 aux++; /* Increment number of rays which are not vertices */
1510 }
1511 }
1512 }
1513
1514 /* Include the positivity constraint */
1515 if (aux >= Dim_RaySpace) {
1516 Vector_Set(Pol->Constraint[NbEq2 + NbIneq2], 0, Dimension + 1);
1517 value_set_si(Pol->Constraint[NbEq2 + NbIneq2][0], 1);
1518 value_set_si(Pol->Constraint[NbEq2 + NbIneq2][Dimension], 1);
1519 NbIneq2++;
1520 }
1521 } /* end of TRY */
1522
1524
1525#ifdef POLY_RR_DEBUG
1526 fprintf(stderr, "[Remove_redundants : Step9]\nConstraints =");
1527 Matrix_Print(stderr, 0, Mat);
1528 fprintf(stderr, "\nRay =");
1529 Matrix_Print(stderr, 0, Ray);
1530#endif
1531
1532 free(Trace);
1533 free(bx);
1534 free(jx);
1535 if (temp2)
1536 free(temp2);
1537
1538 Pol->NbConstraints = NbEq2 + NbIneq2;
1539 Pol->NbRays = NbBid2 + NbUni2;
1540
1541 Vector_Free(temp1);
1542 F_SET(Pol,
1544 return Pol;
1545
1546oom:
1547 errormsg1("Remove_Redundants", "outofmem", "out of memory space");
1548
1549 Vector_Free(temp1);
1550 if (temp2)
1551 free(temp2);
1552 if (bx)
1553 free(bx);
1554 if (jx)
1555 free(jx);
1556 return NULL;
1557
1558empty:
1559 Vector_Free(temp1);
1560 if (temp2)
1561 free(temp2);
1562 if (bx)
1563 free(bx);
1564 if (jx)
1565 free(jx);
1567 return Empty_Polyhedron(Dimension - 1);
1568} /* Remove_Redundants */
1569
1570/*
1571 * Allocate memory space for polyhedron.
1572 */
1573Polyhedron *Polyhedron_Alloc(unsigned Dimension, unsigned NbConstraints,
1574 unsigned NbRays) {
1575
1576 Polyhedron *Pol;
1577 unsigned NbRows, NbColumns;
1578 int i;
1579 Value *p, **q;
1580
1581 Pol = malloc(sizeof(Polyhedron));
1582 if (!Pol) {
1583 errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
1584 return 0;
1585 }
1586
1587 Pol->next = (Polyhedron *)0;
1588 Pol->Dimension = Dimension;
1589 Pol->NbConstraints = NbConstraints;
1590 Pol->NbRays = NbRays;
1591 Pol->NbEq = 0;
1592 Pol->NbBid = 0;
1593 Pol->flags = 0;
1594 NbRows = NbConstraints + NbRays;
1595 NbColumns = Dimension + 2;
1596
1597 q = malloc(NbRows * sizeof(Value *));
1598 if (!q) {
1599 errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
1600 return 0;
1601 }
1602 p = value_alloc(NbRows * NbColumns, &Pol->p_Init_size);
1603 if (!p) {
1604 free(q);
1605 errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
1606 return 0;
1607 }
1608 Pol->Constraint = q;
1609 Pol->Ray = q + NbConstraints;
1610 Pol->p_Init = p;
1611 for (i = 0; i < NbRows; i++) {
1612 *q++ = p;
1613 p += NbColumns;
1614 }
1615 return Pol;
1616} /* Polyhedron_Alloc */
1617
1618/*
1619 * Free the memory space occupied by the single polyhedron.
1620 */
1622 if (!Pol)
1623 return;
1624 value_free(Pol->p_Init, Pol->p_Init_size);
1625 free(Pol->Constraint);
1626 free(Pol);
1627 return;
1628} /* Polyhedron_Free */
1629
1630/*
1631 * Free the memory space occupied by the domain.
1632 */
1634 Polyhedron *Next;
1635
1636 for (; Pol; Pol = Next) {
1637 Next = Pol->next;
1638 Polyhedron_Free(Pol);
1639 }
1640 return;
1641} /* Domain_Free */
1642
1643/*
1644 * Print the contents of a polyhedron.
1645 */
1646void Polyhedron_Print(FILE *Dst, const char *Format, const Polyhedron *Pol) {
1647 unsigned Dimension, NbConstraints, NbRays;
1648 int i, j;
1649 Value *p;
1650
1651 if (!Pol) {
1652 fprintf(Dst, "<null polyhedron>\n");
1653 return;
1654 }
1655
1656 Dimension = Pol->Dimension + 2; /* Homogenous Dimension + status */
1657 NbConstraints = Pol->NbConstraints;
1658 NbRays = Pol->NbRays;
1659 fprintf(Dst, "POLYHEDRON Dimension:%d\n", Pol->Dimension);
1660 fprintf(Dst, " Constraints:%d Equations:%d Rays:%d Lines:%d\n",
1661 Pol->NbConstraints, Pol->NbEq, Pol->NbRays, Pol->NbBid);
1662 fprintf(Dst, "Constraints %d %d\n", NbConstraints, Dimension);
1663
1664 for (i = 0; i < NbConstraints; i++) {
1665 p = Pol->Constraint[i];
1666
1667 /* if (*p) */
1668 if (value_notzero_p(*p))
1669 fprintf(Dst, "Inequality: [");
1670 else
1671 fprintf(Dst, "Equality: [");
1672 p++;
1673 for (j = 1; j < Dimension; j++) {
1674 value_print(Dst, Format, *p++);
1675 }
1676 (void)fprintf(Dst, " ]\n");
1677 }
1678
1679 (void)fprintf(Dst, "Rays %d %d\n", NbRays, Dimension);
1680 for (i = 0; i < NbRays; i++) {
1681 p = Pol->Ray[i];
1682
1683 /* if (*p) */
1684 if (value_notzero_p(*p)) {
1685 p++;
1686
1687 /* if ( p[Dimension-2] ) */
1688 if (value_notzero_p(p[Dimension - 2]))
1689 fprintf(Dst, "Vertex: [");
1690 else
1691 fprintf(Dst, "Ray: [");
1692 } else {
1693 p++;
1694 fprintf(Dst, "Line: [");
1695 }
1696 for (j = 1; j < Dimension - 1; j++) {
1697 value_print(Dst, Format, *p++);
1698 }
1699
1700 /* if (*p) */
1701 if (value_notzero_p(*p)) {
1702 fprintf(Dst, " ]/");
1703 value_print(Dst, VALUE_FMT, *p);
1704 fprintf(Dst, "\n");
1705 } else
1706 fprintf(Dst, " ]\n");
1707 }
1708 if (Pol->next) {
1709 fprintf(Dst, "UNION ");
1710 Polyhedron_Print(Dst, Format, Pol->next);
1711 }
1712} /* Polyhedron_Print */
1713
1714/*
1715 * Print the contents of a polyhedron 'Pol' (used for debugging purpose).
1716 */
1718 Polyhedron_Print(stderr, "%4d", Pol);
1719} /* PolyPrint */
1720
1721/*
1722 * Create and return an empty polyhedron of non-homogenous dimension
1723 * 'Dimension'. An empty polyhedron is characterized by :-
1724 * (a) The dimension of the ray-space is -1.
1725 * (b) There is an over-constrained system of equations given by:
1726 * x=0, y=0, ...... z=0, 1=0
1727 */
1728Polyhedron *Empty_Polyhedron(unsigned Dimension) {
1729
1730 Polyhedron *Pol;
1731 int i;
1732
1733 Pol = Polyhedron_Alloc(Dimension, Dimension + 1, 0);
1734 if (!Pol) {
1735 errormsg1("Empty_Polyhedron", "outofmem", "out of memory space");
1736 return 0;
1737 }
1738 Vector_Set(Pol->Constraint[0], 0, (Dimension + 1) * (Dimension + 2));
1739 for (i = 0; i <= Dimension; i++) {
1740
1741 /* Pol->Constraint[i][i+1]=1 */
1742 value_set_si(Pol->Constraint[i][i + 1], 1);
1743 }
1744 Pol->NbEq = Dimension + 1;
1745 Pol->NbBid = 0;
1746 F_SET(Pol,
1748 return Pol;
1749} /* Empty_Polyhedron */
1750
1751/*
1752 * Create and return a universe polyhedron of non-homogenous dimension
1753 * 'Dimension'. A universe polyhedron is characterized by:
1754 * (a) The dimension of rayspace is zero.
1755 * (b) The dimension of lineality space is the dimension of the polyhedron.
1756 * (c) There is only one constraint (positivity constraint) in the constraint
1757 * set given by : 1 >= 0.
1758 * (d) The bi-directional ray set is the canonical set of vectors.
1759 * (e) The only vertex is the origin (0,0,0,....0).
1760 */
1761Polyhedron *Universe_Polyhedron(unsigned Dimension) {
1762
1763 Polyhedron *Pol;
1764 int i;
1765
1766 Pol = Polyhedron_Alloc(Dimension, 1, Dimension + 1);
1767 if (!Pol) {
1768 errormsg1("Universe_Polyhedron", "outofmem", "out of memory space");
1769 return 0;
1770 }
1771 Vector_Set(Pol->Constraint[0], 0, (Dimension + 2));
1772
1773 /* Pol->Constraint[0][0] = 1 */
1774 value_set_si(Pol->Constraint[0][0], 1);
1775
1776 /* Pol->Constraint[0][Dimension+1] = 1 */
1777 value_set_si(Pol->Constraint[0][Dimension + 1], 1);
1778 Vector_Set(Pol->Ray[0], 0, (Dimension + 1) * (Dimension + 2));
1779 for (i = 0; i <= Dimension; i++) {
1780
1781 /* Pol->Ray[i][i+1]=1 */
1782 value_set_si(Pol->Ray[i][i + 1], 1);
1783 }
1784
1785 /* Pol->Ray[Dimension][0] = 1 : vertex status */
1786 value_set_si(Pol->Ray[Dimension][0], 1);
1787 Pol->NbEq = 0;
1788 Pol->NbBid = Dimension;
1789 F_SET(Pol,
1791 return Pol;
1792} /* Universe_Polyhedron */
1793
1794/*
1795
1796Sort constraints and remove trivially redundant constraints.
1797
1798*/
1799static void SortConstraints(Matrix *Constraints, unsigned NbEq) {
1800 int i, j, k;
1801 for (i = NbEq; i < Constraints->NbRows; ++i) {
1802 int max = i;
1803 for (k = i + 1; k < Constraints->NbRows; ++k) {
1804 for (j = 1; j < Constraints->NbColumns - 1; ++j) {
1805 if (value_eq(Constraints->p[k][j], Constraints->p[max][j]))
1806 continue;
1807 if (value_abs_lt(Constraints->p[k][j], Constraints->p[max][j]))
1808 break;
1809 if (value_abs_eq(Constraints->p[k][j], Constraints->p[max][j]) &&
1810 value_pos_p(Constraints->p[max][j]))
1811 break;
1812 max = k;
1813 break;
1814 }
1815 /* equal, except for possibly the constant
1816 * => remove constraint with biggest constant
1817 */
1818 if (j == Constraints->NbColumns - 1) {
1819 if (value_lt(Constraints->p[k][j], Constraints->p[max][j]))
1820 Vector_Exchange(Constraints->p[k], Constraints->p[max],
1821 Constraints->NbColumns);
1822 Constraints->NbRows--;
1823 if (k < Constraints->NbRows)
1824 Vector_Exchange(Constraints->p[k],
1825 Constraints->p[Constraints->NbRows],
1826 Constraints->NbColumns);
1827 k--;
1828 }
1829 }
1830 if (max != i)
1831 Vector_Exchange(Constraints->p[max], Constraints->p[i],
1832 Constraints->NbColumns);
1833 }
1834}
1835
1836/*
1837
1838Search for trivial implicit equalities,
1839assuming the constraints have been sorted.
1840
1841*/
1842
1843static int ImplicitEqualities(Matrix *Constraints, unsigned NbEq) {
1844 int row, nrow, k;
1845 int found = 0;
1846 Value tmp;
1847 for (row = NbEq; row < Constraints->NbRows; ++row) {
1848 int d = First_Non_Zero(Constraints->p[row] + 1, Constraints->NbColumns - 2);
1849 if (d == -1) {
1850 /* -n >= 0 */
1851 if (value_neg_p(Constraints->p[row][Constraints->NbColumns - 1])) {
1852 value_set_si(Constraints->p[row][0], 0);
1853 found = 1;
1854 }
1855 break;
1856 }
1857 if (value_neg_p(Constraints->p[row][1 + d]))
1858 continue;
1859 for (nrow = row + 1; nrow < Constraints->NbRows; ++nrow) {
1860 if (value_zero_p(Constraints->p[nrow][1 + d]))
1861 break;
1862 if (value_pos_p(Constraints->p[nrow][1 + d]))
1863 continue;
1864 for (k = d; k < Constraints->NbColumns - 1; ++k) {
1865 if (value_abs_ne(Constraints->p[row][1 + k],
1866 Constraints->p[nrow][1 + k]))
1867 break;
1868 if (value_zero_p(Constraints->p[row][1 + k]))
1869 continue;
1870 if (value_eq(Constraints->p[row][1 + k], Constraints->p[nrow][1 + k]))
1871 break;
1872 }
1873 if (k == Constraints->NbColumns - 1) {
1874 value_set_si(Constraints->p[row][0], 0);
1875 value_set_si(Constraints->p[nrow][0], 0);
1876 found = 1;
1877 break;
1878 }
1879 if (k != Constraints->NbColumns - 2)
1880 continue;
1881 /* if the constants are such that
1882 * the sum c1+c2 is negative then the constraints conflict
1883 */
1884 value_init(tmp);
1885 value_addto(tmp, Constraints->p[row][1 + k], Constraints->p[nrow][1 + k]);
1886 if (value_sign(tmp) < 0) {
1887 Vector_Set(Constraints->p[row], 0, Constraints->NbColumns - 1);
1888 Vector_Set(Constraints->p[nrow], 0, Constraints->NbColumns - 1);
1889 value_set_si(Constraints->p[row][1 + k], 1);
1890 value_set_si(Constraints->p[nrow][1 + k], 1);
1891 found = 1;
1892 }
1893 value_clear(tmp);
1894 if (found)
1895 break;
1896 }
1897 }
1898 return found;
1899}
1900
1901/**
1902
1903Given a matrix of constraints ('Constraints'), construct and return a
1904polyhedron.
1905
1906@param Constraints Constraints (may be modified!)
1907@param NbMaxRays Estimated number of rays in the ray matrix of the
1908polyhedron.
1909@return newly allocated Polyhedron
1910
1911*/
1912Polyhedron *Constraints2Polyhedron(Matrix *Constraints, unsigned NbMaxRays) {
1913
1914 Polyhedron *Pol = NULL;
1915 Matrix *Ray = NULL;
1916 SatMatrix *Sat = NULL;
1917 unsigned Dimension, nbcolumns;
1918 int i;
1919
1920 Dimension = Constraints->NbColumns - 1; /* Homogeneous Dimension */
1921 if (Dimension < 1) {
1922 errormsg1("Constraints2Polyhedron", "invalidpoly",
1923 "invalid polyhedron dimension");
1924 return 0;
1925 }
1926
1927 /* If there is no constraint in the constraint matrix, return universe */
1928 /* polyhderon. */
1929 if (Constraints->NbRows == 0) {
1930 Pol = Universe_Polyhedron(Dimension - 1);
1931 return Pol;
1932 }
1933
1934 if (POL_ISSET(NbMaxRays, POL_NO_DUAL)) {
1935 unsigned NbEq;
1936 unsigned Rank;
1937 Value tmp;
1938 if (POL_ISSET(NbMaxRays, POL_INTEGER))
1939 value_init(tmp);
1940 do {
1941 NbEq = 0;
1942 /* Move equalities up */
1943 for (i = 0; i < Constraints->NbRows; ++i)
1944 if (value_zero_p(Constraints->p[i][0])) {
1945 if (POL_ISSET(NbMaxRays, POL_INTEGER) &&
1946 ConstraintSimplify(Constraints->p[i], Constraints->p[i],
1947 Dimension + 1, &tmp)) {
1948 value_clear(tmp);
1949 return Empty_Polyhedron(Dimension - 1);
1950 }
1951 /* detect 1 == 0, possibly created by ImplicitEqualities */
1952 if (First_Non_Zero(Constraints->p[i] + 1, Dimension - 1) == -1 &&
1953 value_notzero_p(Constraints->p[i][Dimension])) {
1954 if (POL_ISSET(NbMaxRays, POL_INTEGER))
1955 value_clear(tmp);
1956 return Empty_Polyhedron(Dimension - 1);
1957 }
1958 if (i != NbEq)
1959 ExchangeRows(Constraints, i, NbEq);
1960 ++NbEq;
1961 }
1962 Rank = Gauss(Constraints, NbEq, Dimension);
1963 if (POL_ISSET(NbMaxRays, POL_INTEGER))
1964 for (i = NbEq; i < Constraints->NbRows; ++i)
1965 ConstraintSimplify(Constraints->p[i], Constraints->p[i],
1966 Dimension + 1, &tmp);
1967 SortConstraints(Constraints, NbEq);
1968 } while (ImplicitEqualities(Constraints, NbEq));
1969 if (POL_ISSET(NbMaxRays, POL_INTEGER))
1970 value_clear(tmp);
1971 Pol =
1972 Polyhedron_Alloc(Dimension - 1, Constraints->NbRows - (NbEq - Rank), 0);
1973 if (Rank > 0)
1974 Vector_Copy(Constraints->p[0], Pol->Constraint[0],
1975 Rank * Constraints->NbColumns);
1976 if (Constraints->NbRows > NbEq)
1977 Vector_Copy(Constraints->p[NbEq], Pol->Constraint[Rank],
1978 (Constraints->NbRows - NbEq) * Constraints->NbColumns);
1979 Pol->NbEq = Rank;
1980 /* Make sure nobody accesses the rays by accident */
1981 Pol->Ray = 0;
1983 return Pol;
1984 }
1985
1986 if (Dimension > NbMaxRays)
1987 NbMaxRays = Dimension;
1988
1989 /*
1990 * Rather than adding a 'positivity constraint', it is better to
1991 * initialize the lineality space with line in each of the index
1992 * dimensions, but no line in the lambda dimension. Then initialize
1993 * the ray space with an origin at 0. This is what you get anyway,
1994 * after the positivity constraint has been processed by Chernikova
1995 * function.
1996 */
1997
1998 /* Allocate and initialize the Ray Space */
1999 Ray = Matrix_Alloc(NbMaxRays, Dimension + 1);
2000 if (!Ray) {
2001 errormsg1("Constraints2Polyhedron", "outofmem", "out of memory space");
2002 return 0;
2003 }
2004 Vector_Set(Ray->p_Init, 0, NbMaxRays * (Dimension + 1));
2005 for (i = 0; i < Dimension; i++) {
2006
2007 /* Ray->p[i][i+1] = 1 */
2008 value_set_si(Ray->p[i][i + 1], 1);
2009 }
2010
2011 /* Ray->p[Dimension-1][0] = 1 : mark for ray */
2012 value_set_si(Ray->p[Dimension - 1][0], 1);
2013 Ray->NbRows = Dimension;
2014
2015 /* Initialize the Sat Matrix */
2016 nbcolumns = (Constraints->NbRows - 1) / (sizeof(int) * 8) + 1;
2017 Sat = SMAlloc(NbMaxRays, nbcolumns);
2018 SMVector_Init(Sat->p_init, Dimension * nbcolumns);
2019 Sat->NbRows = Dimension;
2020
2022
2023 /* In case of overflow, free the allocated memory and forward. */
2024 if (Sat)
2025 SMFree(&Sat);
2026 if (Ray)
2027 Matrix_Free(Ray);
2028 if (Pol)
2029 Polyhedron_Free(Pol);
2030 RETHROW();
2031 }
2032 TRY {
2033
2034 /* Create ray matrix 'Ray' from constraint matrix 'Constraints' */
2035 Chernikova(Constraints, Ray, Sat, Dimension - 1, NbMaxRays, 0, 0);
2036
2037#ifdef POLY_DEBUG
2038 fprintf(stderr, "[constraints2polyhedron]\nConstraints = ");
2039 Matrix_Print(stderr, 0, Constraints);
2040 fprintf(stderr, "\nRay = ");
2041 Matrix_Print(stderr, 0, Ray);
2042 fprintf(stderr, "\nSat = ");
2043 SMPrint(Sat);
2044#endif
2045
2046 /* Remove the redundant constraints and create the polyhedron */
2047 Pol = Remove_Redundants(Constraints, Ray, Sat, 0);
2048 } /* end of TRY */
2049
2051
2052#ifdef POLY_DEBUG
2053 fprintf(stderr, "\nPol = ");
2054 Polyhedron_Print(stderr, "%4d", Pol);
2055#endif
2056
2057 SMFree(&Sat), Sat = NULL;
2058 Matrix_Free(Ray), Ray = NULL;
2059 return Pol;
2060} /* Constraints2Polyhedron */
2061
2062#undef POLY_DEBUG
2063
2064/*
2065 * Given a polyhedron 'Pol', return a matrix of constraints.
2066 */
2068
2069 Matrix *Mat;
2070 unsigned NbConstraints, Dimension;
2071
2073
2074 NbConstraints = Pol->NbConstraints;
2075 Dimension = Pol->Dimension + 2;
2076 Mat = Matrix_Alloc(NbConstraints, Dimension);
2077 if (!Mat) {
2078 errormsg1("Polyhedron2Constraints", "outofmem", "out of memory space");
2079 return 0;
2080 }
2081 Vector_Copy(Pol->Constraint[0], Mat->p_Init, NbConstraints * Dimension);
2082 return Mat;
2083} /* Polyhedron2Constraints */
2084
2085/**
2086
2087Given a matrix of rays 'Ray', create and return a polyhedron.
2088
2089@param Ray Rays (may be modified!)
2090@param NbMaxConstrs Estimated number of constraints in the polyhedron.
2091@return newly allocated Polyhedron
2092
2093*/
2094Polyhedron *Rays2Polyhedron(Matrix *Ray, unsigned NbMaxConstrs) {
2095
2096 Polyhedron *Pol = NULL;
2097 Matrix *Mat = NULL;
2098 SatMatrix *Sat = NULL, *SatTranspose = NULL;
2099 unsigned Dimension, nbcolumns;
2100 int i;
2101
2102 Dimension = Ray->NbColumns - 1; /* Homogeneous Dimension */
2103 Sat = NULL;
2104 SatTranspose = NULL;
2105 Mat = NULL;
2106
2107 if (Ray->NbRows == 0) {
2108
2109 /* If there is no ray in the matrix 'Ray', return an empty polyhedron */
2110 Pol = Empty_Polyhedron(Dimension - 1);
2111 return (Pol);
2112 }
2113
2114 /* Ignore for now */
2115 if (POL_ISSET(NbMaxConstrs, POL_NO_DUAL))
2116 NbMaxConstrs = 0;
2117
2118 if (Dimension > NbMaxConstrs)
2119 NbMaxConstrs = Dimension;
2120
2121 /* Allocate space for constraint matrix 'Mat' */
2122 Mat = Matrix_Alloc(NbMaxConstrs, Dimension + 1);
2123 if (!Mat) {
2124 errormsg1("Rays2Polyhedron", "outofmem", "out of memory space");
2125 return 0;
2126 }
2127
2128 /* Initialize the constraint matrix 'Mat' */
2129 Vector_Set(Mat->p_Init, 0, NbMaxConstrs * (Dimension + 1));
2130 for (i = 0; i < Dimension; i++) {
2131
2132 /* Mat->p[i][i+1]=1 */
2133 value_set_si(Mat->p[i][i + 1], 1);
2134 }
2135
2136 /* Allocate and assign the saturation matrix. Remember we are using a */
2137 /* transposed saturation matrix referenced by (constraint,ray) pair. */
2138 Mat->NbRows = Dimension;
2139 nbcolumns = (Ray->NbRows - 1) / (sizeof(int) * 8) + 1;
2140 SatTranspose = SMAlloc(NbMaxConstrs, nbcolumns);
2141 SMVector_Init(SatTranspose->p[0], Dimension * nbcolumns);
2142 SatTranspose->NbRows = Dimension;
2143
2144#ifdef POLY_DEBUG
2145 fprintf(stderr, "[ray2polyhedron: Before]\nRay = ");
2146 Matrix_Print(stderr, 0, Ray);
2147 fprintf(stderr, "\nConstraints = ");
2148 Matrix_Print(stderr, 0, Mat);
2149 fprintf(stderr, "\nSatTranspose = ");
2150 SMPrint(SatTranspose);
2151#endif
2152
2154
2155 /* In case of overflow, free the allocated memory before forwarding
2156 * the exception.
2157 */
2158 if (SatTranspose)
2159 SMFree(&SatTranspose);
2160 if (Sat)
2161 SMFree(&Sat);
2162 if (Mat)
2163 Matrix_Free(Mat);
2164 if (Pol)
2165 Polyhedron_Free(Pol);
2166 RETHROW();
2167 }
2168 TRY {
2169
2170 /* Create constraint matrix 'Mat' from ray matrix 'Ray' */
2171 Chernikova(Ray, Mat, SatTranspose, Dimension, NbMaxConstrs, 0, 1);
2172
2173#ifdef POLY_DEBUG
2174 fprintf(stderr, "[ray2polyhedron: After]\nRay = ");
2175 Matrix_Print(stderr, 0, Ray);
2176 fprintf(stderr, "\nConstraints = ");
2177 Matrix_Print(stderr, 0, Mat);
2178 fprintf(stderr, "\nSatTranspose = ");
2179 SMPrint(SatTranspose);
2180#endif
2181
2182 /* Transform the saturation matrix 'SatTranspose' in the standard */
2183 /* format, that is, ray X constraint format. */
2184 Sat = TransformSat(Mat, Ray, SatTranspose);
2185
2186#ifdef POLY_DEBUG
2187 fprintf(stderr, "\nSat =");
2188 SMPrint(Sat);
2189#endif
2190
2191 SMFree(&SatTranspose), SatTranspose = NULL;
2192
2193 /* Remove redundant rays from the ray matrix 'Ray' */
2194 Pol = Remove_Redundants(Mat, Ray, Sat, 0);
2195 } /* of TRY */
2196
2198
2199#ifdef POLY_DEBUG
2200 fprintf(stderr, "\nPol = ");
2201 Polyhedron_Print(stderr, "%4d", Pol);
2202#endif
2203
2204 SMFree(&Sat);
2205 Matrix_Free(Mat);
2206 return Pol;
2207} /* Rays2Polyhedron */
2208
2209/*
2210 * Compute the dual representation if P only contains one representation.
2211 * Currently only handles the case where only the equalities are known.
2212 */
2214 if (!F_ISSET(P, POL_VALID))
2215 return;
2216
2218 return;
2219
2220 if (F_ISSET(P, POL_INEQUALITIES)) {
2221 Matrix M;
2222 Polyhedron tmp, *Q;
2223 /* Pretend P is a Matrix for a second */
2224 M.NbRows = P->NbConstraints;
2225 M.NbColumns = P->Dimension + 2;
2226 M.p_Init = P->p_Init;
2227 M.p = P->Constraint;
2228 Q = Constraints2Polyhedron(&M, 0);
2229
2230 /* Switch contents of P and Q ... */
2231 tmp = *Q;
2232 *Q = *P;
2233 *P = tmp;
2234 /* ... but keep the next pointer */
2235 P->next = Q->next;
2236 Polyhedron_Free(Q);
2237 return;
2238 }
2239
2240 /* other cases not handled yet */
2241 assert(0);
2242}
2243
2244/*
2245 * Build a saturation matrix from constraint matrix 'Mat' and ray matrix
2246 * 'Ray'. Only 'NbConstraints' constraint of matrix 'Mat' are considered
2247 * in creating the saturation matrix. 'NbMaxRays' is the maximum number
2248 * of rows (rays) allowed in the saturation matrix.
2249 * Vin100's stuff, for the polyparam vertices to work.
2250 */
2251static SatMatrix *BuildSat(Matrix *Mat, Matrix *Ray, unsigned NbConstraints,
2252 unsigned NbMaxRays) {
2253
2254 SatMatrix *Sat = NULL;
2255 int i, j, k, jx;
2256 Value *p1, *p2, *p3;
2257 unsigned Dimension, NbRay, bx, nbcolumns;
2258
2260 if (Sat)
2261 SMFree(&Sat);
2262 RETHROW();
2263 }
2264 TRY {
2265 NbRay = Ray->NbRows;
2266 Dimension = Mat->NbColumns - 1; /* Homogeneous Dimension */
2267
2268 /* Build the Sat matrix */
2269 nbcolumns = (Mat->NbRows - 1) / (sizeof(int) * 8) + 1;
2270 Sat = SMAlloc(NbMaxRays, nbcolumns);
2271 Sat->NbRows = NbRay;
2272 SMVector_Init(Sat->p_init, nbcolumns * NbRay);
2273 jx = 0;
2274 bx = MSB;
2275 for (k = 0; k < NbConstraints; k++) {
2276 for (i = 0; i < NbRay; i++) {
2277
2278 /* Compute the dot product of ray(i) and constraint(k) and */
2279 /* store in the status element of ray(i). */
2280 p1 = Ray->p[i] + 1;
2281 p2 = Mat->p[k] + 1;
2282 p3 = Ray->p[i];
2283 value_set_si(*p3, 0);
2284 for (j = 0; j < Dimension; j++) {
2285 value_addmul(*p3, *p1, *p2);
2286 p1++;
2287 p2++;
2288 }
2289 }
2290 for (j = 0; j < NbRay; j++) {
2291
2292 /* Set 1 in the saturation matrix if the ray doesn't saturate */
2293 /* the constraint, otherwise the entry is 0. */
2294 if (value_notzero_p(Ray->p[j][0]))
2295 Sat->p[j][jx] |= bx;
2296 }
2297 NEXT(jx, bx);
2298 }
2299 } /* end of TRY */
2300
2302 return Sat;
2303} /* BuildSat */
2304
2305/*
2306 * Add 'Nbconstraints' new constraints to polyhedron 'Pol'. Constraints are
2307 * pointed by 'Con' and the maximum allowed rays in the new polyhedron is
2308 * 'NbMaxRays'.
2309 * Returns a newly allocated Polyhedron.
2310 */
2311Polyhedron *AddConstraints(Value *Con, unsigned NbConstraints, Polyhedron *Pol,
2312 unsigned NbMaxRays) {
2313
2314 Polyhedron *NewPol = NULL;
2315 Matrix *Mat = NULL, *Ray = NULL;
2316 SatMatrix *Sat = NULL;
2317 unsigned NbRay, NbCon, Dimension;
2318
2319 if (NbConstraints == 0)
2320 return Polyhedron_Copy(Pol);
2321
2323 Dimension = Pol->Dimension + 2; /* Homogeneous Dimension + Status */
2324
2325 if (POL_ISSET(NbMaxRays, POL_NO_DUAL)) {
2326 NbCon = Pol->NbConstraints + NbConstraints;
2327
2328 Mat = Matrix_Alloc(NbCon, Dimension);
2329 if (!Mat) {
2330 errormsg1("AddConstraints", "outofmem", "out of memory space");
2331 return NULL;
2332 }
2333 Vector_Copy(Pol->Constraint[0], Mat->p[0], Pol->NbConstraints * Dimension);
2334 Vector_Copy(Con, Mat->p[Pol->NbConstraints], NbConstraints * Dimension);
2335 NewPol = Constraints2Polyhedron(Mat, NbMaxRays);
2336 Matrix_Free(Mat);
2337 return NewPol;
2338 }
2339
2341
2343 if (NewPol)
2344 Polyhedron_Free(NewPol);
2345 if (Mat)
2346 Matrix_Free(Mat);
2347 if (Ray)
2348 Matrix_Free(Ray);
2349 if (Sat)
2350 SMFree(&Sat);
2351 RETHROW();
2352 }
2353 TRY {
2354 NbRay = Pol->NbRays;
2355 NbCon = Pol->NbConstraints + NbConstraints;
2356
2357 if (NbRay > NbMaxRays)
2358 NbMaxRays = NbRay;
2359
2360 Mat = Matrix_Alloc(NbCon, Dimension);
2361 if (!Mat) {
2362 errormsg1("AddConstraints", "outofmem", "out of memory space");
2364 return 0;
2365 }
2366
2367 /* Copy constraints of polyhedron 'Pol' to matrix 'Mat' */
2368 Vector_Copy(Pol->Constraint[0], Mat->p[0], Pol->NbConstraints * Dimension);
2369
2370 /* Add the new constraints pointed by 'Con' to matrix 'Mat' */
2371 Vector_Copy(Con, Mat->p[Pol->NbConstraints], NbConstraints * Dimension);
2372
2373 /* Allocate space for ray matrix 'Ray' */
2374 Ray = Matrix_Alloc(NbMaxRays, Dimension);
2375 if (!Ray) {
2376 errormsg1("AddConstraints", "outofmem", "out of memory space");
2378 return 0;
2379 }
2380 Ray->NbRows = NbRay;
2381
2382 /* Copy rays of polyhedron 'Pol' to matrix 'Ray' */
2383 if (NbRay)
2384 Vector_Copy(Pol->Ray[0], Ray->p[0], NbRay * Dimension);
2385
2386 /* Create the saturation matrix 'Sat' from constraint matrix 'Mat' and */
2387 /* ray matrix 'Ray' . */
2388 Sat = BuildSat(Mat, Ray, Pol->NbConstraints, NbMaxRays);
2389
2390 /* Create the ray matrix 'Ray' from the constraint matrix 'Mat' */
2391 Pol_status =
2392 Chernikova(Mat, Ray, Sat, Pol->NbBid, NbMaxRays, Pol->NbConstraints, 0);
2393
2394 /* Remove redundant constraints from matrix 'Mat' */
2395 NewPol = Remove_Redundants(Mat, Ray, Sat, 0);
2396
2397 } /* end of TRY */
2398
2400 SMFree(&Sat);
2401 Matrix_Free(Ray);
2402 Matrix_Free(Mat);
2403 return NewPol;
2404} /* AddConstraints */
2405
2406/*
2407 * Return 1 if 'Pol1' includes (covers) 'Pol2', 0 otherwise.
2408 * Polyhedron 'A' includes polyhedron 'B' if the rays of 'B' saturate
2409 * the equalities and verify the inequalities of 'A'. Both 'Pol1' and
2410 * 'Pol2' have same dimensions.
2411 */
2413
2414 int Dimension = Pol1->Dimension + 1; /* Homogenous Dimension */
2415 int i, j, k;
2416 Value *p1, *p2, p3;
2417
2418 POL_ENSURE_FACETS(Pol1);
2419 POL_ENSURE_VERTICES(Pol1);
2420 POL_ENSURE_FACETS(Pol2);
2421 POL_ENSURE_VERTICES(Pol2);
2422
2423 value_init(p3);
2424 for (k = 0; k < Pol1->NbConstraints; k++) {
2425 for (i = 0; i < Pol2->NbRays; i++) {
2426
2427 /* Compute the dot product of ray(i) and constraint(k) and store in p3 */
2428 p1 = Pol2->Ray[i] + 1;
2429 p2 = Pol1->Constraint[k] + 1;
2430 value_set_si(p3, 0);
2431 for (j = 0; j < Dimension; j++) {
2432 value_addmul(p3, *p1, *p2);
2433 p1++;
2434 p2++;
2435 }
2436
2437 /* If (p3 < 0) or (p3 > 0 and (constraint(k) is equality
2438 or ray(i) is a line)), return 0 */
2439 if (value_neg_p(p3) ||
2440 (value_notzero_p(p3) && (value_zero_p(Pol1->Constraint[k][0]) ||
2441 (value_zero_p(Pol2->Ray[i][0]))))) {
2442 value_clear(p3);
2443 return 0;
2444 }
2445 }
2446 }
2447 value_clear(p3);
2448 return 1;
2449} /* PolyhedronIncludes */
2450
2451/*
2452 * Add Polyhedron 'Pol' to polyhedral domain 'PolDomain'.
2453 * If 'Pol' covers some polyhedron in the domain 'PolDomain', it is removed
2454 * from the domain and freed.
2455 * On the other hand if some polyhedron in the domain covers polyhedron
2456 * 'Pol' then 'Pol' is not included and freed.
2457 *
2458 * Consumes Pol and PolDomain to build the result (do not free).
2459 */
2461
2462 Polyhedron *p, *pnext, *p_domain_end = (Polyhedron *)0;
2463 int Redundant;
2464
2465 if (!Pol)
2466 return PolDomain;
2467 if (!PolDomain)
2468 return Pol;
2469
2470 POL_ENSURE_FACETS(Pol);
2472
2473 /* Check for emptiness of polyhedron 'Pol' */
2474 if (emptyQ(Pol)) {
2475 Polyhedron_Free(Pol);
2476 return PolDomain;
2477 }
2478
2479 POL_ENSURE_FACETS(PolDomain);
2480 POL_ENSURE_VERTICES(PolDomain);
2481
2482 /* Check for emptiness of polyhedral domain 'PolDomain' */
2483 if (emptyQ(PolDomain)) {
2484 Polyhedron_Free(PolDomain);
2485 return Pol;
2486 }
2487
2488 /* Test 'Pol' against the domain 'PolDomain' */
2489 Redundant = 0;
2490 for (p = PolDomain, PolDomain = (Polyhedron *)0; p; p = pnext) {
2491
2492 /* If 'Pol' covers 'p' */
2493 if (PolyhedronIncludes(Pol, p)) {
2494 /* free p */
2495 pnext = p->next;
2496 Polyhedron_Free(p);
2497 continue;
2498 }
2499
2500 /* Add polyhedron p to the new domain list */
2501 if (!PolDomain)
2502 PolDomain = p;
2503 else
2504 p_domain_end->next = p;
2505 p_domain_end = p;
2506
2507 /* If p covers Pol */
2508 if (PolyhedronIncludes(p, Pol)) {
2509 Redundant = 1;
2510 break;
2511 }
2512 pnext = p->next;
2513 }
2514 if (!Redundant) {
2515
2516 /* The whole list has been checked. Add new polyhedron 'Pol' to the */
2517 /* new domain list. */
2518 if (!PolDomain)
2519 PolDomain = Pol;
2520 else
2521 p_domain_end->next = Pol;
2522 } else {
2523
2524 /* The rest of the list is just inherited from p */
2525 Polyhedron_Free(Pol);
2526 }
2527 return PolDomain;
2528} /* AddPolyToDomain */
2529
2530/*
2531 * Given a polyhedron 'Pol' and a single constraint 'Con' and an integer 'Pass'
2532 * whose value ranges from 0 to 3, add the inverse of constraint 'Con' to the
2533 * constraint set of 'Pol' and return the new polyhedron. 'NbMaxRays' is the
2534 * maximum allowed rays in the new generated polyhedron.
2535 * If Pass == 0, add ( -constraint -1) >= 0
2536 * If Pass == 1, add ( +constraint -1) >= 0
2537 * If Pass == 2, add ( -constraint ) >= 0
2538 * If Pass == 3, add ( +constraint ) >= 0
2539 */
2540Polyhedron *SubConstraint(Value *Con, Polyhedron *Pol, unsigned NbMaxRays,
2541 int Pass) {
2542
2543 Polyhedron *NewPol = NULL;
2544 Matrix *Mat = NULL, *Ray = NULL;
2545 SatMatrix *Sat = NULL;
2546 unsigned NbRay, NbCon, NbEle1, Dimension;
2547 int i;
2548
2549 POL_ENSURE_FACETS(Pol);
2551
2553 if (NewPol)
2554 Polyhedron_Free(NewPol);
2555 if (Mat)
2556 Matrix_Free(Mat);
2557 if (Ray)
2558 Matrix_Free(Ray);
2559 if (Sat)
2560 SMFree(&Sat);
2561 RETHROW();
2562 }
2563 TRY {
2564
2565 /* If 'Con' is the positivity constraint, return Null */
2566 Dimension = Pol->Dimension + 1; /* Homogeneous Dimension */
2567 for (i = 1; i < Dimension; i++)
2568 if (value_notzero_p(Con[i]))
2569 break;
2570 if (i == Dimension) {
2572 return (Polyhedron *)0;
2573 }
2574
2575 NbRay = Pol->NbRays;
2576 NbCon = Pol->NbConstraints;
2577 Dimension = Pol->Dimension + 2; /* Homogeneous Dimension + Status */
2578 NbEle1 = NbCon * Dimension;
2579
2580 /* Ignore for now */
2581 if (POL_ISSET(NbMaxRays, POL_NO_DUAL))
2582 NbMaxRays = 0;
2583
2584 if (NbRay > NbMaxRays)
2585 NbMaxRays = NbRay;
2586
2587 Mat = Matrix_Alloc(NbCon + 1, Dimension);
2588 if (!Mat) {
2589 errormsg1("SubConstraint", "outofmem", "out of memory space");
2591 return 0;
2592 }
2593
2594 /* Set the constraints of Pol */
2595 Vector_Copy(Pol->Constraint[0], Mat->p[0], NbEle1);
2596
2597 /* Add the new constraint */
2598 value_set_si(Mat->p[NbCon][0], 1);
2599 if (!(Pass & 1))
2600 for (i = 1; i < Dimension; i++)
2601 value_oppose(Mat->p[NbCon][i], Con[i]);
2602 else
2603 for (i = 1; i < Dimension; i++)
2604 value_assign(Mat->p[NbCon][i], Con[i]);
2605 if (!(Pass & 2))
2606 value_decrement(Mat->p[NbCon][Dimension - 1],
2607 Mat->p[NbCon][Dimension - 1]);
2608
2609 /* Allocate the ray matrix. */
2610 Ray = Matrix_Alloc(NbMaxRays, Dimension);
2611 if (!Ray) {
2612 errormsg1("SubConstraint", "outofmem", "out of memory space");
2614 return 0;
2615 }
2616
2617 /* Initialize the ray matrix with the rays of polyhedron 'Pol' */
2618 Ray->NbRows = NbRay;
2619 if (NbRay)
2620 Vector_Copy(Pol->Ray[0], Ray->p[0], NbRay * Dimension);
2621
2622 /* Create the saturation matrix from the constraint matrix 'mat' and */
2623 /* ray matrix 'Ray'. */
2624 Sat = BuildSat(Mat, Ray, NbCon, NbMaxRays);
2625
2626 /* Create the ray matrix 'Ray' from consraint matrix 'Mat' */
2627 Pol_status = Chernikova(Mat, Ray, Sat, Pol->NbBid, NbMaxRays, NbCon, 0);
2628
2629 /* Remove redundant constraints from matrix 'Mat' */
2630 NewPol = Remove_Redundants(Mat, Ray, Sat, 0);
2631
2632 } /* end of TRY */
2633
2635
2636 SMFree(&Sat);
2637 Matrix_Free(Ray);
2638 Matrix_Free(Mat);
2639 return NewPol;
2640} /* SubConstraint */
2641
2642/*
2643
2644 Return the intersection of two polyhedral domains 'Pol1' and 'Pol2'.
2645 The maximum allowed rays in the new polyhedron generated is 'NbMaxRays'.
2646
2647*/
2649 unsigned NbMaxRays) {
2650
2651 Polyhedron *p1, *p2, *p3, *d;
2652
2653 if (!Pol1 || !Pol2)
2654 return (Polyhedron *)0;
2655 if (Pol1->Dimension != Pol2->Dimension) {
2656 errormsg1("DomainIntersection", "diffdim",
2657 "operation on different dimensions");
2658 return (Polyhedron *)0;
2659 }
2660
2661 /* For every polyhedron pair (p1,p2) where p1 belongs to domain Pol1 and */
2662 /* p2 belongs to domain Pol2, compute the intersection and add it to the */
2663 /* new domain 'd'. */
2664 d = (Polyhedron *)0;
2665 for (p1 = Pol1; p1; p1 = p1->next) {
2666 for (p2 = Pol2; p2; p2 = p2->next) {
2667 p3 = AddConstraints(p2->Constraint[0], p2->NbConstraints, p1, NbMaxRays);
2668 d = AddPolyToDomain(p3, d);
2669 }
2670 }
2671 if (!d)
2672 return Empty_Polyhedron(Pol1->Dimension);
2673 else
2674 return d;
2675
2676} /* DomainIntersection */
2677
2678/**
2679
2680 Given a polyhedron 'Pol', return a matrix of rays.
2681
2682*/
2684
2685 Matrix *Ray;
2686 unsigned NbRays, Dimension;
2687
2688 POL_ENSURE_POINTS(Pol);
2689
2690 NbRays = Pol->NbRays;
2691 Dimension = Pol->Dimension + 2; /* Homogeneous Dimension + Status */
2692 Ray = Matrix_Alloc(NbRays, Dimension);
2693 if (!Ray) {
2694 errormsg1("Polyhedron2Rays", "outofmem", "out of memory space");
2695 return 0;
2696 }
2697 Vector_Copy(Pol->Ray[0], Ray->p_Init, NbRays * Dimension);
2698 return Ray;
2699} /* Polyhedron2Rays */
2700
2701/**
2702
2703 Add 'NbAddedRays' rays to polyhedron 'Pol'. Rays are pointed by 'AddedRays'
2704 and the maximum allowed constraints in the new polyhedron is 'NbMaxConstrs'.
2705
2706*/
2707Polyhedron *AddRays(Value *AddedRays, unsigned NbAddedRays, Polyhedron *Pol,
2708 unsigned NbMaxConstrs) {
2709
2710 Polyhedron *NewPol = NULL;
2711 Matrix *Mat = NULL, *Ray = NULL;
2712 SatMatrix *Sat = NULL, *SatTranspose = NULL;
2713 unsigned NbCon, NbRay, NbEle1, Dimension;
2714
2715 POL_ENSURE_FACETS(Pol);
2717
2719 if (NewPol)
2720 Polyhedron_Free(NewPol);
2721 if (Mat)
2722 Matrix_Free(Mat);
2723 if (Ray)
2724 Matrix_Free(Ray);
2725 if (Sat)
2726 SMFree(&Sat);
2727 if (SatTranspose)
2728 SMFree(&SatTranspose);
2729 RETHROW();
2730 }
2731 TRY {
2732
2733 NbCon = Pol->NbConstraints;
2734 NbRay = Pol->NbRays;
2735 Dimension = Pol->Dimension + 2; /* Homogeneous Dimension + Status */
2736 NbEle1 = NbRay * Dimension;
2737
2738 Ray = Matrix_Alloc(NbAddedRays + NbRay, Dimension);
2739 if (!Ray) {
2740 errormsg1("AddRays", "outofmem", "out of memory space");
2742 return 0;
2743 }
2744
2745 /* Copy rays of polyhedron 'Pol' to matrix 'Ray' */
2746 if (NbRay)
2747 Vector_Copy(Pol->Ray[0], Ray->p_Init, NbEle1);
2748
2749 /* Add the new rays pointed by 'AddedRays' to matrix 'Ray' */
2750 Vector_Copy(AddedRays, Ray->p_Init + NbEle1, NbAddedRays * Dimension);
2751
2752 /* Ignore for now */
2753 if (POL_ISSET(NbMaxConstrs, POL_NO_DUAL))
2754 NbMaxConstrs = 0;
2755
2756 /* We need at least NbCon rows */
2757 if (NbMaxConstrs < NbCon)
2758 NbMaxConstrs = NbCon;
2759
2760 /* Allocate space for constraint matrix 'Mat' */
2761 Mat = Matrix_Alloc(NbMaxConstrs, Dimension);
2762 if (!Mat) {
2763 errormsg1("AddRays", "outofmem", "out of memory space");
2765 return 0;
2766 }
2767 Mat->NbRows = NbCon;
2768
2769 /* Copy constraints of polyhedron 'Pol' to matrix 'Mat' */
2770 Vector_Copy(Pol->Constraint[0], Mat->p_Init, NbCon * Dimension);
2771
2772 /* Create the saturation matrix 'SatTranspose' from constraint matrix */
2773 /* 'Mat' and ray matrix 'Ray'. Remember the saturation matrix is */
2774 /* referenced by (constraint,ray) pair */
2775 SatTranspose = BuildSat(Ray, Mat, NbRay, NbMaxConstrs);
2776
2777 /* Create the constraint matrix 'Mat' from the ray matrix 'Ray' */
2778 Pol_status =
2779 Chernikova(Ray, Mat, SatTranspose, Pol->NbEq, NbMaxConstrs, NbRay, 1);
2780
2781 /* Transform the saturation matrix 'SatTranspose' in the standard format */
2782 /* , that is, (ray X constraint) format. */
2783 Sat = TransformSat(Mat, Ray, SatTranspose);
2784 SMFree(&SatTranspose), SatTranspose = NULL;
2785
2786 /* Remove redundant rays from the ray matrix 'Ray' */
2787 NewPol = Remove_Redundants(Mat, Ray, Sat, 0);
2788
2789 SMFree(&Sat), Sat = NULL;
2790 Matrix_Free(Mat), Mat = NULL;
2791 Matrix_Free(Ray), Ray = NULL;
2792 } /* end of TRY */
2793
2795 return NewPol;
2796} /* AddRays */
2797
2798/**
2799
2800 Add rays pointed by 'Ray' to each and every polyhedron in the polyhedral
2801 domain 'Pol'. 'NbMaxConstrs' is maximum allowed constraints in the
2802 constraint set of a polyhedron.
2803
2804*/
2805Polyhedron *DomainAddRays(Polyhedron *Pol, Matrix *Ray, unsigned NbMaxConstrs) {
2806
2807 Polyhedron *PolA, *PolEndA, *p1, *p2, *p3;
2808 int Redundant;
2809
2810 if (!Pol)
2811 return (Polyhedron *)0;
2812 if (!Ray || Ray->NbRows == 0)
2813 return Domain_Copy(Pol);
2814 if (Pol->Dimension != Ray->NbColumns - 2) {
2815 errormsg1("DomainAddRays", "diffdim", "operation on different dimensions");
2816 return (Polyhedron *)0;
2817 }
2818
2819 /* Copy Pol to PolA */
2820 PolA = PolEndA = (Polyhedron *)0;
2821 for (p1 = Pol; p1; p1 = p1->next) {
2822 p3 = AddRays(Ray->p[0], Ray->NbRows, p1, NbMaxConstrs);
2823
2824 /* Does any component of PolA cover 'p3' ? */
2825 Redundant = 0;
2826 for (p2 = PolA; p2; p2 = p2->next) {
2827 if (PolyhedronIncludes(p2, p3)) { /* If p2 covers p3 */
2828 Redundant = 1;
2829 break;
2830 }
2831 }
2832
2833 /* If the new polyheron is not redundant, add it ('p3') to the list */
2834 if (Redundant)
2835 Polyhedron_Free(p3);
2836 else {
2837 if (!PolEndA)
2838 PolEndA = PolA = p3;
2839 else {
2840 PolEndA->next = p3;
2841 PolEndA = PolEndA->next;
2842 }
2843 }
2844 }
2845 return PolA;
2846} /* DomainAddRays */
2847
2848/*
2849 * Create a copy of the polyhedron 'Pol'
2850 */
2852
2853 Polyhedron *Pol1;
2854
2855 if (!Pol)
2856 return (Polyhedron *)0;
2857
2858 /* Allocate space for the new polyhedron */
2859 Pol1 = Polyhedron_Alloc(Pol->Dimension, Pol->NbConstraints, Pol->NbRays);
2860 if (!Pol1) {
2861 errormsg1("Polyhedron_Copy", "outofmem", "out of memory space");
2862 return 0;
2863 }
2864 if (Pol->NbConstraints)
2865 Vector_Copy(Pol->Constraint[0], Pol1->Constraint[0],
2866 Pol->NbConstraints * (Pol->Dimension + 2));
2867 if (Pol->NbRays)
2868 Vector_Copy(Pol->Ray[0], Pol1->Ray[0], Pol->NbRays * (Pol->Dimension + 2));
2869 Pol1->NbBid = Pol->NbBid;
2870 Pol1->NbEq = Pol->NbEq;
2871 Pol1->flags = Pol->flags;
2872 return Pol1;
2873} /* Polyhedron_Copy */
2874
2875/*
2876 * Create a copy of a polyhedral domain.
2877 */
2879
2880 Polyhedron *Pol1;
2881
2882 if (!Pol)
2883 return (Polyhedron *)0;
2884 Pol1 = Polyhedron_Copy(Pol);
2885 if (Pol->next)
2886 Pol1->next = Domain_Copy(Pol->next);
2887 return Pol1;
2888} /* Domain_Copy */
2889
2890/*
2891 * Given constraint number 'k' of a polyhedron, and an array 'Filter' to store
2892 * the non-redundant constraints of the polyhedron in bit-wise notation, and
2893 * a Matrix 'Sat', add the constraint 'k' in 'Filter' array. tmpR[i] stores the
2894 * number of constraints, other than those in 'Filter', which ray(i) saturates
2895 * or verifies. In case, ray(i) does not saturate or verify a constraint in
2896 * array 'Filter', it is assigned to -1. Similarly, tmpC[j] stores the number
2897 * of rays which constraint(j), if it doesn't belong to Filter, saturates or
2898 * verifies. If constraint(j) belongs to 'Filter', then tmpC[j] is assigned to
2899 * -1. 'NbConstraints' is the number of constraints in the constraint matrix of
2900 * the polyhedron.
2901 * NOTE: (1) 'Sat' is not the saturation matrix of the polyhedron. In fact,
2902 * entry in 'Sat' is set to 1 if ray(i) of polyhedron1 verifies or
2903 * saturates the constraint(j) of polyhedron2 and otherwise it is set
2904 * to 0. So here the difference with saturation matrix is in terms
2905 * definition and entries(1<->0) of the matrix 'Sat'.
2906 *
2907 * ALGORITHM:->
2908 * (1) Include constraint(k) in array 'Filter'.
2909 * (2) Set tmpC[k] to -1.
2910 * (3) For all ray(i) {
2911 * If ray(i) saturates or verifies constraint(k) then --(tmpR[i])
2912 * Else {
2913 * Discard ray(i) by assigning tmpR[i] = -1
2914 * Decrement tmpC[j] for all constraint(j) not in array 'Filter'.
2915 * }
2916 * }
2917 */
2918static void addToFilter(int k, unsigned *Filter, SatMatrix *Sat, int *tmpR,
2919 int *tmpC, int NbRays, int NbConstraints) {
2920
2921 int kj, i, j, jx;
2922 unsigned kb, bx;
2923
2924 /* Remove constraint k */
2925 kj = k / WSIZE;
2926 kb = MSB;
2927 kb >>= k % WSIZE;
2928 Filter[kj] |= kb;
2929 tmpC[k] = -1;
2930
2931 /* Remove rays excluded by constraint k */
2932 for (i = 0; i < NbRays; i++)
2933 if (tmpR[i] >= 0) {
2934 if (Sat->p[i][kj] & kb)
2935 tmpR[i]--; /* adjust included ray */
2936 else {
2937
2938 /* Constraint k excludes ray i -- delete ray i */
2939 tmpR[i] = -1;
2940
2941 /* Adjust non-deleted constraints */
2942 jx = 0;
2943 bx = MSB;
2944 for (j = 0; j < NbConstraints; j++) {
2945 if ((tmpC[j] >= 0) && (Sat->p[i][jx] & bx))
2946 tmpC[j]--;
2947 NEXT(jx, bx);
2948 }
2949 }
2950 }
2951} /* addToFilter */
2952
2953/*
2954 * Given polyhedra 'P1' and 'P2' such that their intersection is an empty
2955 * polyhedron, find the minimal set of constraints of 'P1' which contradict
2956 * all of the constraints of 'P2'. This is believed to be an NP-hard problem
2957 * and so a heuristic is employed to solve it in worst case. The heuristic is
2958 * to select in every turn that constraint of 'P1' which excludes most rays of
2959 * 'P2'. A bit in the binary format of an element of array 'Filter' is set to
2960 * 1 if the corresponding constraint is to be included in the minimal set of
2961 * constraints otherwise it is set to 0.
2962 */
2963static void FindSimple(Polyhedron *P1, Polyhedron *P2, unsigned *Filter,
2964 unsigned NbMaxRays)
2965{
2966 Matrix *Mat = NULL;
2967 SatMatrix *Sat = NULL;
2968 int i, j, k, jx, found;
2969 Value p3;
2970 unsigned Dimension, NbRays, NbConstraints, bx, nc;
2971 int NbConstraintsLeft;
2972 int *tmpC = NULL, *tmpR = NULL, previous_size = 0;
2973 Polyhedron *Pol = NULL, *Pol2 = NULL;
2974
2975 /* Initialize all the 'Value' variables */
2976 value_init(p3);
2977
2979 // free memory
2980 if (tmpC) free(tmpC);
2981 if (Mat) Matrix_Free(Mat);
2982 SMFree(&Sat);
2983 if (Pol2 && Pol2 != P2)
2984 Polyhedron_Free(Pol2);
2985 if (Pol && Pol != Pol2 && Pol != P2)
2986 Polyhedron_Free(Pol);
2987 value_clear(p3);
2988 RETHROW();
2989 }
2990 TRY {
2991 Dimension = P1->Dimension + 2; /* status + homogeneous Dimension */
2992 Mat = Matrix_Alloc(P1->NbConstraints, Dimension);
2993 Sat = SMAlloc(0, 0); // initial alloc
2994
2995 /* Post constraints in P1 already included by Filter */
2996 jx = 0;
2997 bx = MSB;
2998 Mat->NbRows = 0;
2999 NbConstraintsLeft = 0;
3000 for (k = 0; k < P1->NbConstraints; k++) {
3001 if (Filter[jx] & bx) {
3002 Vector_Copy(P1->Constraint[k], Mat->p[Mat->NbRows], Dimension);
3003 Mat->NbRows++;
3004 } else
3005 NbConstraintsLeft++;
3006 NEXT(jx, bx);
3007 }
3008 Pol2 = P2;
3009
3010 for (;;) {
3011 if (Mat->NbRows == 0)
3012 Pol = Polyhedron_Copy(Pol2);
3013 else {
3014 Pol = AddConstraints(Mat->p_Init, Mat->NbRows, Pol2, NbMaxRays);
3015 if (Pol2 != P2)
3016 Polyhedron_Free(Pol2), Pol2 = NULL;
3017 }
3018 if (emptyQ(Pol)) {
3019 // free memory
3020 Matrix_Free(Mat);
3021 Polyhedron_Free(Pol);
3022 SMFree(&Sat);
3023 if(tmpC) free(tmpC);
3024 value_clear(p3);
3025
3027 return;
3028 }
3029 Mat->NbRows = 0; /* Reset Mat */
3030 Pol2 = Pol;
3031
3032 /* It's not enough-- find some more constraints */
3033 Dimension = Pol->Dimension + 1; /* homogeneous Dimension */
3034 NbRays = Pol->NbRays;
3035 NbConstraints = P1->NbConstraints;
3036 if(NbConstraints + NbRays > previous_size) {
3037 // realloc array if necessary:
3038 tmpC = realloc(tmpC, (NbConstraints + NbRays) * sizeof(int));
3039 if (!tmpC) {
3040 errormsg1("FindSimple", "outofmem", "out of memory space");
3042
3043 /* Clear all the 'Value' variables */
3044 value_clear(p3);
3045 return;
3046 }
3047 previous_size = NbConstraints + NbRays;
3048 }
3049 tmpR = tmpC + NbConstraints;
3050 for(i = 0; i < NbConstraints + NbRays; i++) {
3051 tmpC[i] = 0;
3052 }
3053
3054 /* Build the Sat matrix */
3055 nc = (NbConstraints - 1) / (sizeof(int) * 8) + 1;
3056 // Sat = SMAlloc(NbRays, nc); // -> reuse memory
3057 SatMatrix_Extend(Sat, NbRays, nc);
3058 SMVector_Init(Sat->p_init, nc * NbRays);
3059
3060 jx = 0;
3061 bx = MSB;
3062 for (k = 0; k < NbConstraints; k++) {
3063 if (Filter[jx] & bx)
3064 tmpC[k] = -1;
3065 else
3066 for (i = 0; i < NbRays; i++) {
3067 Inner_Product(Pol->Ray[i] + 1, P1->Constraint[k] + 1, Dimension,
3068 &p3);
3069 if (value_zero_p(p3) ||
3070 (value_pos_p(p3) && value_notzero_p(P1->Constraint[k][0]))) {
3071 Sat->p[i][jx] |= bx; /* constraint includes ray, set flag */
3072 tmpR[i]++;
3073 tmpC[k]++;
3074 }
3075 }
3076 NEXT(jx, bx);
3077 }
3078
3079 do { /* find all of the essential constraints */
3080 found = 0;
3081 for (i = 0; i < NbRays; i++)
3082 if (tmpR[i] >= 0) {
3083 if ((tmpR[i] + 1 == NbConstraintsLeft)) {
3084
3085 /* Ray i is excluded by only one constraint... find it */
3086 jx = 0;
3087 bx = MSB;
3088 for (k = 0; k < NbConstraints; k++) {
3089 if ((tmpC[k] >= 0) && ((Sat->p[i][jx] & bx) == 0)) {
3090 addToFilter(k, Filter, Sat, tmpR, tmpC, NbRays,
3091 NbConstraints);
3092 Vector_Copy(P1->Constraint[k], Mat->p[Mat->NbRows],
3093 Dimension + 1);
3094 Mat->NbRows++;
3095 NbConstraintsLeft--;
3096 found = 1;
3097 break;
3098 }
3099 NEXT(jx, bx);
3100 }
3101 break;
3102 }
3103 }
3104 } while (found);
3105
3106 if (!Mat->NbRows) { /* Well then, just use a stupid heuristic */
3107 /* find the constraint which excludes the most */
3108 long int cmax;
3109
3110 cmax = (NbRays * NbConstraints + 1);
3111 j = -1;
3112 for (k = 0; k < NbConstraints; k++)
3113 if (tmpC[k] >= 0) {
3114 if (cmax > tmpC[k]) {
3115 cmax = tmpC[k];
3116 j = k;
3117 }
3118 }
3119 if (j < 0) {
3120 errormsg1("DomSimplify", "logerror", "logic error");
3121 }
3122 else {
3123 addToFilter(j, Filter, Sat, tmpR, tmpC, NbRays, NbConstraints);
3124 Vector_Copy(P1->Constraint[j], Mat->p[Mat->NbRows], Dimension + 1);
3125 Mat->NbRows++;
3126 NbConstraintsLeft--;
3127 }
3128 }
3129 } /* end forever */
3130 } /* end of TRY */
3131
3132 /* Clear all the 'Value' variables */
3133 value_clear(p3);
3134 if(tmpC) free(tmpC);
3135 SMFree(&Sat);
3137} /* FindSimple */
3138
3139/*
3140 * Return 0 if the intersection of Pol1 and Pol2 is empty, otherwise return 1.
3141 * If the intersection is non-empty, store the non-redundant constraints in
3142 * 'Filter' array. If the intersection is empty then store the smallest set of
3143 * constraints of 'Pol1' which on intersection with 'Pol2' gives empty set, in
3144 * 'Filter' array. 'NbMaxRays' is the maximum allowed rays in the intersection
3145 * of 'Pol1' and 'Pol2'.
3146 */
3148 unsigned *Filter, unsigned NbMaxRays) {
3149
3150 Polyhedron *Pol = NULL;
3151 Matrix *Mat = NULL, *Ray = NULL;
3152 SatMatrix *Sat = NULL;
3153 unsigned NbRay, NbCon, NbCon1, NbCon2, NbEle1, Dimension, notempty;
3154
3156 if (Pol)
3157 Polyhedron_Free(Pol);
3158 if (Mat)
3159 Matrix_Free(Mat);
3160 if (Ray)
3161 Matrix_Free(Ray);
3162 SMFree(&Sat);
3163 RETHROW();
3164 }
3165 TRY {
3166
3167 NbRay = Pol1->NbRays;
3168 NbCon1 = Pol1->NbConstraints;
3169 NbCon2 = Pol2->NbConstraints;
3170 NbCon = NbCon1 + NbCon2;
3171 Dimension = Pol1->Dimension + 2; /* Homogeneous Dimension + Status */
3172 NbEle1 = NbCon1 * Dimension;
3173
3174 /* Ignore for now */
3175 if (POL_ISSET(NbMaxRays, POL_NO_DUAL))
3176 NbMaxRays = 0;
3177
3178 if (NbRay > NbMaxRays)
3179 NbMaxRays = NbRay;
3180
3181 /* Allocate space for constraint matrix 'Mat' */
3182 Mat = Matrix_Alloc(NbCon, Dimension);
3183 if (!Mat) {
3184 errormsg1("SimplifyConstraints", "outofmem", "out of memory space");
3186 return 0;
3187 }
3188
3189 /* Copy constraints of 'Pol1' to matrix 'Mat' */
3190 Vector_Copy(Pol1->Constraint[0], Mat->p_Init, NbEle1);
3191
3192 /* Add constraints of 'Pol2' to matrix 'Mat'*/
3193 Vector_Copy(Pol2->Constraint[0], Mat->p_Init + NbEle1, NbCon2 * Dimension);
3194
3195 /* Allocate space for ray matrix 'Ray' */
3196 Ray = Matrix_Alloc(NbMaxRays, Dimension);
3197 if (!Ray) {
3198 errormsg1("SimplifyConstraints", "outofmem", "out of memory space");
3200 return 0;
3201 }
3202 Ray->NbRows = NbRay;
3203
3204 /* Copy rays of polyhedron 'Pol1' to matrix 'Ray' */
3205 Vector_Copy(Pol1->Ray[0], Ray->p_Init, NbRay * Dimension);
3206
3207 /* Create saturation matrix from constraint matrix 'Mat' and ray matrix */
3208 /* 'Ray'. */
3209 Sat = BuildSat(Mat, Ray, NbCon1, NbMaxRays);
3210
3211 /* Create the ray matrix 'Ray' from the constraint matrix 'Mat' */
3212 Pol_status = Chernikova(Mat, Ray, Sat, Pol1->NbBid, NbMaxRays, NbCon1, 0);
3213
3214 /* Remove redundant constraints from the constraint matrix 'Mat' */
3215 Pol = Remove_Redundants(Mat, Ray, Sat, Filter);
3216 notempty = 1;
3217 if (Filter && emptyQ(Pol)) {
3218 notempty = 0;
3219 FindSimple(Pol1, Pol2, Filter, NbMaxRays);
3220 }
3221 /* Polyhedron_Print(stderr,"%4d",Pol1); */
3222
3223 Polyhedron_Free(Pol), Pol = NULL;
3224 SMFree(&Sat);
3225 Matrix_Free(Ray), Ray = NULL;
3226 Matrix_Free(Mat), Mat = NULL;
3227
3228 } /* end of TRY */
3229
3231 return notempty;
3232} /* SimplifyConstraints */
3233
3234/*
3235 * Eliminate equations of Pol1 using equations of Pol2. Mark as needed,
3236 * equations of Pol1 that are not eliminated. Or info into Filter vector.
3237 */
3239 unsigned *Filter) {
3240
3241 int i, j;
3242 unsigned ix, bx, NbEqn, NbEqn1, NbEqn2, NbEle2, Dimension;
3243 Matrix *Mat;
3244
3245 NbEqn1 = Pol1->NbEq;
3246 NbEqn2 = Pol2->NbEq;
3247 NbEqn = NbEqn1 + NbEqn2;
3248 Dimension = Pol1->Dimension + 2; /* Homogeneous Dimension + Status */
3249 NbEle2 = NbEqn2 * Dimension;
3250
3251 Mat = Matrix_Alloc(NbEqn, Dimension);
3252 if (!Mat) {
3253 errormsg1("SimplifyEqualities", "outofmem", "out of memory space");
3254 Pol_status = 1;
3255 return;
3256 }
3257
3258 /* Set the equalities of Pol2 */
3259 Vector_Copy(Pol2->Constraint[0], Mat->p_Init, NbEle2);
3260
3261 /* Add the equalities of Pol1 */
3262 Vector_Copy(Pol1->Constraint[0], Mat->p_Init + NbEle2, NbEqn1 * Dimension);
3263
3264 Gauss(Mat, NbEqn2, Dimension - 1);
3265
3266 ix = 0;
3267 bx = MSB;
3268 for (i = NbEqn2; i < NbEqn; i++) {
3269 for (j = 1; j < Dimension; j++) {
3270 if (value_notzero_p(Mat->p[i][j])) {
3271 /* If any coefficient of the equation is non-zero */
3272 /* Set the filter bit for the equation */
3273
3274 Filter[ix] |= bx;
3275 break;
3276 }
3277 }
3278 NEXT(ix, bx);
3279 }
3280 Matrix_Free(Mat);
3281 return;
3282} /* SimplifyEqualities */
3283
3284/*
3285 * Given two polyhedral domains 'Pol1' and 'Pol2', find the largest domain
3286 * set (or the smallest list of non-redundant constraints), that when
3287 * intersected with polyhedral domain 'Pol2' equals (Pol1)intersect(Pol2).
3288 * The output is a polyhedral domain with the "redundant" constraints removed.
3289 * 'NbMaxRays' is the maximium allowed rays in the new polyhedra.
3290 */
3292 unsigned NbMaxRays) {
3293
3294 Polyhedron *p1, *p2, *p3, *d;
3295 unsigned k, jx, bx, nbentries, NbConstraints, Dimension, NbCon, empty;
3296 unsigned *Filter;
3297 Matrix *Constraints;
3298
3299 if (!Pol1 || !Pol2)
3300 return Pol1;
3301 if (Pol1->Dimension != Pol2->Dimension) {
3302 errormsg1("DomSimplify", "diffdim", "operation on different dimensions");
3303 Pol_status = 1;
3304 return 0;
3305 }
3306 POL_ENSURE_VERTICES(Pol1);
3307 POL_ENSURE_VERTICES(Pol2);
3308 if (emptyQ(Pol1) || emptyQ(Pol2))
3309 return Empty_Polyhedron(Pol1->Dimension);
3310
3311 /* Find the maximum number of constraints over all polyhedron in the */
3312 /* polyhedral domain 'Pol2' and store in 'NbCon'. */
3313 NbCon = 0;
3314 for (p2 = Pol2; p2; p2 = p2->next)
3315 if (p2->NbConstraints > NbCon)
3316 NbCon = p2->NbConstraints;
3317
3318 Dimension = Pol1->Dimension + 2; /* Homogenous Dimension + Status */
3319 d = (Polyhedron *)0;
3320 for (p1 = Pol1; p1; p1 = p1->next) {
3321
3323
3324 /* Filter is an array of integers, each bit in an element of Filter */
3325 /* array corresponds to a constraint. The bit is marked 1 if the */
3326 /* corresponding constraint is non-redundant and is 0 if it is */
3327 /* redundant. */
3328
3329 NbConstraints = p1->NbConstraints;
3330 nbentries = (NbConstraints + NbCon - 1) / (sizeof(int) * 8) + 1;
3331
3332 /* Allocate space for array 'Filter' */
3333 Filter = malloc(nbentries * sizeof(int));
3334 if (!Filter) {
3335 errormsg1("DomSimplify", "outofmem", "out of memory space\n");
3336 Pol_status = 1;
3337 return 0;
3338 }
3339
3340 /* Initialize 'Filter' with zeros */
3341 SMVector_Init(Filter, nbentries);
3342
3343 /* Filter the constraints of p1 in context of polyhedra p2(s) */
3344 empty = 1;
3345 for (p2 = Pol2; p2; p2 = p2->next) {
3346
3348
3349 /* Store the non-redundant constraints in array 'Filter'. With */
3350 /* successive loops, the array 'Filter' holds the union of all */
3351 /* non-redundant constraints. 'empty' is set to zero if the */
3352 /* intersection of two polyhedra is non-empty and Filter is !Null */
3353
3354 SimplifyEqualities(p1, p2, Filter);
3355 if (SimplifyConstraints(p1, p2, Filter, NbMaxRays))
3356 empty = 0;
3357
3358 /* takes the union of all non redundant constraints */
3359 }
3360
3361 if (!empty) {
3362
3363 /* Copy all non-redundant constraints to matrix 'Constraints' */
3364 Constraints = Matrix_Alloc(NbConstraints, Dimension);
3365 if (!Constraints) {
3366 errormsg1("DomSimplify", "outofmem", "out of memory space\n");
3367 Pol_status = 1;
3368 return 0;
3369 }
3370 Constraints->NbRows = 0;
3371 for (k = 0, jx = 0, bx = MSB; k < NbConstraints; k++) {
3372
3373 /* If a bit entry in Filter[jx] is marked 1, copy the correspond- */
3374 /* ing constraint in matrix 'Constraints'. */
3375 if (Filter[jx] & bx) {
3376 Vector_Copy(p1->Constraint[k], Constraints->p[Constraints->NbRows],
3377 Dimension);
3378 Constraints->NbRows++;
3379 }
3380 NEXT(jx, bx);
3381 }
3382
3383 /* Create the polyhedron 'p3' corresponding to the constraints in */
3384 /* matrix 'Constraints'. */
3385 p3 = Constraints2Polyhedron(Constraints, NbMaxRays);
3386 Matrix_Free(Constraints);
3387
3388 /* Add polyhedron 'p3' in the domain 'd'. */
3389 d = AddPolyToDomain(p3, d);
3390 p3 = NULL;
3391 }
3392 free(Filter);
3393 }
3394 if (!d)
3395 return Empty_Polyhedron(Pol1->Dimension);
3396 else
3397 return d;
3398
3399} /* DomainSimplify */
3400
3401/*
3402 * Domain Simplify as defined in Strasborg Polylib version.
3403 */
3405 unsigned NbMaxRays) {
3406
3407 Polyhedron *p1, *p2, *p3 = NULL, *d = NULL;
3408 unsigned k, jx, bx, nbentries, NbConstraints, Dimension, NbCon, empty;
3409 unsigned *Filter = NULL;
3410 Matrix *Constraints = NULL;
3411
3413 if (Constraints)
3414 Matrix_Free(Constraints);
3415 if (Filter)
3416 free(Filter);
3417 if (d)
3418 Polyhedron_Free(d);
3419 if (p2)
3420 Polyhedron_Free(p3);
3421 RETHROW();
3422 }
3423 TRY {
3424 if (!Pol1 || !Pol2) {
3426 return Pol1;
3427 }
3428 if (Pol1->Dimension != Pol2->Dimension) {
3429 errormsg1("DomainSimplify", "diffdim",
3430 "operation on different dimensions");
3432 return 0;
3433 }
3434 POL_ENSURE_VERTICES(Pol1);
3435 POL_ENSURE_VERTICES(Pol2);
3436 if (emptyQ(Pol1) || emptyQ(Pol2)) {
3438 return Empty_Polyhedron(Pol1->Dimension);
3439 }
3440
3441 /* Find the maximum number of constraints over all polyhedron in the */
3442 /* polyhedral domain 'Pol2' and store in 'NbCon'. */
3443 NbCon = 0;
3444 for (p2 = Pol2; p2; p2 = p2->next)
3445 if (p2->NbConstraints > NbCon)
3446 NbCon = p2->NbConstraints;
3447
3448 Dimension = Pol1->Dimension + 2; /* Homogenous Dimension + Status */
3449 d = (Polyhedron *)0;
3450 for (p1 = Pol1; p1; p1 = p1->next) {
3451
3452 /* Filter is an array of integers, each bit in an element of Filter */
3453 /* array corresponds to a constraint. The bit is marked 1 if the */
3454 /* corresponding constraint is non-redundant and is 0 if it is */
3455 /* redundant. */
3456
3457 NbConstraints = p1->NbConstraints;
3458 nbentries = (NbConstraints + NbCon - 1) / (sizeof(int) * 8) + 1;
3459
3460 /* Allocate space for array 'Filter' */
3461 Filter = malloc(nbentries * sizeof(int));
3462 if (!Filter) {
3463 errormsg1("DomainSimplify", "outofmem", "out of memory space");
3465 return 0;
3466 }
3467
3468 /* Initialize 'Filter' with zeros */
3469 SMVector_Init(Filter, nbentries);
3470
3471 /* Filter the constraints of p1 in context to the polyhedra p2(s) */
3472 empty = 1;
3473 for (p2 = Pol2; p2; p2 = p2->next) {
3474
3475 /* Store the non-redundant constraints in array 'Filter'. With */
3476 /* successive loops, the array 'Filter' holds the union of all */
3477 /* non-redundant constraints. 'empty' is set to zero if the */
3478 /* intersection of two polyhedra is non-empty and Filter is !Null */
3479
3480 if (SimplifyConstraints(p1, p2, Filter, NbMaxRays))
3481 empty = 0;
3482 }
3483
3484 if (!empty) {
3485
3486 /* Copy all non-redundant constraints to matrix 'Constraints' */
3487 Constraints = Matrix_Alloc(NbConstraints, Dimension);
3488 if (!Constraints) {
3489 errormsg1("DomainSimplify", "outofmem", "out of memory space");
3491 return 0;
3492 }
3493 Constraints->NbRows = 0;
3494 for (k = 0, jx = 0, bx = MSB; k < NbConstraints; k++) {
3495
3496 /* If a bit entry in Filter[jx] is marked 1, copy the correspond- */
3497 /* ing constraint in matrix 'Constraints'. */
3498 if (Filter[jx] & bx) {
3499 Vector_Copy(p1->Constraint[k], Constraints->p[Constraints->NbRows],
3500 Dimension);
3501 Constraints->NbRows++;
3502 }
3503 NEXT(jx, bx);
3504 }
3505
3506 /* Create the polyhedron 'p3' corresponding to the constraints in */
3507 /* matrix 'Constraints'. */
3508 p3 = Constraints2Polyhedron(Constraints, NbMaxRays);
3509 Matrix_Free(Constraints), Constraints = NULL;
3510
3511 /* Add polyhedron 'p3' in the domain 'd'. */
3512 d = AddPolyToDomain(p3, d);
3513 p3 = NULL;
3514 }
3515 free(Filter), Filter = NULL;
3516 }
3517 } /* end of TRY */
3518
3520 if (!d)
3521 return Empty_Polyhedron(Pol1->Dimension);
3522 else
3523 return d;
3524} /* DomainSimplify */
3525
3526/*
3527 * Return the union of two polyhedral domains 'Pol1' and Pol2'. The result is
3528 * a new polyhedral domain.
3529 */
3531 unsigned NbMaxRays) {
3532
3533 Polyhedron *PolA, *PolEndA, *PolB, *PolEndB, *p1, *p2;
3534 int Redundant;
3535
3536 if (!Pol1)
3537 return Domain_Copy(Pol2);
3538 if (!Pol2)
3539 return Domain_Copy(Pol1);
3540 if (Pol1->Dimension != Pol2->Dimension) {
3541 errormsg1("DomainUnion", "diffdim", "operation on different dimensions");
3542 return (Polyhedron *)0;
3543 }
3544
3545 /* Copy 'Pol1' to 'PolA' */
3546 PolA = PolEndA = (Polyhedron *)0;
3547 for (p1 = Pol1; p1; p1 = p1->next) {
3548
3549 /* Does any component of 'Pol2' cover 'p1' ? */
3550 Redundant = 0;
3551 for (p2 = Pol2; p2; p2 = p2->next) {
3552 if (PolyhedronIncludes(p2, p1)) { /* p2 covers p1 */
3553 Redundant = 1;
3554
3555 break;
3556 }
3557 }
3558 if (!Redundant) {
3559
3560 /* Add 'p1' to 'PolA' */
3561 if (!PolEndA)
3562 PolEndA = PolA = Polyhedron_Copy(p1);
3563 else {
3564 PolEndA->next = Polyhedron_Copy(p1);
3565 PolEndA = PolEndA->next;
3566 }
3567 }
3568 }
3569
3570 /* Copy 'Pol2' to PolB */
3571 PolB = PolEndB = (Polyhedron *)0;
3572 for (p2 = Pol2; p2; p2 = p2->next) {
3573
3574 /* Does any component of PolA cover 'p2' ? */
3575 Redundant = 0;
3576 for (p1 = PolA; p1; p1 = p1->next) {
3577 if (PolyhedronIncludes(p1, p2)) { /* p1 covers p2 */
3578 Redundant = 1;
3579 break;
3580 }
3581 }
3582 if (!Redundant) {
3583
3584 /* Add 'p2' to 'PolB' */
3585 if (!PolEndB)
3586 PolEndB = PolB = Polyhedron_Copy(p2);
3587 else {
3588 PolEndB->next = Polyhedron_Copy(p2);
3589 PolEndB = PolEndB->next;
3590 }
3591 }
3592 }
3593
3594 if (!PolA)
3595 return PolB;
3596 PolEndA->next = PolB;
3597 return PolA;
3598} /* DomainUnion */
3599
3600/*
3601 * Given a polyhedral domain 'Pol', concatenate the lists of rays and lines
3602 * of the two (or more) polyhedra in the domain into one combined list, and
3603 * find the set of constraints which tightly bound all of those objects.
3604 * 'NbMaxConstrs' is the maximum allowed constraints in the new polyhedron.
3605 */
3606Polyhedron *DomainConvex(Polyhedron *Pol, unsigned NbMaxConstrs) {
3607
3608 Polyhedron *p, *q, *NewPol = NULL;
3609
3611 if (NewPol)
3612 Polyhedron_Free(NewPol);
3613 RETHROW();
3614 }
3615 TRY {
3616
3617 if (!Pol) {
3619 return (Polyhedron *)0;
3620 }
3621
3623 NewPol = Polyhedron_Copy(Pol);
3624 for (p = Pol->next; p; p = p->next) {
3626 q = AddRays(p->Ray[0], p->NbRays, NewPol, NbMaxConstrs);
3627 Polyhedron_Free(NewPol);
3628 NewPol = q;
3629 }
3630 } /* end of TRY */
3631
3633
3634 return NewPol;
3635} /* DomainConvex */
3636
3637/*
3638 * Given polyhedral domains 'Pol1' and 'Pol2', create a new polyhedral
3639 * domain which is mathematically the difference Pol1 - Pol2
3640 */
3642 unsigned NbMaxRays) {
3643
3644 Polyhedron *p1, *p2, *p3, *d;
3645 int i;
3646
3647 if (!Pol1)
3648 return(NULL);
3649 if (!Pol2)
3650 return(Polyhedron_Copy(Pol1));
3651 if (Pol1->Dimension != Pol2->Dimension) {
3652 errormsg1("DomainDifference", "diffdim",
3653 "operation on different dimensions");
3654 return (Polyhedron *)0;
3655 }
3656 POL_ENSURE_FACETS(Pol1);
3657 POL_ENSURE_VERTICES(Pol1);
3658 POL_ENSURE_FACETS(Pol2);
3659 POL_ENSURE_VERTICES(Pol2);
3660 if (emptyQ(Pol1) || emptyQ(Pol2))
3661 return (Domain_Copy(Pol1));
3662 d = (Polyhedron *)0;
3663 for (p2 = Pol2; p2; p2 = p2->next) {
3664 for (p1 = Pol1; p1; p1 = p1->next) {
3665 for (i = 0; i < p2->NbConstraints; i++) {
3666
3667 /* Add the constraint ( -p2->constraint[i] -1) >= 0 in 'p1' */
3668 /* and create the new polyhedron 'p3'. */
3669 p3 = SubConstraint(p2->Constraint[i], p1, NbMaxRays, 0);
3670
3671 /* Add 'p3' in the new domain 'd' */
3672 d = AddPolyToDomain(p3, d);
3673
3674 /* If the constraint p2->constraint[i][0] is an equality, then */
3675 /* add the constraint ( +p2->constraint[i] -1) >= 0 in 'p1' and*/
3676 /* create the new polyhedron 'p3'. */
3677
3678 if (value_notzero_p(p2->Constraint[i][0])) /* Inequality */
3679 continue;
3680 p3 = SubConstraint(p2->Constraint[i], p1, NbMaxRays, 1);
3681
3682 /* Add 'p3' in the new domain 'd' */
3683 d = AddPolyToDomain(p3, d);
3684 }
3685 }
3686 if (p2 != Pol2)
3687 Domain_Free(Pol1);
3688 Pol1 = d;
3689 d = (Polyhedron *)0;
3690 }
3691 if (!Pol1)
3692 return Empty_Polyhedron(Pol2->Dimension);
3693 else
3694 return Pol1;
3695} /* DomainDifference */
3696
3697/*
3698 * Given a polyhedral domain 'Pol', convert it to a new polyhedral domain
3699 * with dimension expanded to 'align_dimension'. The first dimensions are
3700 * free variables.
3701 *
3702 * 'NbMaxRays' is the maximum allowed rays in the new polyhedra.
3703 */
3704Polyhedron *align_context(Polyhedron *Pol, int align_dimension, int NbMaxRays) {
3705
3706 int i, k;
3707 Polyhedron *p = NULL, **next, *result = NULL;
3708 unsigned dim;
3709
3711 if (result)
3712 Polyhedron_Free(result);
3713 RETHROW();
3714 }
3715 TRY {
3716
3717 if (!Pol)
3718 return Pol;
3719 dim = Pol->Dimension;
3720 if (align_dimension < Pol->Dimension) {
3721 errormsg1("align_context", "diffdim", "context dimension exceeds data");
3723 return NULL;
3724 }
3725 if (align_dimension == Pol->Dimension) {
3727 return Domain_Copy(Pol);
3728 }
3729
3730 /* 'k' is the dimension increment */
3731 k = align_dimension - Pol->Dimension;
3732 next = &result;
3733
3734 /* Expand the dimension of all polyhedra in the polyhedral domain 'Pol' */
3735 for (; Pol; Pol = Pol->next) {
3736 int have_cons =
3737 !F_ISSET(Pol, POL_VALID) || F_ISSET(Pol, POL_INEQUALITIES);
3738 int have_rays = !F_ISSET(Pol, POL_VALID) || F_ISSET(Pol, POL_POINTS);
3739 unsigned NbCons = have_cons ? Pol->NbConstraints : 0;
3740 unsigned NbRays = have_rays ? Pol->NbRays + k : 0;
3741
3742 if (Pol->Dimension != dim) {
3743 Domain_Free(result);
3744 errormsg1("align_context", "diffdim",
3745 "context not of uniform dimension");
3747 return NULL;
3748 }
3749
3750 p = Polyhedron_Alloc(align_dimension, NbCons, NbRays);
3751 if (have_cons) {
3752 for (i = 0; i < NbCons; ++i) {
3753 value_assign(p->Constraint[i][0],
3754 Pol->Constraint[i][0]); /* Status bit */
3755 Vector_Copy(Pol->Constraint[i] + 1, p->Constraint[i] + k + 1,
3756 Pol->Dimension + 1);
3757 }
3758 p->NbEq = Pol->NbEq;
3759 }
3760
3761 if (have_rays) {
3762 for (i = 0; i < k; ++i)
3763 value_set_si(p->Ray[i][1 + i], 1); /* A line */
3764 for (i = 0; i < Pol->NbRays; ++i) {
3765 value_assign(p->Ray[k + i][0], Pol->Ray[i][0]); /* Status bit */
3766 Vector_Copy(Pol->Ray[i] + 1, p->Ray[i + k] + k + 1,
3767 Pol->Dimension + 1);
3768 }
3769 p->NbBid = Pol->NbBid + k;
3770 }
3771 p->flags = Pol->flags;
3772
3773 *next = p;
3774 next = &p->next;
3775 }
3776 } /* end of TRY */
3777
3779 return result;
3780} /* align_context */
3781
3782/*
3783 * Polyhedron *Polyhedron_Scan(D, C, NbMaxRays)
3784 * D : Domain to be scanned (need to be a single polyhedron only)
3785 * C : Context domain
3786 * NbMaxRays : Workspace size
3787 * The context corresponds to the last dimensions of D.
3788 *
3789 * Returns a linked list of scan domains, outer loop first
3790 */
3791Polyhedron *Polyhedron_Scan(Polyhedron *D, Polyhedron *C, unsigned NbMaxRays) {
3792
3793 int i, j, dim;
3794 Matrix *Mat;
3795 Polyhedron *C1, *C2, *D1, *D2;
3796 Polyhedron *res, *last, *tmp;
3797
3798 dim = D->Dimension - C->Dimension;
3799 res = last = (Polyhedron *)0;
3800 if (dim == 0)
3801 return (Polyhedron *)0;
3802
3803 assert(!D->next);
3804
3809
3810 /* Allocate space for constraint matrix. */
3811 Mat = Matrix_Alloc(D->Dimension, D->Dimension + 2);
3812 if (!Mat) {
3813 errormsg1("Polyhedron_Scan", "outofmem", "out of memory space");
3814 return 0;
3815 }
3816 C1 = align_context(C, D->Dimension, NbMaxRays);
3817 if (!C1) {
3818 return 0;
3819 }
3820 /* Vin100, aug 16, 2001: The context is intersected with D */
3821 D2 = DomainIntersection(C1, D, NbMaxRays);
3822
3823 for (i = 0; i < dim; i++) {
3824 Vector_Set(Mat->p_Init, 0, D2->Dimension * (D2->Dimension + 2));
3825 for (j = i + 1; j < dim; j++) {
3826 value_set_si(Mat->p[j - i - 1][j + 1], 1);
3827 }
3828 Mat->NbRows = dim - i - 1;
3829 D1 = Mat->NbRows ? DomainAddRays(D2, Mat, NbMaxRays) : D2;
3830 tmp = DomainSimplify(D1, C1, NbMaxRays);
3831 if (!last)
3832 res = last = tmp;
3833 else {
3834 last->next = tmp;
3835 last = tmp;
3836 }
3837 C2 = DomainIntersection(C1, D1, NbMaxRays);
3838 Domain_Free(C1);
3839 C1 = C2;
3840 if (Mat->NbRows)
3841 Domain_Free(D1);
3842 }
3843 Domain_Free(D2);
3844 Domain_Free(C1);
3845 Matrix_Free(Mat);
3846 return res;
3847} /* Polyhedron_Scan */
3848
3849/*
3850 * int lower_upper_bounds(pos, P, context, LBp, UBp)
3851 * pos : index position of current loop index (1..hdim-1)
3852 * P: loop domain
3853 * context : context values for fixed dimensions
3854 * context[pos] is set to 0
3855 * LBp, UBp : pointers to resulting bounds
3856 * returns the flag = (UB_INFINITY, LB_INFINITY)
3857 *
3858 */
3859int lower_upper_bounds(int pos, Polyhedron *P, Value *context, Value *LBp,
3860 Value *UBp) {
3861
3862 Value LB, UB;
3863 int flag, i;
3864 Value n, n1, d, tmp;
3865
3868
3869 /* Initialize all the 'Value' variables */
3870 value_init(LB);
3871 value_init(UB);
3872 value_init(tmp);
3873 value_init(n);
3874 value_init(n1);
3875 value_init(d);
3876
3877 value_set_si(LB, 0);
3878 value_set_si(UB, 0);
3879
3880 // 0 1 .. pos pos+1..hdim hdim+1
3881 // context : 0 * * 0 0...0 1
3882 // notice that, in PolyhedronEnumerate() (ehrhart.c), the context between
3883 // pos+1 and hdim can be != 0.
3884
3885 // ensure that context[pos] = 0
3886 value_set_si(context[pos], 0);
3887
3888 /* Compute Upper Bound and Lower Bound for current loop */
3889 flag = LB_INFINITY | UB_INFINITY;
3890 for (i = 0; i < P->NbConstraints; i++) {
3891 value_assign(d, P->Constraint[i][pos]);
3892 Inner_Product(&context[1], &(P->Constraint[i][1]), P->Dimension, &n);
3893 value_addto(n, n, P->Constraint[i][P->Dimension + 1]);
3894 if (value_zero_p(d)) {
3895 /* If context doesn't satisfy constraints, return empty loop. */
3896 if (value_neg_p(n) ||
3897 (value_zero_p(P->Constraint[i][0]) && value_notzero_p(n)))
3898 goto empty_loop;
3899 continue;
3900 }
3901 value_oppose(n, n);
3902
3903 /*---------------------------------------------------*/
3904 /* Compute n/d n/d<0 n/d>0 */
3905 /*---------------------------------------------------*/
3906 /* n%d == 0 floor = n/d floor = n/d */
3907 /* ceiling = n/d ceiling = n/d */
3908 /*---------------------------------------------------*/
3909 /* n%d != 0 floor = n/d - 1 floor = n/d */
3910 /* ceiling = n/d ceiling = n/d + 1 */
3911 /*---------------------------------------------------*/
3912
3913 /* Check to see if constraint is inequality */
3914 /* if constraint is equality, both upper and lower bounds are fixed */
3915 if (value_zero_p(P->Constraint[i][0])) { /* Equality */
3916 value_modulus(tmp, n, d);
3917
3918 /* if not integer, return 0; */
3919 if (value_notzero_p(tmp))
3920 goto empty_loop;
3921
3922 value_division(n1, n, d);
3923
3924 /* Upper and Lower bounds found */
3925 if ((flag & LB_INFINITY) || value_gt(n1, LB))
3926 value_assign(LB, n1);
3927 if ((flag & UB_INFINITY) || value_lt(n1, UB))
3928 value_assign(UB, n1);
3929 flag = 0;
3930 }
3931
3932 if (value_pos_p(d)) { /* Lower Bound */
3933 value_modulus(tmp, n, d); // tmp = n % d
3934
3935 /* n1 = ceiling(n/d) */
3936 if (value_pos_p(n) && value_notzero_p(tmp)) { // n>0 && tmp!=0
3937 value_division(n1, n, d);
3938 value_add_int(n1, n1, 1); // n1 = n/d+1
3939 } else
3940 value_division(n1, n, d); // n1 = n/d
3941 if (flag & LB_INFINITY) {
3942 value_assign(LB, n1);
3943 flag ^= LB_INFINITY;
3944 } else if (value_gt(n1, LB))
3945 value_assign(LB, n1);
3946 }
3947
3948 if (value_neg_p(d)) { /* Upper Bound */
3949 value_modulus(tmp, n, d);
3950
3951 /* n1 = floor(n/d) */
3952 if (value_pos_p(n) && value_notzero_p(tmp)) {
3953 value_division(n1, n, d);
3954 value_sub_int(n1, n1, 1);
3955 } else
3956 value_division(n1, n, d);
3957
3958 if (flag & UB_INFINITY) {
3959 value_assign(UB, n1);
3960 flag ^= UB_INFINITY;
3961 } else if (value_lt(n1, UB))
3962 value_assign(UB, n1);
3963 }
3964 }
3965 if ((flag & LB_INFINITY) == 0)
3966 value_assign(*LBp, LB);
3967 if ((flag & UB_INFINITY) == 0)
3968 value_assign(*UBp, UB);
3969
3970 if (0) {
3971 empty_loop:
3972 flag = 0;
3973 value_set_si(*LBp, 1);
3974 value_set_si(*UBp, 0); /* empty loop */
3975 }
3976
3977 /* Clear all the 'Value' variables */
3978 value_clear(LB);
3979 value_clear(UB);
3980 value_clear(tmp);
3981 value_clear(n);
3982 value_clear(n1);
3983 value_clear(d);
3984 return flag;
3985} /* lower_upper_bounds */
3986
3987/*
3988 * C = A x B
3989 */
3990static void Rays_Mult(Value **A, Matrix *B, Value **C, unsigned NbRays) {
3991 int i, j, k;
3992 unsigned Dimension1, Dimension2;
3993 Value Sum, tmp;
3994
3995 value_init(Sum);
3996 value_init(tmp);
3997
3999 value_clear(Sum);
4000 value_clear(tmp);
4001 RETHROW();
4002 }
4003 TRY {
4004 Dimension1 = B->NbRows;
4005 Dimension2 = B->NbColumns;
4006
4007 for (i = 0; i < NbRays; i++) {
4008 value_assign(C[i][0], A[i][0]);
4009 for (j = 0; j < Dimension2; j++) {
4010 value_set_si(Sum, 0);
4011 for (k = 0; k < Dimension1; k++) {
4012
4013 /* Sum+=A[i][k+1] * B->p[k][j]; */
4014 value_addmul(Sum, A[i][k + 1], B->p[k][j]);
4015 }
4016 value_assign(C[i][j + 1], Sum);
4017 }
4018 Vector_Gcd(C[i] + 1, Dimension2, &tmp);
4019 if (value_notone_p(tmp))
4020 Vector_AntiScale(C[i] + 1, C[i] + 1, tmp, Dimension2);
4021 }
4022 }
4024 value_clear(Sum);
4025 value_clear(tmp);
4026}
4027
4028/*
4029 * C = A x B^T
4030 */
4031static void Rays_Mult_Transpose(Value **A, Matrix *B, Value **C,
4032 unsigned NbRays) {
4033 int i, j, k;
4034 unsigned Dimension1, Dimension2;
4035 Value Sum, tmp;
4036
4037 value_init(Sum);
4038 value_init(tmp);
4039
4041 value_clear(Sum);
4042 value_clear(tmp);
4043 RETHROW();
4044 }
4045 TRY {
4046 Dimension1 = B->NbColumns;
4047 Dimension2 = B->NbRows;
4048
4049 for (i = 0; i < NbRays; i++) {
4050 value_assign(C[i][0], A[i][0]);
4051 for (j = 0; j < Dimension2; j++) {
4052 value_set_si(Sum, 0);
4053 for (k = 0; k < Dimension1; k++) {
4054
4055 /* Sum+=A[i][k+1] * B->p[j][k]; */
4056 value_addmul(Sum, A[i][k + 1], B->p[j][k]);
4057 }
4058 value_assign(C[i][j + 1], Sum);
4059 }
4060 Vector_Gcd(C[i] + 1, Dimension2, &tmp);
4061 if (value_notone_p(tmp))
4062 Vector_AntiScale(C[i] + 1, C[i] + 1, tmp, Dimension2);
4063 }
4064 }
4066 value_clear(Sum);
4067 value_clear(tmp);
4068}
4069
4070/*
4071 * Given a polyhedron 'Pol' and a transformation matrix 'Func', return the
4072 * polyhedron which when transformed by mapping function 'Func' gives 'Pol'.
4073 * 'NbMaxRays' is the maximum number of rays that can be in the ray matrix
4074 * of the resulting polyhedron.
4075 */
4077 unsigned NbMaxRays) {
4078
4079 Matrix *Constraints = NULL;
4080 Polyhedron *NewPol = NULL;
4081 unsigned NbConstraints, Dimension1, Dimension2;
4082
4084
4086 if (Constraints)
4087 Matrix_Free(Constraints);
4088 if (NewPol)
4089 Polyhedron_Free(NewPol);
4090 RETHROW();
4091 }
4092 TRY {
4093
4094 NbConstraints = Pol->NbConstraints;
4095 Dimension1 = Pol->Dimension + 1; /* Homogeneous Dimension */
4096 Dimension2 = Func->NbColumns; /* Homogeneous Dimension */
4097 if (Dimension1 != (Func->NbRows)) {
4098 errormsg1("Polyhedron_Preimage", "dimincomp", "incompatible dimensions");
4100 return Empty_Polyhedron(Dimension2 - 1);
4101 }
4102
4103 /* Dim1 Dim2 Dim2
4104 __k__ __j__ __j__
4105 NbCon | | X Dim1| | = NbCon | |
4106 i |___| k |___| i |___|
4107 Pol->Constraints Function Constraints
4108 */
4109
4110 /* Allocate space for the resulting constraint matrix */
4111 Constraints = Matrix_Alloc(NbConstraints, Dimension2 + 1);
4112 if (!Constraints) {
4113 errormsg1("Polyhedron_Preimage", "outofmem", "out of memory space\n");
4114 Pol_status = 1;
4116 return 0;
4117 }
4118
4119 /* The new constraint matrix is the product of constraint matrix of the */
4120 /* polyhedron and the function matrix. */
4121 Rays_Mult(Pol->Constraint, Func, Constraints->p, NbConstraints);
4122 NewPol = Constraints2Polyhedron(Constraints, NbMaxRays);
4123 Matrix_Free(Constraints), Constraints = NULL;
4124
4125 } /* end of TRY */
4126
4128
4129 return NewPol;
4130} /* Polyhedron_Preimage */
4131
4132/*
4133 * Given a polyhedral domain 'Pol' and a transformation matrix 'Func', return
4134 * the polyhedral domain which when transformed by mapping function 'Func'
4135 * gives 'Pol'. 'NbMaxRays' is the maximum number of rays that can be in the
4136 * ray matrix of the resulting domain.
4137 */
4138Polyhedron *DomainPreimage(Polyhedron *Pol, Matrix *Func, unsigned NbMaxRays) {
4139
4140 Polyhedron *p, *q, *d = NULL;
4141
4143 if (d)
4144 Polyhedron_Free(d);
4145 RETHROW();
4146 }
4147 TRY {
4148 if (!Pol || !Func) {
4150 return (Polyhedron *)0;
4151 }
4152 d = (Polyhedron *)0;
4153 for (p = Pol; p; p = p->next) {
4154 q = Polyhedron_Preimage(p, Func, NbMaxRays);
4155 d = AddPolyToDomain(q, d);
4156 }
4157 } /* end of TRY */
4159 return d;
4160} /* DomainPreimage */
4161
4162/*
4163 * Transform a polyhedron 'Pol' into another polyhedron according to a given
4164 * affine mapping function 'Func'. 'NbMaxConstrs' is the maximum number of
4165 * constraints that can be in the constraint matrix of the new polyhedron.
4166 */
4168 unsigned NbMaxConstrs) {
4169
4170 Matrix *Rays = NULL;
4171 Polyhedron *NewPol = NULL;
4172 unsigned NbRays, Dimension1, Dimension2;
4173
4174 POL_ENSURE_FACETS(Pol);
4176
4178 if (Rays)
4179 Matrix_Free(Rays);
4180 if (NewPol)
4181 Polyhedron_Free(NewPol);
4182 RETHROW();
4183 }
4184 TRY {
4185
4186 NbRays = Pol->NbRays;
4187 Dimension1 = Pol->Dimension + 1; /* Homogeneous Dimension */
4188 Dimension2 = Func->NbRows; /* Homogeneous Dimension */
4189 if (Dimension1 != Func->NbColumns) {
4190 errormsg1("Polyhedron_Image", "dimincomp", "incompatible dimensions");
4192 return Empty_Polyhedron(Dimension2 - 1);
4193 }
4194
4195 /*
4196 Dim1 / Dim1 \Transpose Dim2
4197 __k__ | __k__ | __j__
4198 NbRays| | X | Dim2 | | | = NbRays| |
4199 i |___| | j |___| | i |___|
4200 Pol->Rays \ Func / Rays
4201
4202 */
4203
4204 if (Dimension1 == Dimension2) {
4205 Matrix *M, *M2;
4206 int ok;
4207 M = Matrix_Copy(Func);
4208 M2 = Matrix_Alloc(Dimension2, Dimension1);
4209 if (!M2) {
4210 errormsg1("Polyhedron_Image", "outofmem", "out of memory space\n");
4212 return 0;
4213 }
4214
4215 ok = Matrix_Inverse(M, M2);
4216 Matrix_Free(M);
4217 if (ok) {
4218 NewPol =
4220 if (!NewPol) {
4221 errormsg1("Polyhedron_Image", "outofmem", "out of memory space\n");
4223 return 0;
4224 }
4225 Rays_Mult_Transpose(Pol->Ray, Func, NewPol->Ray, NbRays);
4226 Rays_Mult(Pol->Constraint, M2, NewPol->Constraint, Pol->NbConstraints);
4227 NewPol->NbEq = Pol->NbEq;
4228 NewPol->NbBid = Pol->NbBid;
4229 if (NewPol->NbEq)
4230 Gauss4(NewPol->Constraint, NewPol->NbEq, NewPol->NbConstraints,
4231 NewPol->Dimension + 1);
4232 if (NewPol->NbBid)
4233 Gauss4(NewPol->Ray, NewPol->NbBid, NewPol->NbRays,
4234 NewPol->Dimension + 1);
4235 }
4236 Matrix_Free(M2);
4237 }
4238
4239 if (!NewPol) {
4240 /* Allocate space for the resulting ray matrix */
4241 Rays = Matrix_Alloc(NbRays, Dimension2 + 1);
4242 if (!Rays) {
4243 errormsg1("Polyhedron_Image", "outofmem", "out of memory space\n");
4245 return 0;
4246 }
4247
4248 /* The new ray space is the product of ray matrix of the polyhedron and */
4249 /* the transpose matrix of the mapping function. */
4250 Rays_Mult_Transpose(Pol->Ray, Func, Rays->p, NbRays);
4251 NewPol = Rays2Polyhedron(Rays, NbMaxConstrs);
4252 Matrix_Free(Rays), Rays = NULL;
4253 }
4254
4255 } /* end of TRY */
4256
4258 return NewPol;
4259} /* Polyhedron_Image */
4260
4261/*
4262 *Transform a polyhedral domain 'Pol' into another domain according to a given
4263 * affine mapping function 'Func'. 'NbMaxConstrs' is the maximum number of
4264 * constraints that can be in the constraint matrix of the resulting domain.
4265 */
4266Polyhedron *DomainImage(Polyhedron *Pol, Matrix *Func, unsigned NbMaxConstrs) {
4267
4268 Polyhedron *p, *q, *d = NULL;
4269
4271 if (d)
4272 Polyhedron_Free(d);
4273 RETHROW();
4274 }
4275 TRY {
4276
4277 if (!Pol || !Func) {
4279 return (Polyhedron *)0;
4280 }
4281 d = (Polyhedron *)0;
4282 for (p = Pol; p; p = p->next) {
4283 q = Polyhedron_Image(p, Func, NbMaxConstrs);
4284 d = AddPolyToDomain(q, d);
4285 }
4286 } /* end of TRY */
4287
4289
4290 return d;
4291} /* DomainImage */
4292
4293/*
4294 * Given a polyhedron 'Pol' and an affine cost function 'Cost', compute the
4295 * maximum and minimum value of the function over set of points representing
4296 * polyhedron.
4297 * Note: If Polyhedron 'Pol' is empty, then there is no feasible solution.
4298 * Otherwise, if there is a bidirectional ray with Sum[cost(i)*ray(i)] != 0 or
4299 * a unidirectional ray with Sum[cost(i)*ray(i)] >0, then the maximum is un-
4300 * bounded else the finite optimal solution occurs at one of the vertices of
4301 * the polyhderon.
4302 */
4304
4305 int i, j, NbRay, Dim;
4306 Value *p1, *p2, p3, d, status;
4307 Value tmp1, tmp2, tmp3;
4308 Value **Ray;
4309 Interval *I = NULL;
4310
4311 value_init(p3);
4312 value_init(d);
4313 value_init(status);
4314 value_init(tmp1);
4315 value_init(tmp2);
4316 value_init(tmp3);
4317
4318 POL_ENSURE_FACETS(Pol);
4320
4322 if (I)
4323 free(I);
4324 RETHROW();
4325 value_clear(p3);
4326 value_clear(d);
4327 value_clear(status);
4328 value_clear(tmp1);
4329 value_clear(tmp2);
4330 value_clear(tmp3);
4331 }
4332 TRY {
4333
4334 Ray = Pol->Ray;
4335 NbRay = Pol->NbRays;
4336 Dim = Pol->Dimension + 1; /* Homogenous Dimension */
4337 I = malloc(sizeof(Interval));
4338 if (!I) {
4339 errormsg1("DomainCost", "outofmem", "out of memory space\n");
4341 value_clear(p3);
4342 value_clear(d);
4343 value_clear(status);
4344 value_clear(tmp1);
4345 value_clear(tmp2);
4346 value_clear(tmp3);
4347 return 0;
4348 }
4349
4350 /* The maximum and minimum values of the cost function over polyhedral */
4351 /* domain is stored in 'I'. I->MaxN and I->MaxD store the numerator and */
4352 /* denominator of the maximum value. Likewise,I->MinN and I->MinD store */
4353 /* the numerator and denominator of the minimum value. I->MaxI and */
4354 /* I->MinI store the ray indices corresponding to the max and min values*/
4355 /* of the function. */
4356
4357 value_set_si(I->MaxN, -1);
4358 value_set_si(I->MaxD, 0); /* Actual cost is MaxN/MaxD */
4359 I->MaxI = -1;
4360 value_set_si(I->MinN, 1);
4361 value_set_si(I->MinD, 0);
4362 I->MinI = -1;
4363
4364 /* Compute the cost of each ray[i] */
4365 for (i = 0; i < NbRay; i++) {
4366 p1 = Ray[i];
4367 value_assign(status, *p1);
4368 p1++;
4369 p2 = Cost;
4370
4371 /* p3 = *p1++ * *p2++; */
4372 value_multiply(p3, *p1, *p2);
4373 p1++;
4374 p2++;
4375 for (j = 1; j < Dim; j++) {
4376 value_multiply(tmp1, *p1, *p2);
4377
4378 /* p3 += *p1++ * *p2++; */
4379 value_addto(p3, p3, tmp1);
4380 p1++;
4381 p2++;
4382 }
4383
4384 /* d = *--p1; */
4385 p1--;
4386 value_assign(d, *p1); /* d == 0 for lines and ray, non-zero for vertex */
4387 value_multiply(tmp1, p3, I->MaxD);
4388 value_multiply(tmp2, I->MaxN, d);
4389 value_set_si(tmp3, 1);
4390
4391 /* Compare p3/d with MaxN/MaxD to assign new maximum cost value */
4392 if (I->MaxI == -1 || value_gt(tmp1, tmp2) ||
4393 (value_eq(tmp1, tmp2) && value_eq(d, tmp3) &&
4394 value_ne(I->MaxD, tmp3))) {
4395 value_assign(I->MaxN, p3);
4396 value_assign(I->MaxD, d);
4397 I->MaxI = i;
4398 }
4399 value_multiply(tmp1, p3, I->MinD);
4400 value_multiply(tmp2, I->MinN, d);
4401 value_set_si(tmp3, 1);
4402
4403 /* Compare p3/d with MinN/MinD to assign new minimum cost value */
4404 if (I->MinI == -1 || value_lt(tmp1, tmp2) ||
4405 (value_eq(tmp1, tmp2) && value_eq(d, tmp3) &&
4406 value_ne(I->MinD, tmp3))) {
4407 value_assign(I->MinN, p3);
4408 value_assign(I->MinD, d);
4409 I->MinI = i;
4410 }
4411 value_multiply(tmp1, p3, I->MaxD);
4412 value_set_si(tmp2, 0);
4413
4414 /* If there is a line, assign max to +infinity and min to -infinity */
4415 if (value_zero_p(status)) { /* line , d is 0 */
4416 if (value_lt(tmp1, tmp2)) {
4417 value_oppose(I->MaxN, p3);
4418 value_set_si(I->MaxD, 0);
4419 I->MaxI = i;
4420 }
4421 value_multiply(tmp1, p3, I->MinD);
4422 value_set_si(tmp2, 0);
4423
4424 if (value_gt(tmp1, tmp2)) {
4425 value_oppose(I->MinN, p3);
4426 value_set_si(I->MinD, 0);
4427 I->MinI = i;
4428 }
4429 }
4430 }
4431 } /* end of TRY */
4432
4434 value_clear(p3);
4435 value_clear(d);
4436 value_clear(status);
4437 value_clear(tmp1);
4438 value_clear(tmp2);
4439 value_clear(tmp3);
4440 return I;
4441} /* DomainCost */
4442
4443/*
4444 * Add constraints pointed by 'Mat' to each and every polyhedron in the
4445 * polyhedral domain 'Pol'. 'NbMaxRays' is maximum allowed rays in the ray
4446 * matrix of a polyhedron.
4447 */
4449 unsigned NbMaxRays) {
4450
4451 Polyhedron *PolA, *PolEndA, *p1, *p2, *p3;
4452 int Redundant;
4453
4454 if (!Pol)
4455 return (Polyhedron *)0;
4456 if (!Mat)
4457 return Pol;
4458 if (Pol->Dimension != Mat->NbColumns - 2) {
4459 errormsg1("DomainAddConstraints", "diffdim",
4460 "operation on different dimensions");
4461 return (Polyhedron *)0;
4462 }
4463
4464 /* Copy 'Pol' to 'PolA' */
4465 PolA = PolEndA = (Polyhedron *)0;
4466 for (p1 = Pol; p1; p1 = p1->next) {
4467 p3 = AddConstraints(Mat->p_Init, Mat->NbRows, p1, NbMaxRays);
4468
4469 /* Does any component of 'PolA' cover 'p3' */
4470 Redundant = 0;
4471 for (p2 = PolA; p2; p2 = p2->next) {
4472 if (PolyhedronIncludes(p2, p3)) { /* 'p2' covers 'p3' */
4473 Redundant = 1;
4474 break;
4475 }
4476 }
4477
4478 /* If the new polyhedron 'p3' is not redundant, add it to the domain */
4479 if (Redundant)
4480 Polyhedron_Free(p3);
4481 else {
4482 if (!PolEndA)
4483 PolEndA = PolA = p3;
4484 else {
4485 PolEndA->next = p3;
4486 PolEndA = PolEndA->next;
4487 }
4488 }
4489 }
4490 return PolA;
4491} /* DomainAddConstraints */
4492
4493/*
4494 * Computes the disjoint union of a union of polyhedra.
4495 * If flag = 0 the result is such that there are no intersections
4496 * between the resulting polyhedra,
4497 * if flag = 1 it computes a joint union, the resulting polyhedra are
4498 * adjacent (they have their facets in common).
4499 *
4500 * WARNING: if all polyhedra are not of same geometrical dimension
4501 * duplicates may appear.
4502 */
4503Polyhedron *Disjoint_Domain(Polyhedron *P, int flag, unsigned NbMaxRays) {
4504 Polyhedron *lP, *tmp, *Result, *lR, *prec, *reste;
4505 Polyhedron *p1, *p2, *p3, *Pol1, *dx, *d1, *d2, *pi, *newpi;
4506 int i;
4507
4508 if (flag != 0 && flag != 1) {
4509 errormsg1("Disjoint_Domain", "invalidarg",
4510 "flag should be equal to 0 or 1");
4511 return (Polyhedron *)0;
4512 }
4513 if (!P)
4514 return (Polyhedron *)0;
4515 if (!P->next)
4516 return Polyhedron_Copy(P);
4517
4518 Result = (Polyhedron *)0;
4519
4520 for (lP = P; lP; lP = lP->next) {
4521 reste = Polyhedron_Copy(lP);
4522 prec = (Polyhedron *)0; /* preceeding lR */
4523 /* Intersection with each polyhedron of the current Result */
4524 lR = Result;
4525 while (lR && reste) {
4526 /* dx = DomainIntersection(reste,lR->P,WS); */
4527 dx = (Polyhedron *)0;
4528 for (p1 = reste; p1; p1 = p1->next) {
4529 p3 = AddConstraints(lR->Constraint[0], lR->NbConstraints, p1,
4530 NbMaxRays);
4531 dx = AddPolyToDomain(p3, dx);
4532 }
4533
4534 /* if empty intersection, continue */
4535 if (!dx) {
4536 prec = lR;
4537 lR = lR->next;
4538 continue;
4539 }
4540 if (emptyQ(dx)) {
4541 Domain_Free(dx);
4542 prec = lR;
4543 lR = lR->next;
4544 continue;
4545 }
4546
4547 /* intersection is not empty, we need to compute the differences */
4548 /* between the intersection and the two polyhedra, such that the */
4549 /* results are disjoint unions (according to flag) */
4550 /* d1 = reste \ P = DomainDifference(reste,lR->P,WS); */
4551 /* d2 = P \ reste = DomainDifference(lR->P,reste,WS); */
4552
4553 /* compute d1 */
4554 d1 = (Polyhedron *)0;
4555 for (p1 = reste; p1; p1 = p1->next) {
4556 pi = p1;
4557 for (i = 0; i < P->NbConstraints && pi; i++) {
4558 /* Add the constraint ( -P->constraint[i] [-1 if flag=0]) >= 0 in 'p1'
4559 */
4560 /* and create the new polyhedron 'p3'. */
4561 p3 = SubConstraint(P->Constraint[i], pi, NbMaxRays, 2 * flag);
4562 /* Add 'p3' in the new domain 'd1' */
4563 d1 = AddPolyToDomain(p3, d1);
4564
4565 /* If the constraint P->constraint[i][0] is an equality, then add */
4566 /* the constraint ( +P->constraint[i] [-1 if flag=0]) >= 0 in 'pi' */
4567 /* and create the new polyhedron 'p3'. */
4568 if (value_zero_p(P->Constraint[i][0])) /* Inequality */
4569 {
4570 p3 = SubConstraint(P->Constraint[i], pi, NbMaxRays, 1 + 2 * flag);
4571 /* Add 'p3' in the new domain 'd1' */
4572 d1 = AddPolyToDomain(p3, d1);
4573
4574 /* newpi : add constraint P->constraint[i]==0 to pi */
4575 newpi = AddConstraints(P->Constraint[i], 1, pi, NbMaxRays);
4576 } else {
4577 /* newpi : add constraint +P->constraint[i] >= 0 in pi */
4578 newpi = SubConstraint(P->Constraint[i], pi, NbMaxRays, 3);
4579 }
4580 if (newpi && emptyQ(newpi)) {
4581 Domain_Free(newpi);
4582 newpi = (Polyhedron *)0;
4583 }
4584 if (pi != p1)
4585 Domain_Free(pi);
4586 pi = newpi;
4587 }
4588 if (pi != p1)
4589 Domain_Free(pi);
4590 }
4591
4592 /* and now d2 */
4593 Pol1 = Polyhedron_Copy(lR);
4594 for (p2 = reste; p2; p2 = p2->next) {
4595 d2 = (Polyhedron *)0;
4596 for (p1 = Pol1; p1; p1 = p1->next) {
4597 pi = p1;
4598 for (i = 0; i < p2->NbConstraints && pi; i++) {
4599 /* Add the constraint ( -p2->constraint[i] [-1 if flag=0]) >= 0 in
4600 * 'pi' */
4601 /* and create the new polyhedron 'p3'. */
4602 p3 = SubConstraint(p2->Constraint[i], pi, NbMaxRays, 2 * flag);
4603 /* Add 'p3' in the new domain 'd2' */
4604 d2 = AddPolyToDomain(p3, d2);
4605
4606 /* If the constraint p2->constraint[i][0] is an equality, then add
4607 */
4608 /* the constraint ( +p2->constraint[i] [-1 if flag=0]) >= 0 in 'pi'
4609 */
4610 /* and create the new polyhedron 'p3'. */
4611 if (value_zero_p(p2->Constraint[i][0])) /* Inequality */
4612 {
4613 p3 =
4614 SubConstraint(p2->Constraint[i], pi, NbMaxRays, 1 + 2 * flag);
4615 /* Add 'p3' in the new domain 'd2' */
4616 d2 = AddPolyToDomain(p3, d2);
4617
4618 /* newpi : add constraint p2->constraint[i]==0 to pi */
4619 newpi = AddConstraints(p2->Constraint[i], 1, pi, NbMaxRays);
4620 } else {
4621 /* newpi : add constraint +p2->constraint[i] >= 0 in pi */
4622 newpi = SubConstraint(p2->Constraint[i], pi, NbMaxRays, 3);
4623 }
4624 if (newpi && emptyQ(newpi)) {
4625 Domain_Free(newpi);
4626 newpi = (Polyhedron *)0;
4627 }
4628 if (pi != p1)
4629 Domain_Free(pi);
4630 pi = newpi;
4631 }
4632 if (pi && pi != p1)
4633 Domain_Free(pi);
4634 }
4635 if (Pol1)
4636 Domain_Free(Pol1);
4637 Pol1 = d2;
4638 }
4639 /* ok, d1 and d2 are computed */
4640
4641 /* now, replace lR by d2+dx (at least dx is nonempty) and set reste to d1
4642 */
4643 if (d1 && emptyQ(d1)) {
4644 Domain_Free(d1);
4645 d1 = NULL;
4646 }
4647 if (d2 && emptyQ(d2)) {
4648 Domain_Free(d2);
4649 d2 = NULL;
4650 }
4651
4652 /* set reste */
4653 Domain_Free(reste);
4654 reste = d1;
4655
4656 /* add d2 at beginning of Result */
4657 if (d2) {
4658 for (tmp = d2; tmp->next; tmp = tmp->next)
4659 ;
4660 tmp->next = Result;
4661 Result = d2;
4662 if (!prec)
4663 prec = tmp;
4664 }
4665
4666 /* add dx at beginning of Result */
4667 for (tmp = dx; tmp->next; tmp = tmp->next)
4668 ;
4669 tmp->next = Result;
4670 Result = dx;
4671 if (!prec)
4672 prec = tmp;
4673
4674 /* suppress current lR */
4675 if (!prec)
4676 errormsg1("Disjoint_Domain", "internalerror", "internal error");
4677 prec->next = lR->next;
4678 Polyhedron_Free(lR);
4679 lR = prec->next;
4680 } /* end for result */
4681
4682 /* if there is something left, add it to Result : */
4683 if (reste) {
4684 if (emptyQ(reste)) {
4685 Domain_Free(reste);
4686 reste = NULL;
4687 } else {
4688 Polyhedron *tnext;
4689 for (tmp = reste; tmp; tmp = tnext) {
4690 tnext = tmp->next;
4691 tmp->next = NULL;
4692 Result = AddPolyToDomain(tmp, Result);
4693 }
4694 }
4695 }
4696 }
4697
4698 return (Result);
4699}
4700
4701/* Procedure to print constraint matrix of a polyhedron */
4702void Polyhedron_PrintConstraints(FILE *Dst, const char *Format,
4703 Polyhedron *Pol) {
4704 int i, j;
4705
4706 fprintf(Dst, "%d %d\n", Pol->NbConstraints, Pol->Dimension + 2);
4707 for (i = 0; i < Pol->NbConstraints; i++) {
4708 for (j = 0; j < Pol->Dimension + 2; j++)
4709 value_print(Dst, Format, Pol->Constraint[i][j]);
4710 fprintf(Dst, "\n");
4711 }
4712}
4713
4714/* Procedure to print constraint matrix of a domain */
4715void Domain_PrintConstraints(FILE *Dst, const char *Format, Polyhedron *Pol) {
4716 Polyhedron *Q;
4717 for (Q = Pol; Q; Q = Q->next)
4718 Polyhedron_PrintConstraints(Dst, Format, Q);
4719}
4720
4722 unsigned MaxRays) {
4723 Polyhedron *T, *R = P;
4724 int len = P->Dimension + 2;
4725 int r;
4726
4727 /* Also look at equalities.
4728 * If an equality can be "simplified" then there
4729 * are no integer solutions and we return an empty polyhedron
4730 */
4731 for (r = 0; r < R->NbConstraints; ++r) {
4732 if (ConstraintSimplify(R->Constraint[r], row->p, len, g)) {
4733 T = R;
4734 if (value_zero_p(R->Constraint[r][0])) {
4736 r = R->NbConstraints;
4737 } else if (POL_ISSET(MaxRays, POL_NO_DUAL)) {
4738 R = Polyhedron_Copy(R);
4740 Vector_Copy(row->p + 1, R->Constraint[r] + 1, R->Dimension + 1);
4741 } else {
4742 R = AddConstraints(row->p, 1, R, MaxRays);
4743 r = -1;
4744 }
4745 if (T != P)
4746 Polyhedron_Free(T);
4747 }
4748 }
4749 if (R != P)
4750 Polyhedron_Free(P);
4751 return R;
4752}
4753
4754/*
4755 * Replaces constraint a x >= c by x >= ceil(c/a)
4756 * where "a" is a common factor in the coefficients
4757 * Destroys P and returns a newly allocated Polyhedron
4758 * or just returns P in case no changes were made
4759 */
4761 if(!P) return(NULL);
4762 Polyhedron **prev;
4763 int len = P->Dimension + 2;
4764 Vector *row = Vector_Alloc(len);
4765 Value g;
4766 Polyhedron *R = P, *N;
4767 value_set_si(row->p[0], 1);
4768 value_init(g);
4769
4770 for (prev = &R; P; P = N) {
4771 Polyhedron *T;
4772 N = P->next;
4773 T = p_simplify_constraints(P, row, &g, MaxRays);
4774
4775 if (emptyQ(T) && prev != &R) {
4776 Polyhedron_Free(T);
4777 *prev = NULL;
4778 continue;
4779 }
4780
4781 if (T != P)
4782 T->next = N;
4783 *prev = T;
4784 prev = &T->next;
4785 }
4786
4787 if (R->next && emptyQ(R)) {
4788 N = R->next;
4789 Polyhedron_Free(R);
4790 R = N;
4791 }
4792
4793 value_clear(g);
4794 Vector_Free(row);
4795 return R;
4796}
4797
4798/**
4799
4800 Free all cache allocated memory: call this function before exiting in a
4801 memory checker environment like valgrind.
4802
4803 Notice that, in a multithreaded environment, *all* your threads have to
4804 call this function
4805
4806*/
4810}
void ExchangeRows(Matrix *M, int Row1, int Row2)
Definition: Matop.c:52
Matrix * Matrix_Copy(Matrix const *Src)
Definition: Matop.c:98
#define CATCH(what)
#define UNCATCH(what)
#define RETHROW()
#define TRY
#define value_pos_p(val)
Definition: arithmetique.h:574
#define value_sign(v)
Definition: arithmetique.h:520
#define value_oppose(ref, val)
Definition: arithmetique.h:555
#define value_sub_int(ref, val, vint)
Definition: arithmetique.h:548
#define value_gt(v1, v2)
Definition: arithmetique.h:507
#define value_abs_eq(v1, v2)
Definition: arithmetique.h:512
#define VALUE_TO_INT(val)
Definition: arithmetique.h:304
#define value_notzero_p(val)
Definition: arithmetique.h:579
#define value_divexact(ref, val1, val2)
Definition: arithmetique.h:551
#define value_gcd(ref, val1, val2)
Definition: arithmetique.h:559
#define value_notone_p(val)
Definition: arithmetique.h:581
#define value_one_p(val)
Definition: arithmetique.h:580
#define value_abs_ne(v1, v2)
Definition: arithmetique.h:513
#define value_absolute(ref, val)
Definition: arithmetique.h:556
#define VALUE_FMT
Definition: arithmetique.h:295
#define value_add_int(ref, val, vint)
Definition: arithmetique.h:541
#define value_decrement(ref, val)
Definition: arithmetique.h:549
#define value_abs_lt(v1, v2)
Definition: arithmetique.h:516
#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_print(Dst, fmt, val)
Definition: arithmetique.h:490
#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_neg_p(val)
Definition: arithmetique.h:575
#define value_init(val)
Definition: arithmetique.h:484
#define value_cmp_si(val, n)
Definition: arithmetique.h:584
#define assert(ex)
Definition: assert.h:16
unsigned int any_exception_error
Definition: errors.c:103
void free_exception_stack()
Definition: errors.c:207
void Matrix_Extend(Matrix *Mat, unsigned NbRows)
Definition: matrix.c:84
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 Matrix_Free(Matrix *Mat)
Definition: matrix.c:69
void PolyPrint(Polyhedron *Pol)
Definition: polyhedron.c:1717
static void SortConstraints(Matrix *Constraints, unsigned NbEq)
Definition: polyhedron.c:1799
int PolyhedronIncludes(Polyhedron *Pol1, Polyhedron *Pol2)
Definition: polyhedron.c:2412
static Polyhedron * Remove_Redundants(Matrix *Mat, Matrix *Ray, SatMatrix *Sat, unsigned *Filter)
Definition: polyhedron.c:863
Polyhedron * DomainAddRays(Polyhedron *Pol, Matrix *Ray, unsigned NbMaxConstrs)
Add rays pointed by 'Ray' to each and every polyhedron in the polyhedral domain 'Pol'.
Definition: polyhedron.c:2805
void errormsg1(const char *f, const char *msgname, const char *msg)
Definition: errormsg.c:25
Polyhedron * align_context(Polyhedron *Pol, int align_dimension, int NbMaxRays)
Definition: polyhedron.c:3704
void Domain_PrintConstraints(FILE *Dst, const char *Format, Polyhedron *Pol)
Definition: polyhedron.c:4715
Polyhedron * Polyhedron_Image(Polyhedron *Pol, Matrix *Func, unsigned NbMaxConstrs)
Definition: polyhedron.c:4167
Polyhedron * Disjoint_Domain(Polyhedron *P, int flag, unsigned NbMaxRays)
Definition: polyhedron.c:4503
static int Gauss4(Value **p, int NbEq, int NbRows, int Dimension)
Definition: polyhedron.c:740
#define SMVector_Copy(p1, p2, length)
Definition: polyhedron.c:186
void Polyhedron_PrintConstraints(FILE *Dst, const char *Format, Polyhedron *Pol)
Definition: polyhedron.c:4702
Polyhedron * AddRays(Value *AddedRays, unsigned NbAddedRays, Polyhedron *Pol, unsigned NbMaxConstrs)
Add 'NbAddedRays' rays to polyhedron 'Pol'.
Definition: polyhedron.c:2707
Polyhedron * Stras_DomainSimplify(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Definition: polyhedron.c:3404
static void Rays_Mult(Value **A, Matrix *B, Value **C, unsigned NbRays)
Definition: polyhedron.c:3990
#define SMVector_Init(p1, length)
Definition: polyhedron.c:192
static void SMFree(SatMatrix **matrix)
Definition: polyhedron.c:129
static void SatMatrix_Extend(SatMatrix *Sat, unsigned rows, unsigned cols)
Definition: polyhedron.c:359
Polyhedron * DomainAddConstraints(Polyhedron *Pol, Matrix *Mat, unsigned NbMaxRays)
Definition: polyhedron.c:4448
static void addToFilter(int k, unsigned *Filter, SatMatrix *Sat, int *tmpR, int *tmpC, int NbRays, int NbConstraints)
Definition: polyhedron.c:2918
void Polyhedron_Free(Polyhedron *Pol)
Definition: polyhedron.c:1621
void Polyhedron_Compute_Dual(Polyhedron *P)
Definition: polyhedron.c:2213
Polyhedron * DomainConvex(Polyhedron *Pol, unsigned NbMaxConstrs)
Definition: polyhedron.c:3606
static SatMatrix * SMAlloc(int rows, int cols)
Definition: polyhedron.c:93
Polyhedron * Empty_Polyhedron(unsigned Dimension)
Definition: polyhedron.c:1728
Polyhedron * DomainConstraintSimplify(Polyhedron *P, unsigned MaxRays)
Definition: polyhedron.c:4760
static int Chernikova(Matrix *Mat, Matrix *Ray, SatMatrix *Sat, unsigned NbBid, unsigned NbMaxRays, unsigned FirstConstraint, unsigned dual)
Definition: polyhedron.c:392
int Gauss(Matrix *Mat, int NbEq, int Dimension)
Definition: polyhedron.c:834
Polyhedron * Polyhedron_Scan(Polyhedron *D, Polyhedron *C, unsigned NbMaxRays)
Definition: polyhedron.c:3791
Polyhedron * DomainDifference(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Definition: polyhedron.c:3641
Polyhedron * AddPolyToDomain(Polyhedron *Pol, Polyhedron *PolDomain)
Definition: polyhedron.c:2460
Polyhedron * Polyhedron_Preimage(Polyhedron *Pol, Matrix *Func, unsigned NbMaxRays)
Definition: polyhedron.c:4076
Polyhedron * DomainIntersection(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Definition: polyhedron.c:2648
Interval * DomainCost(Polyhedron *Pol, Value *Cost)
Definition: polyhedron.c:4303
#define WSIZE
Definition: polyhedron.c:48
Polyhedron * Polyhedron_Copy(Polyhedron *Pol)
Definition: polyhedron.c:2851
#define exchange(a, b, t)
Definition: polyhedron.c:60
Polyhedron * Domain_Copy(Polyhedron *Pol)
Definition: polyhedron.c:2878
static void FindSimple(Polyhedron *P1, Polyhedron *P2, unsigned *Filter, unsigned NbMaxRays)
Definition: polyhedron.c:2963
Polyhedron * DomainPreimage(Polyhedron *Pol, Matrix *Func, unsigned NbMaxRays)
Definition: polyhedron.c:4138
Polyhedron * DomainSimplify(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Definition: polyhedron.c:3291
Polyhedron * Universe_Polyhedron(unsigned Dimension)
Definition: polyhedron.c:1761
static int SimplifyConstraints(Polyhedron *Pol1, Polyhedron *Pol2, unsigned *Filter, unsigned NbMaxRays)
Definition: polyhedron.c:3147
static SatMatrix * TransformSat(Matrix *Mat, Matrix *Ray, SatMatrix *Sat)
Definition: polyhedron.c:261
Polyhedron * Rays2Polyhedron(Matrix *Ray, unsigned NbMaxConstrs)
Given a matrix of rays 'Ray', create and return a polyhedron.
Definition: polyhedron.c:2094
Polyhedron * DomainUnion(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Definition: polyhedron.c:3530
int Pol_status
Definition: polyhedron.c:73
int lower_upper_bounds(int pos, Polyhedron *P, Value *context, Value *LBp, Value *UBp)
Definition: polyhedron.c:3859
void polylib_close()
Free all cache allocated memory: call this function before exiting in a memory checker environment li...
Definition: polyhedron.c:4807
#define bexchange(a, b, l)
Definition: polyhedron.c:50
static void SatVector_OR(int *p1, int *p2, int *p3, unsigned length)
Definition: polyhedron.c:167
Matrix * Polyhedron2Constraints(Polyhedron *Pol)
Definition: polyhedron.c:2067
Polyhedron * DomainImage(Polyhedron *Pol, Matrix *Func, unsigned NbMaxConstrs)
Definition: polyhedron.c:4266
Polyhedron * Polyhedron_Alloc(unsigned Dimension, unsigned NbConstraints, unsigned NbRays)
Definition: polyhedron.c:1573
Polyhedron * Constraints2Polyhedron(Matrix *Constraints, unsigned NbMaxRays)
Given a matrix of constraints ('Constraints'), construct and return a polyhedron.
Definition: polyhedron.c:1912
Polyhedron * AddConstraints(Value *Con, unsigned NbConstraints, Polyhedron *Pol, unsigned NbMaxRays)
Definition: polyhedron.c:2311
void Polyhedron_Print(FILE *Dst, const char *Format, const Polyhedron *Pol)
Definition: polyhedron.c:1646
static void Rays_Mult_Transpose(Value **A, Matrix *B, Value **C, unsigned NbRays)
Definition: polyhedron.c:4031
void Domain_Free(Polyhedron *Pol)
Definition: polyhedron.c:1633
static void SimplifyEqualities(Polyhedron *Pol1, Polyhedron *Pol2, unsigned *Filter)
Definition: polyhedron.c:3238
Polyhedron * SubConstraint(Value *Con, Polyhedron *Pol, unsigned NbMaxRays, int Pass)
Definition: polyhedron.c:2540
static void Combine(Value *p1, Value *p2, Value *p3, int pos, unsigned length)
Definition: polyhedron.c:205
static int ImplicitEqualities(Matrix *Constraints, unsigned NbEq)
Definition: polyhedron.c:1843
static void RaySort(Matrix *Ray, SatMatrix *Sat, int NbBid, int NbRay, int *equal_bound, int *sup_bound, unsigned RowSize1, unsigned RowSize2, unsigned bx, unsigned jx)
Definition: polyhedron.c:300
static Polyhedron * p_simplify_constraints(Polyhedron *P, Vector *row, Value *g, unsigned MaxRays)
Definition: polyhedron.c:4721
static SatMatrix * BuildSat(Matrix *Mat, Matrix *Ray, unsigned NbConstraints, unsigned NbMaxRays)
Definition: polyhedron.c:2251
Matrix * Polyhedron2Rays(Polyhedron *Pol)
Given a polyhedron 'Pol', return a matrix of rays.
Definition: polyhedron.c:2683
#define POL_ENSURE_VERTICES(P)
Definition: polyhedron.h:17
#define POL_ENSURE_INEQUALITIES(P)
Definition: polyhedron.h:5
#define POL_ENSURE_POINTS(P)
Definition: polyhedron.h:9
#define POL_ENSURE_FACETS(P)
Definition: polyhedron.h:13
static SatMatrix * Sat
Definition: polyparam.c:283
static int m
Definition: polyparam.c:276
static int n
Definition: polyparam.c:278
unsigned int NbRows
Definition: polyhedron.c:84
int ** p
Definition: polyhedron.c:86
unsigned int NbColumns
Definition: polyhedron.c:85
int * p_init
Definition: polyhedron.c:87
Definition: types.h:82
unsigned Size
Definition: types.h:83
Value * p
Definition: types.h:84
Value MinD
Definition: types.h:129
int MaxI
Definition: types.h:130
Value MaxN
Definition: types.h:128
int MinI
Definition: types.h:130
Value MinN
Definition: types.h:129
Value MaxD
Definition: types.h:128
Definition: types.h:88
unsigned NbRows
Definition: types.h:89
Value ** p
Definition: types.h:90
unsigned NbColumns
Definition: types.h:89
Value * p_Init
Definition: types.h:91
Value ** Ray
Definition: types.h:112
unsigned Dimension
Definition: types.h:110
unsigned NbConstraints
Definition: types.h:110
Value * p_Init
Definition: types.h:113
unsigned NbRays
Definition: types.h:110
unsigned NbBid
Definition: types.h:110
struct polyhedron * next
Definition: types.h:115
Value ** Constraint
Definition: types.h:111
unsigned flags
Definition: types.h:124
int p_Init_size
Definition: types.h:114
unsigned NbEq
Definition: types.h:110
#define MSB
Definition: types.h:57
#define emptyQ(P)
Definition: types.h:134
#define POL_INEQUALITIES
Definition: types.h:116
#define POL_VERTICES
Definition: types.h:119
#define F_ISSET(p, f)
Definition: types.h:107
#define POL_ISSET(flags, f)
Definition: types.h:77
#define POL_VALID
Definition: types.h:123
#define NEXT(j, b)
Definition: types.h:63
#define UB_INFINITY
Definition: types.h:53
#define POL_NO_DUAL
Definition: types.h:75
#define POL_POINTS
Definition: types.h:118
#define F_SET(p, f)
Definition: types.h:105
#define LB_INFINITY
Definition: types.h:52
#define F_CLR(p, f)
Definition: types.h:106
#define POL_INTEGER
Definition: types.h:76
#define POL_FACETS
Definition: types.h:117
#define P_VALUE_FMT
Definition: types.h:42
Value * value_alloc(int want, int *got)
Definition: vector.c:826
void Vector_Free(Vector *vector)
Definition: vector.c:187
void Vector_Scale(Value *p1, Value *p2, Value lambda, unsigned length)
Definition: vector.c:360
void Vector_Set(Value *p, int n, unsigned length)
Definition: vector.c:248
void Inner_Product(Value *p1, Value *p2, unsigned length, Value *ip)
Definition: vector.c:403
void value_free(Value *p, int size)
Definition: vector.c:875
void Vector_Combine(Value *p1, Value *p2, Value *p3, Value lambda, Value mu, unsigned length)
Definition: vector.c:455
void Vector_Gcd(Value *p, unsigned length, Value *min)
Definition: vector.c:518
void Vector_Exchange(Value *p1, Value *p2, unsigned length)
Definition: vector.c:263
void Vector_AntiScale(Value *p1, Value *p2, Value lambda, unsigned length)
Definition: vector.c:381
void Vector_Normalize(Value *p, unsigned length)
Definition: vector.c:588
int Vector_Equal(Value *Vec1, Value *Vec2, unsigned length)
Definition: vector.c:474
Vector * Vector_Alloc(unsigned length)
Definition: vector.c:134
void Vector_Copy(Value *p1, Value *p2, unsigned length)
Definition: vector.c:276
int First_Non_Zero(Value *p, unsigned length)
Definition: vector.c:117
void free_value_cache()
Definition: vector.c:901
void Vector_Oppose(Value *p1, Value *p2, unsigned len)
Definition: vector.c:392
int ConstraintSimplify(Value *old, Value *newp, int len, Value *v)
Definition: vector.c:743
Value max
Definition: verif_ehrhart.c:43