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