polylib 5.22.8
ehrhart.c
Go to the documentation of this file.
1/***********************************************************************/
2/* Ehrhart V4.20 */
3/* copyright 1997, Doran Wilde */
4/* copyright 1997-2000, Vincent Loechner */
5/***********************************************************************/
6
7#include <assert.h>
8#include <ctype.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <unistd.h>
13
15#include <polylib/polylib.h>
16
17/*! \class Ehrhart
18
19The following are mainly for debug purposes. You shouldn't need to
20change anything for daily usage...
21
22<p>
23
24you may define each macro independently
25<ol>
26<li> #define EDEBUG minimal debug
27<li> #define EDEBUG1 prints enumeration points
28<li> #define EDEBUG11 prints number of points
29<li> #define EDEBUG2 prints domains
30<li> #define EDEBUG21 prints more domains
31<li> #define EDEBUG3 prints systems of equations that are solved
32<li> #define EDEBUG4 prints message for degree reduction
33<li> #define EDEBUG5 prints result before simplification
34<li> #define EDEBUG6 prints domains in Preprocess
35<li> #define EDEBUG61 prints even more in Preprocess
36<li> #define EDEBUG62 prints domains in Preprocess2
37</ol>
38*/
39
40/**
41
42define this to print all constraints on the validity domains if not
43defined, only new constraints (not in validity domain given by the
44user) are printed
45
46*/
47#define EPRINT_ALL_VALIDITY_CONSTRAINTS
48
49/* #define EDEBUG */ /* minimal debug */
50/* #define EDEBUG1 */ /* prints enumeration points */
51/* #define EDEBUG11 */ /* prints number of points */
52/* #define EDEBUG2 */ /* prints domains */
53/* #define EDEBUG21 */ /* prints more domains */
54/* #define EDEBUG3 */ /* prints systems of equations that are solved */
55/* #define EDEBUG4 */ /* prints message for degree reduction */
56/* #define EDEBUG5 */ /* prints result before simplification */
57/* #define EDEBUG6 */ /* prints domains in Preprocess */
58/* #define EDEBUG61 */ /* prints even more in Preprocess */
59/* #define EDEBUG62 */ /* prints domains in Preprocess2 */
60
61/**
62 Reduce the degree of resulting polynomials
63*/
64#define REDUCE_DEGREE
65
66/**
67define this to print one warning message per domain overflow these
68overflows should no longer happen since version 4.20
69*/
70#define ALL_OVERFLOW_WARNINGS
71
72/******************* -----------END USER #DEFS-------- *********************/
73
75
76/*-------------------------------------------------------------------*/
77/* EHRHART POLYNOMIAL SYMBOLIC ALGEBRA SYSTEM */
78/*-------------------------------------------------------------------*/
79/**
80
81EHRHART POLYNOMIAL SYMBOLIC ALGEBRA SYSTEM. The newly allocated enode
82can be freed with a simple free(x)
83
84@param type : enode type
85@param size : degree+1 for polynomial, period for periodic
86@param pos : 1..nb_param, position of parameter
87@return a newly allocated enode
88
89*/
90enode *new_enode(enode_type type, int size, int pos) {
91
92 enode *res;
93 int i;
94
95 if (size == 0) {
96 fprintf(stderr, "Allocating enode of size 0 !\n");
97 return NULL;
98 }
99 res = (enode *)malloc(sizeof(enode) + (size - 1) * sizeof(evalue));
100 res->type = type;
101 res->size = size;
102 res->pos = pos;
103 for (i = 0; i < size; i++) {
104 value_init(res->arr[i].d);
105 value_set_si(res->arr[i].d, 0);
106 res->arr[i].x.p = 0;
107 }
108 return res;
109} /* new_enode */
110
111/**
112releases all memory referenced by e. (recursive)
113@param e pointer to an evalue
114*/
116
117 enode *p;
118 int i;
119
120 if (value_notzero_p(e->d)) {
121
122 /* 'e' stores a constant */
123 value_clear(e->d);
124 value_clear(e->x.n);
125 return;
126 }
127 value_clear(e->d);
128 p = e->x.p;
129 if (!p)
130 return; /* null pointer */
131 for (i = 0; i < p->size; i++) {
132 free_evalue_refs(&(p->arr[i]));
133 }
134 free(p);
135 return;
136} /* free_evalue_refs */
137
138/**
139
140@param e pointer to an evalue
141@return description
142
143*/
145
146 enode *res;
147 int i;
148
149 res = new_enode(e->type, e->size, e->pos);
150 for (i = 0; i < e->size; ++i) {
151 value_assign(res->arr[i].d, e->arr[i].d);
152 if (value_zero_p(res->arr[i].d))
153 res->arr[i].x.p = ecopy(e->arr[i].x.p);
154 else {
155 value_init(res->arr[i].x.n);
156 value_assign(res->arr[i].x.n, e->arr[i].x.n);
157 }
158 }
159 return (res);
160} /* ecopy */
161
162/**
163
164@param DST destination file
165@param e pointer to evalue to be printed
166@param pname array of strings, name of the parameters
167
168*/
169void print_evalue(FILE *DST, evalue *e, const char **pname) {
170 if (value_notzero_p(e->d)) {
171 if (value_notone_p(e->d)) {
172 value_print(DST, VALUE_FMT, e->x.n);
173 fprintf(DST, "/");
174 value_print(DST, VALUE_FMT, e->d);
175 } else {
176 value_print(DST, VALUE_FMT, e->x.n);
177 }
178 } else
179 print_enode(DST, e->x.p, pname);
180 return;
181} /* print_evalue */
182
183/** prints the enode to DST
184
185@param DST destination file
186@param p pointer to enode to be printed
187@param pname array of strings, name of the parameters
188
189*/
190void print_enode(FILE *DST, enode *p, const char **pname) {
191 int i;
192
193 if (!p) {
194 fprintf(DST, "NULL");
195 return;
196 }
197 if (p->type == evector) {
198 fprintf(DST, "{ ");
199 for (i = 0; i < p->size; i++) {
200 print_evalue(DST, &p->arr[i], pname);
201 if (i != (p->size - 1))
202 fprintf(DST, ", ");
203 }
204 fprintf(DST, " }\n");
205 } else if (p->type == polynomial) {
206 fprintf(DST, "( ");
207 for (i = p->size - 1; i >= 0; i--) {
208 print_evalue(DST, &p->arr[i], pname);
209 if (i == 1)
210 fprintf(DST, " * %s + ", pname[p->pos - 1]);
211 else if (i > 1)
212 fprintf(DST, " * %s^%d + ", pname[p->pos - 1], i);
213 }
214 fprintf(DST, " )\n");
215 } else if (p->type == periodic) {
216 fprintf(DST, "[ ");
217 for (i = 0; i < p->size; i++) {
218 print_evalue(DST, &p->arr[i], pname);
219 if (i != (p->size - 1))
220 fprintf(DST, ", ");
221 }
222 fprintf(DST, " ]_%s", pname[p->pos - 1]);
223 }
224 return;
225} /* print_enode */
226
227/**
228
229@param e1 pointers to evalues
230@param e2 pointers to evalues
231@return 1 (true) if they are equal, 0 (false) if not
232
233*/
234static int eequal(evalue *e1, evalue *e2) {
235
236 int i;
237 enode *p1, *p2;
238
239 if (value_ne(e1->d, e2->d))
240 return 0;
241
242 /* e1->d == e2->d */
243 if (value_notzero_p(e1->d)) {
244 if (value_ne(e1->x.n, e2->x.n))
245 return 0;
246
247 /* e1->d == e2->d != 0 AND e1->n == e2->n */
248 return 1;
249 }
250
251 /* e1->d == e2->d == 0 */
252 p1 = e1->x.p;
253 p2 = e2->x.p;
254 if (p1->type != p2->type)
255 return 0;
256 if (p1->size != p2->size)
257 return 0;
258 if (p1->pos != p2->pos)
259 return 0;
260 for (i = 0; i < p1->size; i++)
261 if (!eequal(&p1->arr[i], &p2->arr[i]))
262 return 0;
263 return 1;
264} /* eequal */
265
266/**
267
268@param e pointer to an evalue
269
270*/
272
273 enode *p;
274 int i, j, k;
275
276 if (value_notzero_p(e->d))
277 return; /* a rational number, its already reduced */
278 if (!(p = e->x.p))
279 return; /* hum... an overflow probably occured */
280
281 /* First reduce the components of p */
282 for (i = 0; i < p->size; i++)
283 reduce_evalue(&p->arr[i]);
284
285 if (p->type == periodic) {
286
287 /* Try to reduce the period */
288 for (i = 1; i <= (p->size) / 2; i++) {
289 if ((p->size % i) == 0) {
290
291 /* Can we reduce the size to i ? */
292 for (j = 0; j < i; j++)
293 for (k = j + i; k < e->x.p->size; k += i)
294 if (!eequal(&p->arr[j], &p->arr[k]))
295 goto you_lose;
296
297 /* OK, lets do it */
298 for (j = i; j < p->size; j++)
299 free_evalue_refs(&p->arr[j]);
300 p->size = i;
301 break;
302
303 you_lose: /* OK, lets not do it */
304 continue;
305 }
306 }
307
308 /* Try to reduce its strength */
309 if (p->size == 1) {
310 value_clear(e->d);
311 memcpy(e, &p->arr[0], sizeof(evalue));
312 free(p);
313 }
314 } else if (p->type == polynomial) {
315
316 /* Try to reduce the degree */
317 for (i = p->size - 1; i >= 1; i--) {
318 if (!(value_one_p(p->arr[i].d) && value_zero_p(p->arr[i].x.n)))
319 break;
320 /* Zero coefficient */
321 free_evalue_refs(&p->arr[i]);
322 }
323 if (i + 1 < p->size)
324 p->size = i + 1;
325
326 /* Try to reduce its strength */
327 if (p->size == 1) {
328 value_clear(e->d);
329 memcpy(e, &p->arr[0], sizeof(evalue));
330 free(p);
331 }
332 }
333} /* reduce_evalue */
334
335/**
336
337multiplies two evalues and puts the result in res
338
339@param e1 pointer to an evalue
340@param e2 pointer to a constant evalue
341@param res pointer to result evalue = e1 * e2
342
343*/
344static void emul(evalue *e1, evalue *e2, evalue *res) {
345
346 enode *p;
347 int i;
348 Value g;
349
350 if (value_zero_p(e2->d)) {
351 fprintf(stderr, "emul: ?expecting constant value\n");
352 return;
353 }
354 value_init(g);
355 if (value_notzero_p(e1->d)) {
356
357 value_init(res->x.n);
358 /* Product of two rational numbers */
359 value_multiply(res->d, e1->d, e2->d);
360 value_multiply(res->x.n, e1->x.n, e2->x.n);
361 value_gcd(g, res->x.n, res->d);
362 if (value_notone_p(g)) {
363 value_divexact(res->d, res->d, g);
364 value_divexact(res->x.n, res->x.n, g);
365 }
366 } else { /* e1 is an expression */
367 value_set_si(res->d, 0);
368 p = e1->x.p;
369 res->x.p = new_enode(p->type, p->size, p->pos);
370 for (i = 0; i < p->size; i++) {
371 emul(&p->arr[i], e2, &(res->x.p->arr[i]));
372 }
373 }
374 value_clear(g);
375 return;
376} /* emul */
377
378/**
379adds one evalue to evalue 'res. result = res + e1
380
381@param e1 an evalue
382@param res
383
384*/
385void eadd(evalue *e1, evalue *res) {
386
387 int i;
388 Value g, m1, m2;
389
390 value_init(g);
391 value_init(m1);
392 value_init(m2);
393
394 if (value_notzero_p(e1->d) && value_notzero_p(res->d)) {
395
396 /* Add two rational numbers*/
397 value_multiply(m1, e1->x.n, res->d);
398 value_multiply(m2, res->x.n, e1->d);
399 value_addto(res->x.n, m1, m2);
400 value_multiply(res->d, e1->d, res->d);
401 value_gcd(g, res->x.n, res->d);
402 if (value_notone_p(g)) {
403 value_divexact(res->d, res->d, g);
404 value_divexact(res->x.n, res->x.n, g);
405 }
406 value_clear(g);
407 value_clear(m1);
408 value_clear(m2);
409 return;
410 } else if (value_notzero_p(e1->d) && value_zero_p(res->d)) {
411 if (res->x.p->type == polynomial) {
412
413 /* Add the constant to the constant term */
414 eadd(e1, &res->x.p->arr[0]);
415 value_clear(g);
416 value_clear(m1);
417 value_clear(m2);
418 return;
419 } else if (res->x.p->type == periodic) {
420
421 /* Add the constant to all elements of periodic number */
422 for (i = 0; i < res->x.p->size; i++) {
423 eadd(e1, &res->x.p->arr[i]);
424 }
425 value_clear(g);
426 value_clear(m1);
427 value_clear(m2);
428 return;
429 } else {
430 fprintf(stderr, "eadd: cannot add const with vector\n");
431 value_clear(g);
432 value_clear(m1);
433 value_clear(m2);
434 return;
435 }
436 } else if (value_zero_p(e1->d) && value_notzero_p(res->d)) {
437 fprintf(stderr, "eadd: cannot add evalue to const\n");
438 value_clear(g);
439 value_clear(m1);
440 value_clear(m2);
441 return;
442 } else { /* ((e1->d==0) && (res->d==0)) */
443 if ((e1->x.p->type != res->x.p->type) || (e1->x.p->pos != res->x.p->pos)) {
444 fprintf(stderr, "eadd: ?cannot add, incompatible types\n");
445 value_clear(g);
446 value_clear(m1);
447 value_clear(m2);
448 return;
449 }
450 if (e1->x.p->size == res->x.p->size) {
451 for (i = 0; i < res->x.p->size; i++) {
452 eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
453 }
454 value_clear(g);
455 value_clear(m1);
456 value_clear(m2);
457 return;
458 }
459
460 /* Sizes are different */
461 if (res->x.p->type == polynomial) {
462
463 /* VIN100: if e1-size > res-size you have to copy e1 in a */
464 /* new enode and add res to that new node. If you do not do */
465 /* that, you lose the the upper weight part of e1 ! */
466
467 if (e1->x.p->size > res->x.p->size) {
468 enode *tmp;
469 tmp = ecopy(e1->x.p);
470 for (i = 0; i < res->x.p->size; ++i) {
471 eadd(&res->x.p->arr[i], &tmp->arr[i]);
472 free_evalue_refs(&res->x.p->arr[i]);
473 }
474 res->x.p = tmp;
475 } else {
476 for (i = 0; i < e1->x.p->size; i++) {
477 eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
478 }
479 value_clear(g);
480 value_clear(m1);
481 value_clear(m2);
482 return;
483 }
484 } else if (res->x.p->type == periodic) {
485 fprintf(stderr, "eadd: ?addition of different sized periodic nos\n");
486 value_clear(g);
487 value_clear(m1);
488 value_clear(m2);
489 return;
490 } else { /* evector */
491 fprintf(stderr, "eadd: ?cannot add vectors of different length\n");
492 value_clear(g);
493 value_clear(m1);
494 value_clear(m2);
495 return;
496 }
497 }
498 value_clear(g);
499 value_clear(m1);
500 value_clear(m2);
501 return;
502} /* eadd */
503
504/**
505
506computes the inner product of two vectors. Result = result (evalue) =
507v1.v2 (dot product)
508
509@param v1 an enode (vector)
510@param v2 an enode (vector of constants)
511@param res result (evalue)
512
513*/
514void edot(enode *v1, enode *v2, evalue *res) {
515
516 int i;
517 evalue tmp;
518
519 if ((v1->type != evector) || (v2->type != evector)) {
520 fprintf(stderr, "edot: ?expecting vectors\n");
521 return;
522 }
523 if (v1->size != v2->size) {
524 fprintf(stderr, "edot: ? vector lengths do not agree\n");
525 return;
526 }
527 if (v1->size <= 0) {
528 value_set_si(res->d, 1); /* set result to 0/1 */
529 value_init(res->x.n);
530 value_set_si(res->x.n, 0);
531 return;
532 }
533
534 /* vector v2 is expected to have only rational numbers in */
535 /* the array. No pointers. */
536 emul(&v1->arr[0], &v2->arr[0], res);
537 for (i = 1; i < v1->size; i++) {
538 value_init(tmp.d);
539
540 /* res = res + v1[i]*v2[i] */
541 emul(&v1->arr[i], &v2->arr[i], &tmp);
542 eadd(&tmp, res);
543 free_evalue_refs(&tmp);
544 }
545 return;
546} /* edot */
547
548/**
549
550local recursive function used in the following ref contains the new
551position for each old index position
552
553@param e pointer to an evalue
554@param ref transformation Matrix
555
556*/
557static void aep_evalue(evalue *e, int *ref) {
558
559 enode *p;
560 int i;
561
562 if (value_notzero_p(e->d))
563 return; /* a rational number, its already reduced */
564 if (!(p = e->x.p))
565 return; /* hum... an overflow probably occured */
566
567 /* First check the components of p */
568 for (i = 0; i < p->size; i++)
569 aep_evalue(&p->arr[i], ref);
570
571 /* Then p itself */
572 p->pos = ref[p->pos - 1] + 1;
573 return;
574} /* aep_evalue */
575
576/** Comments */
578
579 enode *p;
580 int i, j;
581 int *ref;
582
583 if (value_notzero_p(e->d))
584 return; /* a rational number, its already reduced */
585 if (!(p = e->x.p))
586 return; /* hum... an overflow probably occured */
587
588 /* Compute ref */
589 ref = (int *)malloc(sizeof(int) * (CT->NbRows - 1));
590 for (i = 0; i < CT->NbRows - 1; i++)
591 for (j = 0; j < CT->NbColumns; j++)
592 if (value_notzero_p(CT->p[i][j])) {
593 ref[i] = j;
594 break;
595 }
596
597 /* Transform the references in e, using ref */
598 aep_evalue(e, ref);
599 free(ref);
600 return;
601} /* addeliminatedparams_evalue */
602
603/**
604
605This procedure finds an integer point contained in polyhedron D /
606first checks for positive values, then for negative values returns
607TRUE on success. Result is in min. returns FALSE if no integer point
608is found
609
610<p>
611
612This is the maximum number of iterations for a given parameter to find
613a integer point inside the context. Kind of weird. cherche_min should
614
615<p>
616
617@param min
618@param D
619@param pos
620
621*/
622/* FIXME: needs to be rewritten ! */
623#define MAXITER 100
624int cherche_min(Value *min, Polyhedron *D, int pos) {
625
626 Value binf, bsup; /* upper & lower bound */
627 Value i;
628 int flag, maxiter;
629
630 if (!D)
631 return (1);
632 if (pos > D->Dimension)
633 return (1);
634
635 value_init(binf);
636 value_init(bsup);
637 value_init(i);
638
639#ifdef EDEBUG61
640 fprintf(stderr, "Entering Cherche min --> \n");
641 fprintf(stderr, "LowerUpperBounds :\n");
642 fprintf(stderr, "pos = %d\n", pos);
643 fprintf(stderr, "current min = (");
644 value_print(stderr, P_VALUE_FMT, min[1]);
645 {
646 int j;
647 for (j = 2; j <= D->Dimension; j++) {
648 fprintf(stderr, ", ");
649 value_print(stderr, P_VALUE_FMT, min[j]);
650 }
651 }
652 fprintf(stderr, ")\n");
653#endif
654
655 flag = lower_upper_bounds(pos, D, min, &binf, &bsup);
656
657#ifdef EDEBUG61
658 fprintf(stderr, "flag = %d\n", flag);
659 fprintf(stderr, "binf = ");
660 value_print(stderr, P_VALUE_FMT, binf);
661 fprintf(stderr, "\n");
662 fprintf(stderr, "bsup = ");
663 value_print(stderr, P_VALUE_FMT, bsup);
664 fprintf(stderr, "\n");
665#endif
666
667 if (flag & LB_INFINITY)
668 value_set_si(binf, 0);
669
670 /* Loop from 0 (or binf if positive) to bsup */
671 for (maxiter = 0,
672 (((flag & LB_INFINITY) || value_neg_p(binf)) ? value_set_si(i, 0)
673 : value_assign(i, binf));
674 ((flag & UB_INFINITY) || value_le(i, bsup)) && maxiter < MAXITER;
675 value_increment(i, i), maxiter++) {
676
677 value_assign(min[pos], i);
678 if (cherche_min(min, D->next, pos + 1)) {
679 value_clear(binf);
680 value_clear(bsup);
681 value_clear(i);
682 return (1);
683 }
684 }
685
686 /* Descending loop from -1 (or bsup if negative) to binf */
687 if ((flag & LB_INFINITY) || value_neg_p(binf))
688 for (maxiter = 0,
689 (((flag & UB_INFINITY) || value_pos_p(bsup)) ? value_set_si(i, -1)
690 : value_assign(i, bsup));
691 ((flag & LB_INFINITY) || value_ge(i, binf)) && maxiter < MAXITER;
692 value_decrement(i, i), maxiter++) {
693
694 value_assign(min[pos], i);
695 if (cherche_min(min, D->next, pos + 1)) {
696 value_clear(binf);
697 value_clear(bsup);
698 value_clear(i);
699 return (1);
700 }
701 }
702 value_clear(binf);
703 value_clear(bsup);
704 value_clear(i);
705
706 value_set_si(min[pos], 0);
707 return (0); /* not found :-( */
708} /* cherche_min */
709
710/**
711
712This procedure finds the smallest parallelepiped of size
713'<i>size[i]</i>' for every dimension i, contained in polyhedron D.
714If this is not possible, NULL is returned
715
716<p>
717
718<pre>
719written by vin100, 2000, for version 4.19
720modified 2002, version 5.10
721</pre>
722
723<p>
724
725It first finds the coordinates of the lexicographically smallest edge
726of the hypercube, obtained by transforming the constraints of D (by
727adding 'size' as many times as there are negative coeficients in each
728constraint), and finding the lexicographical min of this
729polyhedron. Then it builds the hypercube and returns it.
730
731<p>
732@param D
733@param size
734@param MAXRAYS
735
736*/
737
739 unsigned MAXRAYS) {
740 Matrix *M;
741 int i, j, d;
742 Polyhedron *T, *S, *H, *C;
743 Value *min;
744
745 d = D->Dimension;
746 if (MAXRAYS < 2 * D->NbConstraints)
747 MAXRAYS = 2 * D->NbConstraints;
748 M = Matrix_Alloc(MAXRAYS, D->Dimension + 2);
749 M->NbRows = D->NbConstraints;
750
751 /* Original constraints */
752 for (i = 0; i < D->NbConstraints; i++)
753 Vector_Copy(D->Constraint[i], M->p[i], (d + 2));
754
755#ifdef EDEBUG6
756 fprintf(stderr, "M for PreProcess : ");
757 Matrix_Print(stderr, P_VALUE_FMT, M);
758 fprintf(stderr, "\nsize == ");
759 for (i = 0; i < d; i++)
760 value_print(stderr, P_VALUE_FMT, size[i]);
761 fprintf(stderr, "\n");
762#endif
763
764 /* Additionnal constraints */
765 for (i = 0; i < D->NbConstraints; i++) {
766 if (value_zero_p(D->Constraint[i][0])) {
767 fprintf(stderr, "Polyhedron_Preprocess: ");
768 fprintf(stderr,
769 "an equality was found where I did expect an inequality.\n");
770 fprintf(stderr, "Trying to continue...\n");
771 continue;
772 }
773 Vector_Copy(D->Constraint[i], M->p[M->NbRows], (d + 2));
774 for (j = 1; j <= d; j++)
775 if (value_neg_p(D->Constraint[i][j])) {
776 value_addmul(M->p[M->NbRows][d + 1], D->Constraint[i][j], size[j - 1]);
777 }
778
779 /* If anything changed, add this new constraint */
780 if (value_ne(M->p[M->NbRows][d + 1], D->Constraint[i][d + 1]))
781 M->NbRows++;
782 }
783
784#ifdef EDEBUG6
785 fprintf(stderr, "M used to find min : ");
786 Matrix_Print(stderr, P_VALUE_FMT, M);
787#endif
788
790 Matrix_Free(M);
791 if (!T || emptyQ(T)) {
792 if (T)
794 return (NULL);
795 }
796
797 /* Ok, now find the lexicographical min of T */
798 min = (Value *)malloc(sizeof(Value) * (d + 2));
799 for (i = 0; i <= d; i++) {
800 value_init(min[i]);
801 value_set_si(min[i], 0);
802 }
803 value_init(min[i]);
804 value_set_si(min[i], 1);
805 C = Universe_Polyhedron(0);
806 S = Polyhedron_Scan(T, C, MAXRAYS);
809
810#ifdef EDEBUG6
811 for (i = 0; i <= (d + 1); i++) {
812 value_print(stderr, P_VALUE_FMT, min[i]);
813 fprintf(stderr, " ,");
814 }
815 fprintf(stderr, "\n");
816 Polyhedron_Print(stderr, P_VALUE_FMT, S);
817 fprintf(stderr, "\n");
818#endif
819
820 if (!cherche_min(min, S, 1)) {
821 for (i = 0; i <= (d + 1); i++)
822 value_clear(min[i]);
823 return (NULL);
824 }
825 Domain_Free(S);
826
827#ifdef EDEBUG6
828 fprintf(stderr, "min = ( ");
829 value_print(stderr, P_VALUE_FMT, min[1]);
830 for (i = 2; i <= d; i++) {
831 fprintf(stderr, ", ");
832 value_print(stderr, P_VALUE_FMT, min[i]);
833 }
834 fprintf(stderr, ")\n");
835#endif
836
837 /* Min is the point from which we can construct the hypercube */
838 M = Matrix_Alloc(d * 2, d + 2);
839 for (i = 0; i < d; i++) {
840
841 /* Creates inequality 1 0..0 1 0..0 -min[i+1] */
842 value_set_si(M->p[2 * i][0], 1);
843 for (j = 1; j <= d; j++)
844 value_set_si(M->p[2 * i][j], 0);
845 value_set_si(M->p[2 * i][i + 1], 1);
846 value_oppose(M->p[2 * i][d + 1], min[i + 1]);
847
848 /* Creates inequality 1 0..0 -1 0..0 min[i+1]+size -1 */
849 value_set_si(M->p[2 * i + 1][0], 1);
850 for (j = 1; j <= d; j++)
851 value_set_si(M->p[2 * i + 1][j], 0);
852 value_set_si(M->p[2 * i + 1][i + 1], -1);
853 value_addto(M->p[2 * i + 1][d + 1], min[i + 1], size[i]);
854 value_sub_int(M->p[2 * i + 1][d + 1], M->p[2 * i + 1][d + 1], 1);
855 }
856
857#ifdef EDEBUG6
858 fprintf(stderr, "PolyhedronPreprocess: constraints H = ");
859 Matrix_Print(stderr, P_VALUE_FMT, M);
860#endif
861
863
864#ifdef EDEBUG6
865 Polyhedron_Print(stderr, P_VALUE_FMT, H);
866 fprintf(stderr, "\n");
867#endif
868
869 Matrix_Free(M);
870 for (i = 0; i <= (d + 1); i++)
871 value_clear(min[i]);
872 free(min);
873 assert(!emptyQ(H));
874 return (H);
875} /* Polyhedron_Preprocess */
876
877/** This procedure finds an hypercube of size 'size', containing
878polyhedron D increases size and lcm if necessary (and not "too big")
879If this is not possible, an empty polyhedron is returned
880
881<p>
882
883<pre> written by vin100, 2001, for version 4.19</pre>
884
885@param D
886@param size
887@param lcm
888@param MAXRAYS
889
890*/
891Polyhedron *Polyhedron_Preprocess2(Polyhedron *D, Value *size, Value *lcm,
892 unsigned MAXRAYS) {
893
894 Matrix *c;
895 Polyhedron *H;
896 int i, j, r;
897 Value n; /* smallest/biggest value */
898 Value s; /* size in this dimension */
899 Value tmp1, tmp2;
900
901#ifdef EDEBUG62
902 int np;
903#endif
904
905 value_init(n);
906 value_init(s);
907 value_init(tmp1);
908 value_init(tmp2);
909 c = Matrix_Alloc(D->Dimension * 2, D->Dimension + 2);
910
911#ifdef EDEBUG62
912 fprintf(stderr, "\nPreProcess2 : starting\n");
913 fprintf(stderr, "lcm = ");
914 for (np = 0; np < D->Dimension; np++)
915 value_print(stderr, VALUE_FMT, lcm[np]);
916 fprintf(stderr, ", size = ");
917 for (np = 0; np < D->Dimension; np++)
918 value_print(stderr, VALUE_FMT, size[np]);
919 fprintf(stderr, "\n");
920#endif
921
922 for (i = 0; i < D->Dimension; i++) {
923
924 /* Create constraint 1 0..0 1 0..0 -min */
925 value_set_si(c->p[2 * i][0], 1);
926 for (j = 0; j < D->Dimension; j++)
927 value_set_si(c->p[2 * i][1 + j], 0);
928 value_division(n, D->Ray[0][i + 1], D->Ray[0][D->Dimension + 1]);
929 for (r = 1; r < D->NbRays; r++) {
930 value_division(tmp1, D->Ray[r][i + 1], D->Ray[r][D->Dimension + 1]);
931 if (value_gt(n, tmp1)) {
932
933 /* New min */
934 value_division(n, D->Ray[r][i + 1], D->Ray[r][D->Dimension + 1]);
935 }
936 }
937 value_set_si(c->p[2 * i][i + 1], 1);
938 value_oppose(c->p[2 * i][D->Dimension + 1], n);
939
940 /* Create constraint 1 0..0 -1 0..0 max */
941 value_set_si(c->p[2 * i + 1][0], 1);
942 for (j = 0; j < D->Dimension; j++)
943 value_set_si(c->p[2 * i + 1][1 + j], 0);
944
945 /* n = (num+den-1)/den */
946 value_addto(tmp1, D->Ray[0][i + 1], D->Ray[0][D->Dimension + 1]);
947 value_sub_int(tmp1, tmp1, 1);
948 value_division(n, tmp1, D->Ray[0][D->Dimension + 1]);
949 for (r = 1; r < D->NbRays; r++) {
950 value_addto(tmp1, D->Ray[r][i + 1], D->Ray[r][D->Dimension + 1]);
951 value_sub_int(tmp1, tmp1, 1);
952 value_division(tmp1, tmp1, D->Ray[r][D->Dimension + 1]);
953 if (value_lt(n, tmp1)) {
954
955 /* New max */
956 value_addto(tmp1, D->Ray[r][i + 1], D->Ray[r][D->Dimension + 1]);
957 value_sub_int(tmp1, tmp1, 1);
958 value_division(n, tmp1, D->Ray[r][D->Dimension + 1]);
959 }
960 }
961 value_set_si(c->p[2 * i + 1][i + 1], -1);
962 value_assign(c->p[2 * i + 1][D->Dimension + 1], n);
963 value_addto(s, c->p[2 * i + 1][D->Dimension + 1],
964 c->p[2 * i][D->Dimension + 1]);
965
966 /* Now test if the dimension of the cube is greater than the size */
967 if (value_gt(s, size[i])) {
968
969#ifdef EDEBUG62
970 fprintf(stderr, "size on dimension %d\n", i);
971 fprintf(stderr, "lcm = ");
972 for (np = 0; np < D->Dimension; np++)
973 value_print(stderr, VALUE_FMT, lcm[np]);
974 fprintf(stderr, ", size = ");
975 for (np = 0; np < D->Dimension; np++)
976 value_print(stderr, VALUE_FMT, size[np]);
977 fprintf(stderr, "\n");
978 fprintf(stderr, "required size (s) = ");
979 value_print(stderr, VALUE_FMT, s);
980 fprintf(stderr, "\n");
981#endif
982
983 /* If the needed size is "small enough"(<=20 or less than
984 twice *size),
985 then increase *size, and artificially increase lcm too !*/
986 value_set_si(tmp1, 20);
987 value_addto(tmp2, size[i], size[i]);
988 if (value_le(s, tmp1) || value_le(s, tmp2)) {
989
990 if (value_zero_p(lcm[i]))
991 value_set_si(lcm[i], 1);
992 /* lcm divides size... */
993 value_division(tmp1, size[i], lcm[i]);
994
995 /* lcm = ceil(s/h) */
996 value_addto(tmp2, s, tmp1);
997 value_add_int(tmp2, tmp2, 1);
998 value_division(lcm[i], tmp2, tmp1);
999
1000 /* new size = lcm*h */
1001 value_multiply(size[i], lcm[i], tmp1);
1002
1003#ifdef EDEBUG62
1004 fprintf(stderr, "new size = ");
1005 for (np = 0; np < D->Dimension; np++)
1006 value_print(stderr, VALUE_FMT, size[np]);
1007 fprintf(stderr, ", new lcm = ");
1008 for (np = 0; np < D->Dimension; np++)
1009 value_print(stderr, VALUE_FMT, lcm[np]);
1010 fprintf(stderr, "\n");
1011#endif
1012
1013 } else {
1014
1015#ifdef EDEBUG62
1016 fprintf(stderr, "Failed on dimension %d.\n", i);
1017#endif
1018 break;
1019 }
1020 }
1021 }
1022 if (i != D->Dimension) {
1023 Matrix_Free(c);
1024 value_clear(n);
1025 value_clear(s);
1026 value_clear(tmp1);
1027 value_clear(tmp2);
1028 return (NULL);
1029 }
1030 for (i = 0; i < D->Dimension; i++) {
1031 value_subtract(c->p[2 * i + 1][D->Dimension + 1], size[i],
1032 c->p[2 * i][D->Dimension + 1]);
1033 }
1034
1035#ifdef EDEBUG62
1036 fprintf(stderr, "PreProcess2 : c =");
1037 Matrix_Print(stderr, P_VALUE_FMT, c);
1038#endif
1039
1041 Matrix_Free(c);
1042 value_clear(n);
1043 value_clear(s);
1044 value_clear(tmp1);
1045 value_clear(tmp2);
1046 return (H);
1047} /* Polyhedron_Preprocess2 */
1048
1049/**
1050
1051This procedure adds additional constraints to D so that as each
1052parameter is scanned, it will have a minimum of 'size' points If this
1053is not possible, an empty polyhedron is returned
1054
1055@param D
1056@param size
1057@param MAXRAYS
1058
1059*/
1061 unsigned MAXRAYS) {
1062
1063 int p, p1, ub, lb;
1064 Value a, a1, b, b1, g, aa;
1065 Value abs_a, abs_b, size_copy;
1066 int dim, con, newi, needed;
1067 Value **C;
1068 Matrix *M;
1069 Polyhedron *D1;
1070
1071 value_init(a);
1072 value_init(a1);
1073 value_init(b);
1074 value_init(b1);
1075 value_init(g);
1076 value_init(aa);
1077 value_init(abs_a);
1078 value_init(abs_b);
1079 value_init(size_copy);
1080
1081 dim = D->Dimension;
1082 con = D->NbConstraints;
1083 M = Matrix_Alloc(MAXRAYS, dim + 2);
1084 newi = 0;
1085 value_assign(size_copy, size);
1086 C = D->Constraint;
1087 for (p = 1; p <= dim; p++) {
1088 for (ub = 0; ub < con; ub++) {
1089 value_assign(a, C[ub][p]);
1090 if (value_posz_p(a)) /* a >= 0 */
1091 continue; /* not an upper bound */
1092 for (lb = 0; lb < con; lb++) {
1093 value_assign(b, C[lb][p]);
1094 if (value_negz_p(b))
1095 continue; /* not a lower bound */
1096
1097 /* Check if a new constraint is needed for this (ub,lb) pair */
1098 /* a constraint is only needed if a previously scanned */
1099 /* parameter (1..p-1) constrains this parameter (p) */
1100 needed = 0;
1101 for (p1 = 1; p1 < p; p1++) {
1102 if (value_notzero_p(C[ub][p1]) || value_notzero_p(C[lb][p1])) {
1103 needed = 1;
1104 break;
1105 }
1106 }
1107 if (!needed)
1108 continue;
1109 value_absolute(abs_a, a);
1110 value_absolute(abs_b, b);
1111
1112 /* Create new constraint: b*UB-a*LB >= a*b*size */
1113 value_gcd(g, abs_a, abs_b);
1114 value_divexact(a1, a, g);
1115 value_divexact(b1, b, g);
1116 value_set_si(M->p[newi][0], 1);
1117 value_oppose(abs_a, a1); /* abs_a = -a1 */
1118 Vector_Combine(&(C[ub][1]), &(C[lb][1]), &(M->p[newi][1]), b1, abs_a,
1119 dim + 1);
1120 value_multiply(aa, a1, b1);
1121 value_addmul(M->p[newi][dim + 1], aa, size_copy);
1122 Vector_Normalize(&(M->p[newi][1]), (dim + 1));
1123 newi++;
1124 }
1125 }
1126 }
1127 D1 = AddConstraints(M->p_Init, newi, D, MAXRAYS);
1128 Matrix_Free(M);
1129
1130 value_clear(a);
1131 value_clear(a1);
1132 value_clear(b);
1133 value_clear(b1);
1134 value_clear(g);
1135 value_clear(aa);
1136 value_clear(abs_a);
1137 value_clear(abs_b);
1138 value_clear(size_copy);
1139 return D1;
1140} /* old_Polyhedron_Preprocess */
1141
1142/**
1143
1144PROCEDURES TO COMPUTE ENUMERATION. recursive procedure, recurse for
1145each imbriquation
1146
1147@param pos index position of current loop index (1..hdim-1)
1148@param P loop domain
1149@param context context values for fixed indices
1150@param res the number of integer points in this
1151polyhedron
1152
1153*/
1154void count_points(int pos, Polyhedron *P, Value *context, Value *res) {
1155
1156 Value LB, UB, k, c;
1157
1160
1161 if (emptyQ(P)) {
1162 value_set_si(*res, 0);
1163 return;
1164 }
1165
1166 value_init(LB);
1167 value_init(UB);
1168 value_init(k);
1169 value_set_si(LB, 0);
1170 value_set_si(UB, 0);
1171
1172 if (lower_upper_bounds(pos, P, context, &LB, &UB) != 0) {
1173
1174 /* Problem if UB or LB is INFINITY */
1175 fprintf(stderr, "count_points: ? infinite domain\n");
1176 value_clear(LB);
1177 value_clear(UB);
1178 value_clear(k);
1179 value_set_si(*res, -1);
1180 return;
1181 }
1182
1183#ifdef EDEBUG1
1184 if (!P->next) {
1185 int i;
1186 for (value_assign(k, LB); value_le(k, UB); value_increment(k, k)) {
1187 fprintf(stderr, "(");
1188 for (i = 1; i < pos; i++) {
1189 value_print(stderr, P_VALUE_FMT, context[i]);
1190 fprintf(stderr, ",");
1191 }
1192 value_print(stderr, P_VALUE_FMT, k);
1193 fprintf(stderr, ")\n");
1194 }
1195 }
1196#endif
1197
1198 value_set_si(context[pos], 0);
1199 if (value_lt(UB, LB)) {
1200 value_clear(LB);
1201 value_clear(UB);
1202 value_clear(k);
1203 value_set_si(*res, 0);
1204 return;
1205 }
1206 if (!P->next) {
1207 value_subtract(k, UB, LB);
1208 value_add_int(k, k, 1);
1209 value_assign(*res, k);
1210 value_clear(LB);
1211 value_clear(UB);
1212 value_clear(k);
1213 return;
1214 }
1215
1216 /*-----------------------------------------------------------------*/
1217 /* Optimization idea */
1218 /* If inner loops are not a function of k (the current index) */
1219 /* i.e. if P->Constraint[i][pos]==0 for all P following this and */
1220 /* for all i, */
1221 /* Then CNT = (UB-LB+1)*count_points(pos+1, P->next, context) */
1222 /* (skip the for loop) */
1223 /*-----------------------------------------------------------------*/
1224
1225 value_init(c);
1226 value_set_si(*res, 0);
1227 for (value_assign(k, LB); value_le(k, UB); value_increment(k, k)) {
1228 /* Insert k in context */
1229 value_assign(context[pos], k);
1230 count_points(pos + 1, P->next, context, &c);
1231 if (value_notmone_p(c))
1232 value_addto(*res, *res, c);
1233 else {
1234 value_set_si(*res, -1);
1235 break;
1236 }
1237 }
1238 value_clear(c);
1239
1240#ifdef EDEBUG11
1241 fprintf(stderr, "%d\n", CNT);
1242#endif
1243
1244 /* Reset context */
1245 value_set_si(context[pos], 0);
1246 value_clear(LB);
1247 value_clear(UB);
1248 value_clear(k);
1249 return;
1250} /* count_points */
1251
1252/*-------------------------------------------------------------------*/
1253/* enode *P_Enum(L, LQ, context, pos, nb_param, dim, lcm,param_name) */
1254/* L : list of polyhedra for the loop nest */
1255/* LQ : list of polyhedra for the parameter loop nest */
1256/* pos : 1..nb_param, position of the parameter */
1257/* nb_param : number of parameters total */
1258/* dim : total dimension of the polyhedron, param incl. */
1259/* lcm : denominator array [0..dim-1] of the polyhedron */
1260/* param_name : name of the parameters */
1261/* Returns an enode tree representing the pseudo polynomial */
1262/* expression for the enumeration of the polyhedron. */
1263/* A recursive procedure. */
1264/*-------------------------------------------------------------------*/
1265static enode *P_Enum(Polyhedron *L, Polyhedron *LQ, Value *context, int pos,
1266 int nb_param, int dim, Value *lcm,
1267 const char **param_name) {
1268 enode *res, *B, *C;
1269 int hdim, i, j, rank, flag;
1270 Value n, g, nLB, nUB, nlcm, noff, nexp, k1, nm, hdv, k, lcm_copy;
1271 Value tmp;
1272 Matrix *A;
1273
1274#ifdef EDEBUG
1275 fprintf(stderr, "-------------------- begin P_Enum -------------------\n");
1276 fprintf(stderr, "Calling P_Enum with pos = %d\n", pos);
1277#endif
1278
1279 /* Initialize all the 'Value' variables */
1280 value_init(n);
1281 value_init(g);
1282 value_init(nLB);
1283 value_init(nUB);
1284 value_init(nlcm);
1285 value_init(noff);
1286 value_init(nexp);
1287 value_init(k1);
1288 value_init(nm);
1289 value_init(hdv);
1290 value_init(k);
1291 value_init(tmp);
1292 value_init(lcm_copy);
1293
1294 if (value_zero_p(lcm[pos - 1])) {
1295 hdim = 1;
1296 value_set_si(lcm_copy, 1);
1297 } else {
1298 /* hdim is the degree of the polynomial + 1 */
1299 hdim = dim - nb_param + 1; /* homogenous dim w/o parameters */
1300 value_assign(lcm_copy, lcm[pos - 1]);
1301 }
1302
1303 /* code to limit generation of equations to valid parameters only */
1304 /*----------------------------------------------------------------*/
1305 flag = lower_upper_bounds(pos, LQ, &context[dim - nb_param], &nLB, &nUB);
1306 if (flag & LB_INFINITY) {
1307 if (!(flag & UB_INFINITY)) {
1308
1309 /* Only an upper limit: set lower limit */
1310 /* Compute nLB such that (nUB-nLB+1) >= (hdim*lcm) */
1311 value_sub_int(nLB, nUB, 1);
1312 value_set_si(hdv, hdim);
1313 value_multiply(tmp, hdv, lcm_copy);
1314 value_subtract(nLB, nLB, tmp);
1315 if (value_pos_p(nLB))
1316 value_set_si(nLB, 0);
1317 } else {
1318 value_set_si(nLB, 0);
1319
1320 /* No upper nor lower limit: set lower limit to 0 */
1321 value_set_si(hdv, hdim);
1322 value_multiply(nUB, hdv, lcm_copy);
1323 value_add_int(nUB, nUB, 1);
1324 }
1325 }
1326
1327 /* if (nUB-nLB+1) < (hdim*lcm) then we have more unknowns than equations */
1328 /* We can: 1. Find more equations by changing the context parameters, or */
1329 /* 2. Assign extra unknowns values in such a way as to simplify result. */
1330 /* Think about ways to scan parameter space to get as much info out of it*/
1331 /* as possible. */
1332
1333#ifdef REDUCE_DEGREE
1334 if (pos == 1 && (flag & UB_INFINITY) == 0) {
1335 /* only for finite upper bound on first parameter */
1336 /* NOTE: only first parameter because subsequent parameters may
1337 be artificially limited by the choice of the first parameter */
1338
1339#ifdef EDEBUG
1340 fprintf(stderr, "*************** n **********\n");
1341 value_print(stderr, VALUE_FMT, n);
1342 fprintf(stderr, "\n");
1343#endif
1344
1345 value_subtract(n, nUB, nLB);
1347
1348#ifdef EDEBUG
1349 value_print(stderr, VALUE_FMT, n);
1350 fprintf(stderr, "\n*************** n ************\n");
1351#endif
1352
1353 /* Total number of samples>0 */
1354 if (value_neg_p(n))
1355 i = 0;
1356 else {
1357 value_modulus(tmp, n, lcm_copy);
1358 if (value_notzero_p(tmp)) {
1359 value_division(tmp, n, lcm_copy);
1360 value_increment(tmp, tmp);
1361 i = VALUE_TO_INT(tmp);
1362 } else {
1363 value_division(tmp, n, lcm_copy);
1364 i = VALUE_TO_INT(tmp); /* ceiling of n/lcm */
1365 }
1366 }
1367
1368#ifdef EDEBUG
1369 value_print(stderr, VALUE_FMT, n);
1370 fprintf(stderr, "\n*************** n ************\n");
1371#endif
1372
1373 /* Reduce degree of polynomial based on number of sample points */
1374 if (i < hdim) {
1375 hdim = i;
1376
1377#ifdef EDEBUG4
1378 fprintf(stdout, "Parameter #%d: LB=", pos);
1379 value_print(stdout, VALUE_FMT, nLB);
1380 fprintf(stdout, " UB=");
1381 value_print(stdout, VALUE_FMT, nUB);
1382 fprintf(stdout, " lcm=");
1383 value_print(stdout, VALUE_FMT, lcm_copy);
1384 fprintf(stdout, " degree reduced to %d\n", hdim - 1);
1385#endif
1386 }
1387 }
1388#endif /* REDUCE_DEGREE */
1389
1390 /* hdim is now set */
1391 /* allocate result structure */
1392 res = new_enode(polynomial, hdim, pos);
1393 for (i = 0; i < hdim; i++) {
1394 int l;
1395 l = VALUE_TO_INT(lcm_copy);
1396 res->arr[i].x.p = new_enode(periodic, l, pos);
1397 }
1398
1399 /* Utility arrays */
1400 A = Matrix_Alloc(hdim, 2 * hdim + 1); /* used for Gauss */
1401 B = new_enode(evector, hdim, 0);
1402 C = new_enode(evector, hdim, 0);
1403
1404 /* We'll create these again when we need them */
1405 for (j = 0; j < hdim; ++j)
1406 free_evalue_refs(&C->arr[j]);
1407
1408 /*----------------------------------------------------------------*/
1409 /* */
1410 /* 0<-----+---k---------> */
1411 /* |---------noff----------------->-nlcm->-------lcm----> */
1412 /* |--- . . . -----|--------------|------+-------|------+-------|-*/
1413 /* 0 (q-1)*lcm q*lcm | (q+1)*lcm | */
1414 /* nLB nLB+lcm */
1415 /* */
1416 /*----------------------------------------------------------------*/
1417 if (value_neg_p(nLB)) {
1418 value_modulus(nlcm, nLB, lcm_copy);
1419 value_addto(nlcm, nlcm, lcm_copy);
1420 } else {
1421 value_modulus(nlcm, nLB, lcm_copy);
1422 }
1423
1424 /* noff is a multiple of lcm */
1425 value_subtract(noff, nLB, nlcm);
1426 value_addto(tmp, lcm_copy, nlcm);
1427 for (value_assign(k, nlcm); value_lt(k, tmp);) {
1428
1429#ifdef EDEBUG
1430 fprintf(stderr, "Finding ");
1431 value_print(stderr, VALUE_FMT, k);
1432 fprintf(stderr, "-th elements of periodic coefficients\n");
1433#endif
1434
1435 value_set_si(hdv, hdim);
1436 value_multiply(nm, hdv, lcm_copy);
1437 value_addto(nm, nm, nLB);
1438 i = 0;
1439 for (value_addto(n, k, noff); value_lt(n, nm);
1440 value_addto(n, n, lcm_copy), i++) {
1441
1442 /* n == i*lcm + k + noff; */
1443 /* nlcm <= k < nlcm+lcm */
1444 /* n mod lcm == k1 */
1445
1446#ifdef ALL_OVERFLOW_WARNINGS
1447 if (((flag & UB_INFINITY) == 0) && value_gt(n, nUB)) {
1448 fprintf(stdout, "Domain Overflow: Parameter #%d:", pos);
1449 fprintf(stdout, "nLB=");
1450 value_print(stdout, VALUE_FMT, nLB);
1451 fprintf(stdout, " n=");
1452 value_print(stdout, VALUE_FMT, n);
1453 fprintf(stdout, " nUB=");
1454 value_print(stdout, VALUE_FMT, nUB);
1455 fprintf(stdout, "\n");
1456 }
1457#else
1458 if (overflow_warning_flag && ((flag & UB_INFINITY) == 0) &&
1459 value_gt(n, nUB)) {
1460 fprintf(stdout, "\nWARNING: Parameter Domain Overflow.");
1461 fprintf(stdout, " Result may be incorrect on this domain.\n");
1463 }
1464#endif
1465
1466 /* Set parameter to n */
1467 value_assign(context[dim - nb_param + pos], n);
1468
1469#ifdef EDEBUG1
1470 if (param_name) {
1471 fprintf(stderr, "%s = ", param_name[pos - 1]);
1472 value_print(stderr, VALUE_FMT, n);
1473 fprintf(stderr, " (hdim=%d, lcm[%d]=", hdim, pos - 1);
1474 value_print(stderr, VALUE_FMT, lcm_copy);
1475 fprintf(stderr, ")\n");
1476 } else {
1477 fprintf(stderr, "P%d = ", pos);
1478 value_print(stderr, VALUE_FMT, n);
1479 fprintf(stderr, " (hdim=%d, lcm[%d]=", hdim, pos - 1);
1480 value_print(stderr, VALUE_FMT, lcm_copy);
1481 fprintf(stderr, ")\n");
1482 }
1483#endif
1484
1485 /* Setup B vector */
1486 if (pos == nb_param) {
1487
1488#ifdef EDEBUG
1489 fprintf(stderr, "Yes\n");
1490#endif
1491
1492 /* call count */
1493 /* count can only be called when the context is fully specified */
1494 value_set_si(B->arr[i].d, 1);
1495 value_init(B->arr[i].x.n);
1496 count_points(1, L, context, &B->arr[i].x.n);
1497
1498#ifdef EDEBUG3
1499 for (j = 1; j < pos; j++)
1500 fputs(" ", stdout);
1501 fprintf(stdout, "E(");
1502 for (j = 1; j < nb_param; j++) {
1503 value_print(stdout, VALUE_FMT, context[dim - nb_param + j]);
1504 fprintf(stdout, ",");
1505 }
1506 value_print(stdout, VALUE_FMT, n);
1507 fprintf(stdout, ") = ");
1508 value_print(stdout, VALUE_FMT, B->arr[i].x.n);
1509 fprintf(stdout, " =");
1510#endif
1511
1512 } else { /* count is a function of other parameters */
1513 /* call P_Enum recursively */
1514 value_set_si(B->arr[i].d, 0);
1515 B->arr[i].x.p = P_Enum(L, LQ->next, context, pos + 1, nb_param, dim,
1516 lcm, param_name);
1517
1518#ifdef EDEBUG3
1519 if (param_name) {
1520 for (j = 1; j < pos; j++)
1521 fputs(" ", stdout);
1522 fprintf(stdout, "E(");
1523 for (j = 1; j <= pos; j++) {
1524 value_print(stdout, VALUE_FMT, context[dim - nb_param + j]);
1525 fprintf(stdout, ",");
1526 }
1527 for (j = pos + 1; j < nb_param; j++)
1528 fprintf(stdout, "%s,", param_name[j]);
1529 fprintf(stdout, "%s) = ", param_name[j]);
1530 print_enode(stdout, B->arr[i].x.p, param_name);
1531 fprintf(stdout, " =");
1532 }
1533#endif
1534 }
1535
1536 /* Create i-th equation*/
1537 /* K_0 + K_1 * n**1 + ... + K_dim * n**dim | Identity Matrix */
1538
1539 value_set_si(A->p[i][0], 0); /* status bit = equality */
1540 value_set_si(nexp, 1);
1541 for (j = 1; j <= hdim; j++) {
1542 value_assign(A->p[i][j], nexp);
1543 value_set_si(A->p[i][j + hdim], 0);
1544
1545#ifdef EDEBUG3
1546 fprintf(stdout, " + ");
1547 value_print(stdout, VALUE_FMT, nexp);
1548 fprintf(stdout, " c%d", j);
1549#endif
1550 value_multiply(nexp, nexp, n);
1551 }
1552
1553#ifdef EDEBUG3
1554 fprintf(stdout, "\n");
1555#endif
1556
1557 value_set_si(A->p[i][i + 1 + hdim], 1);
1558 }
1559
1560 /* Assertion check */
1561 if (i != hdim)
1562 fprintf(stderr, "P_Enum: ?expecting i==hdim\n");
1563
1564#ifdef EDEBUG
1565 if (param_name) {
1566 fprintf(stderr, "B (enode) =\n");
1567 print_enode(stderr, B, param_name);
1568 }
1569 fprintf(stderr, "A (Before Gauss) =\n");
1570 Matrix_Print(stderr, P_VALUE_FMT, A);
1571#endif
1572
1573 /* Solve hdim (=dim+1) equations with hdim unknowns, result in CNT */
1574 rank = Gauss(A, hdim, 2 * hdim);
1575
1576#ifdef EDEBUG
1577 fprintf(stderr, "A (After Gauss) =\n");
1578 Matrix_Print(stderr, P_VALUE_FMT, A);
1579#endif
1580
1581 /* Assertion check */
1582 if (rank != hdim) {
1583 fprintf(stderr, "P_Enum: ?expecting rank==hdim\n");
1584 }
1585
1586 /* if (rank < hdim) then set the last hdim-rank coefficients to ? */
1587 /* if (rank == 0) then set all coefficients to 0 */
1588 /* copy result as k1-th element of periodic numbers */
1589 if (value_lt(k, lcm_copy))
1590 value_assign(k1, k);
1591 else
1592 value_subtract(k1, k, lcm_copy);
1593
1594 for (i = 0; i < rank; i++) {
1595
1596 /* Set up coefficient vector C from i-th row of inverted matrix */
1597 for (j = 0; j < rank; j++) {
1598 value_gcd(g, A->p[i][i + 1], A->p[i][j + 1 + hdim]);
1599 value_init(C->arr[j].d);
1600 value_divexact(C->arr[j].d, A->p[i][i + 1], g);
1601 value_init(C->arr[j].x.n);
1602 value_divexact(C->arr[j].x.n, A->p[i][j + 1 + hdim], g);
1603 }
1604
1605#ifdef EDEBUG
1606 if (param_name) {
1607 fprintf(stderr, "C (enode) =\n");
1608 print_enode(stderr, C, param_name);
1609 }
1610#endif
1611
1612 /* The i-th enode is the lcm-periodic coefficient of term n**i */
1613 edot(B, C, &(res->arr[i].x.p->arr[VALUE_TO_INT(k1)]));
1614
1615#ifdef EDEBUG
1616 if (param_name) {
1617 fprintf(stderr, "B.C (evalue)=\n");
1618 print_evalue(stderr, &(res->arr[i].x.p->arr[VALUE_TO_INT(k1)]),
1619 param_name);
1620 fprintf(stderr, "\n");
1621 }
1622#endif
1623
1624 for (j = 0; j < rank; ++j)
1625 free_evalue_refs(&C->arr[j]);
1626 }
1627 value_addto(tmp, lcm_copy, nlcm);
1628
1629 value_increment(k, k);
1630 for (i = 0; i < hdim; ++i) {
1631 free_evalue_refs(&B->arr[i]);
1632 if (value_lt(k, tmp))
1633 value_init(B->arr[i].d);
1634 }
1635 }
1636
1637#ifdef EDEBUG
1638 if (param_name) {
1639 fprintf(stderr, "res (enode) =\n");
1640 print_enode(stderr, res, param_name);
1641 }
1642 fprintf(stderr, "-------------------- end P_Enum -----------------------\n");
1643#endif
1644
1645 /* Reset context */
1646 value_set_si(context[dim - nb_param + pos], 0);
1647
1648 /* Release memory */
1649 Matrix_Free(A);
1650 free(B);
1651 free(C);
1652
1653 /* Clear all the 'Value' variables */
1654 value_clear(n);
1655 value_clear(g);
1656 value_clear(nLB);
1657 value_clear(nUB);
1658 value_clear(nlcm);
1659 value_clear(noff);
1660 value_clear(nexp);
1661 value_clear(k1);
1662 value_clear(nm);
1663 value_clear(hdv);
1664 value_clear(k);
1665 value_clear(tmp);
1666 value_clear(lcm_copy);
1667 return res;
1668} /* P_Enum */
1669
1670/*----------------------------------------------------------------*/
1671/* Scan_Vertices(PP, Q, CT) */
1672/* PP : ParamPolyhedron */
1673/* Q : Domain */
1674/* CT : Context transformation matrix */
1675/* lcm : lcm array (output) */
1676/* nbp : number of parameters */
1677/* param_name : name of the parameters */
1678/*----------------------------------------------------------------*/
1680 Value *lcm, int nbp, const char **param_name) {
1681 Param_Vertices *V;
1682 int i, j, ix, l, np;
1683 unsigned bx;
1684 Value k, m1;
1685
1686 /* Compute the denominator of P */
1687 /* lcm = Least Common Multiple of the denominators of the vertices of P */
1688 /* and print the vertices */
1689
1690 value_init(k);
1691 value_init(m1);
1692 for (np = 0; np < nbp; np++)
1693 value_set_si(lcm[np], 0);
1694
1695 if (param_name)
1696 fprintf(stdout, "Vertices:\n");
1697
1698 for (i = 0, ix = 0, bx = MSB, V = PP->V; V && i < PP->nbV; i++, V = V->next) {
1699 if (Q->F[ix] & bx) {
1700 if (param_name) {
1701 if (CT) {
1702 Matrix *v;
1703 v = VertexCT(V->Vertex, CT);
1704 Print_Vertex(stdout, v, param_name);
1705 Matrix_Free(v);
1706 } else
1707 Print_Vertex(stdout, V->Vertex, param_name);
1708 fprintf(stdout, "\n");
1709 }
1710
1711 for (j = 0; j < V->Vertex->NbRows; j++) {
1712 /* A matrix */
1713 for (l = 0; l < V->Vertex->NbColumns - 1; l++) {
1714 if (value_notzero_p(V->Vertex->p[j][l])) {
1715 value_gcd(m1, V->Vertex->p[j][V->Vertex->NbColumns - 1],
1716 V->Vertex->p[j][l]);
1717 value_divexact(k, V->Vertex->p[j][V->Vertex->NbColumns - 1], m1);
1718 if (value_notzero_p(lcm[l])) {
1719 /* lcm[l] = lcm[l] * k / gcd(k,lcm[l]) */
1720 if (value_notzero_p(k) && value_notone_p(k)) {
1721 value_gcd(m1, lcm[l], k);
1722 value_divexact(k, k, m1);
1723 value_multiply(lcm[l], lcm[l], k);
1724 }
1725 } else {
1726 value_assign(lcm[l], k);
1727 }
1728 }
1729 }
1730 }
1731 }
1732 NEXT(ix, bx);
1733 }
1734 value_clear(k);
1735 value_clear(m1);
1736} /* Scan_Vertices */
1737
1738/**
1739
1740Procedure to count points in a non-parameterized polytope.
1741
1742@param P Polyhedron to count
1743@param C Parameter Context domain
1744@param CT Matrix to transform context to original
1745@param CEq additionnal equalities in context
1746@param MAXRAYS workspace size
1747@param param_name parameter names
1748
1749*/
1751 Polyhedron *CEq, unsigned MAXRAYS,
1752 const char **param_name) {
1753 Polyhedron *L;
1754 Enumeration *res;
1755 Value *context;
1756 int j;
1757 int hdim = P->Dimension + 1;
1758 int r, i;
1759
1760 /* Create a context vector size dim+2 */
1761 context = (Value *)malloc((hdim + 1) * sizeof(Value));
1762 for (j = 0; j <= hdim; j++)
1763 value_init(context[j]);
1764
1765 res = (Enumeration *)malloc(sizeof(Enumeration));
1766 res->next = NULL;
1767 res->ValidityDomain = Universe_Polyhedron(0); /* no parameters */
1768 value_init(res->EP.d);
1769 value_set_si(res->EP.d, 0);
1771
1772#ifdef EDEBUG2
1773 fprintf(stderr, "L = \n");
1774 Polyhedron_Print(stderr, P_VALUE_FMT, L);
1775#endif
1776
1777 if (CT) {
1778 Polyhedron *Dt;
1779
1780 /* Add parameters to validity domain */
1783 res->ValidityDomain = DomainIntersection(Dt, CEq, MAXRAYS);
1784 Polyhedron_Free(Dt);
1785 }
1786
1787 if (param_name) {
1788 fprintf(stdout, "---------------------------------------\n");
1789 fprintf(stdout, "Domain:\n");
1790 Print_Domain(stdout, res->ValidityDomain, param_name);
1791
1792 /* Print the vertices */
1793 printf("Vertices:\n");
1794 for (r = 0; r < P->NbRays; ++r) {
1795 if (value_zero_p(P->Ray[r][0]))
1796 printf("(line) ");
1797 printf("[");
1798 if (P->Dimension > 0)
1799 value_print(stdout, P_VALUE_FMT, P->Ray[r][1]);
1800 for (i = 1; i < P->Dimension; i++) {
1801 printf(", ");
1802 value_print(stdout, P_VALUE_FMT, P->Ray[r][i + 1]);
1803 }
1804 printf("]");
1805 if (value_notone_p(P->Ray[r][P->Dimension + 1])) {
1806 printf("/");
1807 value_print(stdout, P_VALUE_FMT, P->Ray[r][P->Dimension + 1]);
1808 }
1809 printf("\n");
1810 }
1811 }
1812
1813 res->EP.x.p = new_enode(polynomial, 1, 0);
1814 ;
1815 value_set_si(res->EP.x.p->arr[0].d, 1);
1816 value_init(res->EP.x.p->arr[0].x.n);
1817
1818 if (emptyQ(P)) {
1819 value_set_si(res->EP.x.p->arr[0].x.n, 0);
1820 } else if (!L) {
1821 /* Non-empty zero-dimensional domain */
1822 value_set_si(res->EP.x.p->arr[0].x.n, 1);
1823 } else {
1825 fprintf(stderr, "Enumerate: arithmetic overflow error.\n");
1826 fprintf(stderr, "You should rebuild PolyLib using GNU-MP"
1827 " or increasing the size of integers.\n");
1830 }
1831 TRY {
1832
1833 Vector_Set(context, 0, (hdim + 1));
1834
1835 /* Set context[hdim] = 1 (the constant) */
1836 value_set_si(context[hdim], 1);
1837 count_points(1, L, context, &res->EP.x.p->arr[0].x.n);
1839 }
1840 }
1841
1842 Domain_Free(L);
1843
1844 /* **USELESS, there are no references to parameters in res**
1845 if( CT )
1846 addeliminatedparams_evalue(&res->EP, CT);
1847 */
1848
1849 if (param_name) {
1850 fprintf(stdout, "\nEhrhart Polynomial:\n");
1851 print_evalue(stdout, &res->EP, param_name);
1852 fprintf(stdout, "\n");
1853 }
1854
1855 for (j = 0; j <= hdim; j++)
1856 value_clear(context[j]);
1857 free(context);
1858 return (res);
1859} /* Enumerate_NoParameters */
1860
1861/** Procedure to count points in a parameterized polytope.
1862
1863@param Pi Polyhedron to enumerate
1864@param C Context Domain
1865@param MAXRAYS size of workspace
1866@param param_name parameter names (array of strings), may be NULL
1867@return a list of validity domains + evalues EP
1868
1869*/
1871 unsigned MAXRAYS, const char **param_name) {
1872 Polyhedron *L, *CQ, *CQ2, *LQ, *U, *CEq, *rVD, *P, *Ph = NULL;
1873 Matrix *CT;
1874 Param_Polyhedron *PP;
1875 Param_Domain *Q;
1876 int i, hdim, dim, nb_param, np;
1877 Value *lcm, *m1, hdv;
1878 Value *context;
1879 Enumeration *en, *res;
1880
1882 MAXRAYS = 0;
1883
1888
1889 res = NULL;
1890 P = Pi;
1891
1892#ifdef EDEBUG2
1893 fprintf(stderr, "C = \n");
1894 Polyhedron_Print(stderr, P_VALUE_FMT, C);
1895 fprintf(stderr, "P = \n");
1896 Polyhedron_Print(stderr, P_VALUE_FMT, P);
1897#endif
1898
1899 hdim = P->Dimension + 1;
1900 dim = P->Dimension;
1901 nb_param = C->Dimension;
1902
1903 /* Don't call Polyhedron2Param_Domain if there are no parameters */
1904 if (nb_param == 0) {
1905
1906 return (Enumerate_NoParameters(P, C, NULL, NULL, MAXRAYS, param_name));
1907 }
1908 if (nb_param == dim) {
1909 res = (Enumeration *)malloc(sizeof(Enumeration));
1910 res->next = 0;
1912 value_init(res->EP.d);
1913 value_init(res->EP.x.n);
1914 value_set_si(res->EP.d, 1);
1915 value_set_si(res->EP.x.n, 1);
1916 if (param_name) {
1917 fprintf(stdout, "---------------------------------------\n");
1918 fprintf(stdout, "Domain:\n");
1919 Print_Domain(stdout, res->ValidityDomain, param_name);
1920 fprintf(stdout, "\nEhrhart Polynomial:\n");
1921 print_evalue(stdout, &res->EP, param_name);
1922 fprintf(stdout, "\n");
1923 }
1924 return res;
1925 }
1926 PP = Polyhedron2Param_SimplifiedDomain(&P, C, MAXRAYS, &CEq, &CT);
1927 if (!PP) {
1928 if (param_name)
1929 fprintf(stdout, "\nEhrhart Polynomial:\nNULL\n");
1930
1931 return (NULL);
1932 }
1933
1934 /* CT : transformation matrix to eliminate useless ("false") parameters */
1935 if (CT) {
1936 nb_param -= CT->NbColumns - CT->NbRows;
1937 dim -= CT->NbColumns - CT->NbRows;
1938 hdim -= CT->NbColumns - CT->NbRows;
1939
1940 /* Don't call Polyhedron2Param_Domain if there are no parameters */
1941 if (nb_param == 0) {
1942 res = Enumerate_NoParameters(P, C, CT, CEq, MAXRAYS, param_name);
1944 goto out;
1945 }
1946 }
1947
1948 /* get memory for Values */
1949 lcm = (Value *)malloc((nb_param + 1) * sizeof(Value));
1950 m1 = (Value *)malloc((nb_param + 1) * sizeof(Value));
1951 /* Initialize all the 'Value' variables */
1952 for (np = 0; np < nb_param + 1; np++) {
1953 value_init(lcm[np]);
1954 value_init(m1[np]);
1955 }
1956 value_init(hdv);
1957
1958 for (Q = PP->D; Q; Q = Q->next) {
1959 int hom = 0;
1960 if (CT) {
1961 Polyhedron *Dt;
1962 CQ = Q->Domain;
1963 Dt = Polyhedron_Preimage(Q->Domain, CT, MAXRAYS);
1964 rVD = DomainIntersection(Dt, CEq, MAXRAYS);
1965
1966 /* if rVD is empty or too small in geometric dimension */
1967 if (!rVD || emptyQ(rVD) ||
1968 (rVD->Dimension - rVD->NbEq < Dt->Dimension - Dt->NbEq - CEq->NbEq)) {
1969 if (rVD)
1970 Polyhedron_Free(rVD);
1971 Polyhedron_Free(Dt);
1972 Polyhedron_Free(CQ);
1973 continue; /* empty validity domain */
1974 }
1975 Polyhedron_Free(Dt);
1976 } else
1977 rVD = CQ = Q->Domain;
1978 en = (Enumeration *)malloc(sizeof(Enumeration));
1979 en->next = res;
1980 res = en;
1981 res->ValidityDomain = rVD;
1982
1983 if (param_name) {
1984 fprintf(stdout, "---------------------------------------\n");
1985 fprintf(stdout, "Domain:\n");
1986
1987#ifdef EPRINT_ALL_VALIDITY_CONSTRAINTS
1988 Print_Domain(stdout, res->ValidityDomain, param_name);
1989#else
1990 {
1991 Polyhedron *VD;
1992 VD = DomainSimplify(res->ValidityDomain, C, MAXRAYS);
1993 Print_Domain(stdout, VD, param_name);
1994 Domain_Free(VD);
1995 }
1996#endif /* EPRINT_ALL_VALIDITY_CONSTRAINTS */
1997 }
1998
2000
2001 /* Scan the vertices and compute lcm */
2002 Scan_Vertices(PP, Q, CT, lcm, nb_param, param_name);
2003
2004#ifdef EDEBUG2
2005 fprintf(stderr, "Denominator = ");
2006 for (np = 0; np < nb_param; np++)
2007 value_print(stderr, P_VALUE_FMT, lcm[np]);
2008 fprintf(stderr, " and hdim == %d \n", hdim);
2009#endif
2010
2011#ifdef EDEBUG2
2012 fprintf(stderr, "CQ = \n");
2013 Polyhedron_Print(stderr, P_VALUE_FMT, CQ);
2014#endif
2015
2016 /* Before scanning, add constraints to ensure at least hdim*lcm */
2017 /* points in every dimension */
2018 value_set_si(hdv, hdim - nb_param);
2019
2020 for (np = 0; np < nb_param + 1; np++) {
2021 if (value_notzero_p(lcm[np]))
2022 value_multiply(m1[np], hdv, lcm[np]);
2023 else
2024 value_set_si(m1[np], 1);
2025 }
2026
2027#ifdef EDEBUG2
2028 fprintf(stderr, "m1 == ");
2029 for (np = 0; np < nb_param; np++)
2030 value_print(stderr, P_VALUE_FMT, m1[np]);
2031 fprintf(stderr, "\n");
2032#endif
2033
2035 fprintf(stderr, "Enumerate: arithmetic overflow error.\n");
2036 CQ2 = NULL;
2037 }
2038 TRY {
2039 CQ2 = Polyhedron_Preprocess(CQ, m1, MAXRAYS);
2040
2041#ifdef EDEBUG2
2042 fprintf(stderr, "After preprocess, CQ2 = ");
2043 Polyhedron_Print(stderr, P_VALUE_FMT, CQ2);
2044#endif
2045
2047 }
2048
2049 /* Vin100, Feb 2001 */
2050 /* in case of degenerate, try to find a domain _containing_ CQ */
2051 if ((!CQ2 || emptyQ(CQ2)) && CQ->NbBid == 0) {
2052 int r;
2053
2054#ifdef EDEBUG2
2055 fprintf(stderr, "Trying to call Polyhedron_Preprocess2 : CQ = \n");
2056 Polyhedron_Print(stderr, P_VALUE_FMT, CQ);
2057#endif
2058
2059 /* Check if CQ is bounded */
2060 for (r = 0; r < CQ->NbRays; r++) {
2061 if (value_zero_p(CQ->Ray[r][0]) ||
2062 value_zero_p(CQ->Ray[r][CQ->Dimension + 1]))
2063 break;
2064 }
2065 if (r == CQ->NbRays) {
2066
2067 /* ok, CQ is bounded */
2068 /* now find if CQ is contained in a hypercube of size m1 */
2069 CQ2 = Polyhedron_Preprocess2(CQ, m1, lcm, MAXRAYS);
2070 }
2071 }
2072
2073 if (!CQ2) {
2074 Polyhedron *tmp;
2075#ifdef EDEBUG2
2076 fprintf(stderr, "Homogenize.\n");
2077#endif
2078 hom = 1;
2079 tmp = homogenize(CQ, MAXRAYS);
2080 CQ2 = Polyhedron_Preprocess(tmp, m1, MAXRAYS);
2081 Polyhedron_Free(tmp);
2082 if (!Ph)
2083 Ph = homogenize(P, MAXRAYS);
2084 for (np = 0; np < nb_param + 1; np++)
2085 if (value_notzero_p(lcm[np]))
2086 value_addto(m1[np], m1[np], lcm[np]);
2087 }
2088
2089 if (!CQ2 || emptyQ(CQ2)) {
2090#ifdef EDEBUG2
2091 fprintf(stderr, "Degenerate.\n");
2092#endif
2093 fprintf(stdout, "Degenerate Domain. Can not continue.\n");
2094 value_init(res->EP.d);
2095 value_init(res->EP.x.n);
2096 value_set_si(res->EP.d, 1);
2097 value_set_si(res->EP.x.n, -1);
2098 } else {
2099
2100#ifdef EDEBUG2
2101 fprintf(stderr, "CQ2 = \n");
2102 Polyhedron_Print(stderr, P_VALUE_FMT, CQ2);
2103 if (!PolyhedronIncludes(CQ, CQ2))
2104 fprintf(stderr, "CQ does not include CQ2 !\n");
2105 else
2106 fprintf(stderr, "CQ includes CQ2.\n");
2107 if (!PolyhedronIncludes(res->ValidityDomain, CQ2))
2108 fprintf(stderr, "CQ2 is *not* included in validity domain !\n");
2109 else
2110 fprintf(stderr, "CQ2 is included in validity domain.\n");
2111#endif
2112
2113 /* L is used in counting the number of points in the base cases */
2114 L = Polyhedron_Scan(hom ? Ph : P, CQ2, MAXRAYS);
2115 U = Universe_Polyhedron(0);
2116
2117 /* LQ is used to scan the parameter space */
2118 LQ = Polyhedron_Scan(CQ2, U, MAXRAYS); /* bounds on parameters */
2119 Domain_Free(U);
2120 if (CT) /* we did compute another Q->Domain */
2121 Domain_Free(CQ);
2122
2123 /* Else, CQ was Q->Domain (used in res) */
2124 Domain_Free(CQ2);
2125
2126#ifdef EDEBUG2
2127 fprintf(stderr, "L = \n");
2128 Polyhedron_Print(stderr, P_VALUE_FMT, L);
2129 fprintf(stderr, "LQ = \n");
2130 Polyhedron_Print(stderr, P_VALUE_FMT, LQ);
2131#endif
2132#ifdef EDEBUG3
2133 fprintf(stdout, "\nSystem of Equations:\n");
2134#endif
2135
2136 value_init(res->EP.d);
2137 value_set_si(res->EP.d, 0);
2138
2139 /* Create a context vector size dim+2 */
2140 context = (Value *)malloc((hdim + 1 + hom) * sizeof(Value));
2141 for (i = 0; i <= (hdim + hom); i++)
2142 value_init(context[i]);
2143 Vector_Set(context, 0, (hdim + 1 + hom));
2144
2145 /* Set context[hdim] = 1 (the constant) */
2146 value_set_si(context[hdim + hom], 1);
2147
2149 fprintf(stderr, "Enumerate: arithmetic overflow error.\n");
2150 fprintf(stderr, "You should rebuild PolyLib using GNU-MP "
2151 "or increasing the size of integers.\n");
2154 }
2155 TRY {
2156 res->EP.x.p = P_Enum(L, LQ, context, 1, nb_param + hom, dim + hom, lcm,
2157 param_name);
2159 }
2160 if (hom)
2161 dehomogenize_evalue(&res->EP, nb_param + 1);
2162
2163 for (i = 0; i <= (hdim + hom); i++)
2164 value_clear(context[i]);
2165 free(context);
2166 Domain_Free(L);
2167 Domain_Free(LQ);
2168
2169#ifdef EDEBUG5
2170 if (param_name) {
2171 fprintf(stdout, "\nEhrhart Polynomial (before simplification):\n");
2172 print_evalue(stdout, &res->EP, param_name);
2173 }
2174#endif
2175
2176 /* Try to simplify the result */
2177 reduce_evalue(&res->EP);
2178
2179 /* Put back the original parameters into result */
2180 /* (equalities have been eliminated) */
2181 if (CT)
2182 addeliminatedparams_evalue(&res->EP, CT);
2183
2184 if (param_name) {
2185 fprintf(stdout, "\nEhrhart Polynomial:\n");
2186 print_evalue(stdout, &res->EP, param_name);
2187 fprintf(stdout, "\n");
2188 /* sometimes the final \n lacks (when a single constant is printed) */
2189 }
2190 }
2191 }
2192
2193 if (Ph)
2194 Polyhedron_Free(Ph);
2195 /* Clear all the 'Value' variables */
2196 for (np = 0; np < nb_param + 1; np++) {
2197 value_clear(lcm[np]);
2198 value_clear(m1[np]);
2199 }
2200 value_clear(hdv);
2201 free(lcm);
2202 free(m1);
2203 /* We can't simply call Param_Polyhedron_Free because we've reused the domains
2204 */
2206 while (PP->D) {
2207 Q = PP->D;
2208 PP->D = PP->D->next;
2209 free(Q->F);
2210 free(Q);
2211 }
2212 free(PP);
2213
2214out:
2215 if (CEq)
2216 Polyhedron_Free(CEq);
2217 if (CT)
2218 Matrix_Free(CT);
2219 if (P != Pi)
2220 Polyhedron_Free(P);
2221
2222 return res;
2223} /* Polyhedron_Enumerate */
2224
2226 Enumeration *ee;
2227
2228 while (en) {
2229 free_evalue_refs(&(en->EP));
2231 ee = en->next;
2232 free(en);
2233 en = ee;
2234 }
2235}
2236
2237/* adds by B. Meister for Ehrhart Polynomial approximation */
2238
2239/**
2240 * Divides the evalue e by the integer n<br/>
2241 * recursive function<br/>
2242 * Warning : modifies e
2243 * @param e an evalue (to be divided by n)
2244 * @param n
2245 */
2246
2247void evalue_div(evalue *e, Value n) {
2248 int i;
2249 Value gc;
2250 value_init(gc);
2251 if (value_zero_p(e->d)) {
2252 for (i = 0; i < e->x.p->size; i++) {
2253 evalue_div(&(e->x.p->arr[i]), n);
2254 }
2255 } else {
2256 value_multiply(e->d, e->d, n);
2257 /* simplify the new rational if needed */
2258 value_gcd(gc, e->x.n, e->d);
2259 if (value_notone_p(gc)) {
2260 value_divexact(e->d, e->d, gc);
2261 value_divexact(e->x.n, e->x.n, gc);
2262 }
2263 }
2264 value_clear(gc);
2265} /* evalue_div */
2266
2267/**
2268
2269Ehrhart_Quick_Apx_Full_Dim(P, C, MAXRAYS, param_names)
2270
2271Procedure to estimate the number of points in a parameterized polytope.
2272Returns a list of validity domains + evalues EP
2273B.M.
2274The most rough and quick approximation by variables expansion
2275Deals with the full-dimensional case.
2276@param Pi : Polyhedron to enumerate (approximatively)
2277@param C : Context Domain
2278@param MAXRAYS : size of workspace
2279@param param_name : names for the parameters (char strings)
2280
2281*/
2283 unsigned MAXRAYS,
2284 const char **param_name) {
2285 Polyhedron *L, *CQ, *CQ2, *LQ, *U, *CEq, *rVD, *P;
2286 Matrix *CT;
2287 Param_Polyhedron *PP;
2288 Param_Domain *Q;
2289 int i, j, hdim, dim, nb_param, np;
2290 Value *lcm, *m1, hdv;
2291 Value *context;
2292 Enumeration *en, *res;
2293 Value expansion_det;
2294 Polyhedron *Expanded;
2295
2296 /* used to scan the vertices */
2297 Param_Vertices *V_tmp;
2298
2299 res = NULL;
2300 P = Pi;
2301
2302 value_init(expansion_det);
2303
2304#ifdef EDEBUG2
2305 fprintf(stderr, "C = \n");
2306 Polyhedron_Print(stderr, P_VALUE_FMT, C);
2307 fprintf(stderr, "P = \n");
2308 Polyhedron_Print(stderr, P_VALUE_FMT, P);
2309#endif
2310
2311 hdim = P->Dimension + 1;
2312 dim = P->Dimension;
2313 nb_param = C->Dimension;
2314
2315 /* Don't call Polyhedron2Param_Domain if there are no parameters */
2316 if (nb_param == 0) {
2317
2318 return (Enumerate_NoParameters(P, C, NULL, NULL, MAXRAYS, param_name));
2319 }
2320
2321#if EDEBUG2
2322 printf("Enumerating polyhedron : \n");
2323 Polyhedron_Print(stdout, P_VALUE_FMT, P);
2324#endif
2325
2326 PP = Polyhedron2Param_SimplifiedDomain(&P, C, MAXRAYS, &CEq, &CT);
2327 if (!PP) {
2328 if (param_name)
2329 fprintf(stdout, "\nEhrhart Polynomial:\nNULL\n");
2330
2331 return (NULL);
2332 }
2333
2334 /* CT : transformation matrix to eliminate useless ("false") parameters */
2335 if (CT) {
2336 nb_param -= CT->NbColumns - CT->NbRows;
2337 dim -= CT->NbColumns - CT->NbRows;
2338 hdim -= CT->NbColumns - CT->NbRows;
2339
2340 /* Don't call Polyhedron2Param_Domain if there are no parameters */
2341 if (nb_param == 0) {
2342 res = Enumerate_NoParameters(P, C, CT, CEq, MAXRAYS, param_name);
2343 if (P != Pi)
2344 Polyhedron_Free(P);
2345 return (res);
2346 }
2347 }
2348
2349 if (!PP->nbV)
2350 /* Leaks memory */
2351 return NULL;
2352
2353 /* get memory for Values */
2354 lcm = (Value *)malloc(nb_param * sizeof(Value));
2355 m1 = (Value *)malloc(nb_param * sizeof(Value));
2356 /* Initialize all the 'Value' variables */
2357 for (np = 0; np < nb_param; np++) {
2358 value_init(lcm[np]);
2359 value_init(m1[np]);
2360 }
2361 value_init(hdv);
2362
2363#if EDEBUG2
2364 Polyhedron_Print(stderr, P_VALUE_FMT, P);
2365#endif
2366
2367 Expanded = P;
2368 Param_Polyhedron_Scale_Integer(PP, &Expanded, &expansion_det, MAXRAYS);
2369
2370#if EDEBUG2
2371 Polyhedron_Print(stderr, P_VALUE_FMT, Expanded);
2372#endif
2373
2374 if (P != Expanded)
2375 Polyhedron_Free(P);
2376 P = Expanded;
2377
2378 /* formerly : Scan the vertices and compute lcm
2379 Scan_Vertices_Quick_Apx(PP,Q,CT,lcm,nb_param); */
2380 /* now : lcm = 1 (by construction) */
2381 /* OPT : A lot among what happens after this point can be simplified by
2382 knowing that lcm[i] = 1 for now, we just conservatively fool the rest of
2383 the function with lcm = 1 */
2384 for (i = 0; i < nb_param; i++)
2385 value_set_si(lcm[i], 1);
2386
2387 for (Q = PP->D; Q; Q = Q->next) {
2388 if (CT) {
2389 Polyhedron *Dt;
2390 CQ = Q->Domain;
2391 Dt = Polyhedron_Preimage(Q->Domain, CT, MAXRAYS);
2392 rVD = DomainIntersection(Dt, CEq, MAXRAYS);
2393
2394 /* if rVD is empty or too small in geometric dimension */
2395 if (!rVD || emptyQ(rVD) ||
2396 (rVD->Dimension - rVD->NbEq < Dt->Dimension - Dt->NbEq - CEq->NbEq)) {
2397 if (rVD)
2398 Polyhedron_Free(rVD);
2399 Polyhedron_Free(Dt);
2400 continue; /* empty validity domain */
2401 }
2402 Polyhedron_Free(Dt);
2403 } else
2404 rVD = CQ = Q->Domain;
2405 en = (Enumeration *)malloc(sizeof(Enumeration));
2406 en->next = res;
2407 res = en;
2408 res->ValidityDomain = rVD;
2409
2410 if (param_name) {
2411 fprintf(stdout, "---------------------------------------\n");
2412 fprintf(stdout, "Domain:\n");
2413
2414#ifdef EPRINT_ALL_VALIDITY_CONSTRAINTS
2415 Print_Domain(stdout, res->ValidityDomain, param_name);
2416#else
2417 {
2418 Polyhedron *VD;
2419 VD = DomainSimplify(res->ValidityDomain, C, MAXRAYS);
2420 Print_Domain(stdout, VD, param_name);
2421 Domain_Free(VD);
2422 }
2423#endif /* EPRINT_ALL_VALIDITY_CONSTRAINTS */
2424 }
2425
2427
2428#ifdef EDEBUG2
2429 fprintf(stderr, "Denominator = ");
2430 for (np = 0; np < nb_param; np++)
2431 value_print(stderr, P_VALUE_FMT, lcm[np]);
2432 fprintf(stderr, " and hdim == %d \n", hdim);
2433#endif
2434
2435#ifdef EDEBUG2
2436 fprintf(stderr, "CQ = \n");
2437 Polyhedron_Print(stderr, P_VALUE_FMT, CQ);
2438#endif
2439
2440 /* Before scanning, add constraints to ensure at least hdim*lcm */
2441 /* points in every dimension */
2442 value_set_si(hdv, hdim - nb_param);
2443
2444 for (np = 0; np < nb_param; np++) {
2445 if (value_notzero_p(lcm[np]))
2446 value_multiply(m1[np], hdv, lcm[np]);
2447 else
2448 value_set_si(m1[np], 1);
2449 }
2450
2451#ifdef EDEBUG2
2452 fprintf(stderr, "m1 == ");
2453 for (np = 0; np < nb_param; np++)
2454 value_print(stderr, P_VALUE_FMT, m1[np]);
2455 fprintf(stderr, "\n");
2456#endif
2457
2459 fprintf(stderr, "Enumerate: arithmetic overflow error.\n");
2460 CQ2 = NULL;
2461 }
2462 TRY {
2463 CQ2 = Polyhedron_Preprocess(CQ, m1, MAXRAYS);
2464
2465#ifdef EDEBUG2
2466 fprintf(stderr, "After preprocess, CQ2 = ");
2467 Polyhedron_Print(stderr, P_VALUE_FMT, CQ2);
2468#endif
2469
2471 }
2472
2473 /* Vin100, Feb 2001 */
2474 /* in case of degenerate, try to find a domain _containing_ CQ */
2475 if ((!CQ2 || emptyQ(CQ2)) && CQ->NbBid == 0) {
2476 int r;
2477
2478#ifdef EDEBUG2
2479 fprintf(stderr, "Trying to call Polyhedron_Preprocess2 : CQ = \n");
2480 Polyhedron_Print(stderr, P_VALUE_FMT, CQ);
2481#endif
2482
2483 /* Check if CQ is bounded */
2484 for (r = 0; r < CQ->NbRays; r++) {
2485 if (value_zero_p(CQ->Ray[r][0]) ||
2486 value_zero_p(CQ->Ray[r][CQ->Dimension + 1]))
2487 break;
2488 }
2489 if (r == CQ->NbRays) {
2490
2491 /* ok, CQ is bounded */
2492 /* now find if CQ is contained in a hypercube of size m1 */
2493 CQ2 = Polyhedron_Preprocess2(CQ, m1, lcm, MAXRAYS);
2494 }
2495 }
2496 if (!CQ2 || emptyQ(CQ2)) {
2497#ifdef EDEBUG2
2498 fprintf(stderr, "Degenerate.\n");
2499#endif
2500 fprintf(stdout, "Degenerate Domain. Can not continue.\n");
2501 value_init(res->EP.d);
2502 value_init(res->EP.x.n);
2503 value_set_si(res->EP.d, 1);
2504 value_set_si(res->EP.x.n, -1);
2505 } else {
2506
2507#ifdef EDEBUG2
2508 fprintf(stderr, "CQ2 = \n");
2509 Polyhedron_Print(stderr, P_VALUE_FMT, CQ2);
2510 if (!PolyhedronIncludes(CQ, CQ2))
2511 fprintf(stderr, "CQ does not include CQ2 !\n");
2512 else
2513 fprintf(stderr, "CQ includes CQ2.\n");
2514 if (!PolyhedronIncludes(res->ValidityDomain, CQ2))
2515 fprintf(stderr, "CQ2 is *not* included in validity domain !\n");
2516 else
2517 fprintf(stderr, "CQ2 is included in validity domain.\n");
2518#endif
2519
2520 /* L is used in counting the number of points in the base cases */
2521 L = Polyhedron_Scan(P, CQ, MAXRAYS);
2522 U = Universe_Polyhedron(0);
2523
2524 /* LQ is used to scan the parameter space */
2525 LQ = Polyhedron_Scan(CQ2, U, MAXRAYS); /* bounds on parameters */
2526 Domain_Free(U);
2527 if (CT) /* we did compute another Q->Domain */
2528 Domain_Free(CQ);
2529
2530 /* Else, CQ was Q->Domain (used in res) */
2531 Domain_Free(CQ2);
2532
2533#ifdef EDEBUG2
2534 fprintf(stderr, "L = \n");
2535 Polyhedron_Print(stderr, P_VALUE_FMT, L);
2536 fprintf(stderr, "LQ = \n");
2537 Polyhedron_Print(stderr, P_VALUE_FMT, LQ);
2538#endif
2539#ifdef EDEBUG3
2540 fprintf(stdout, "\nSystem of Equations:\n");
2541#endif
2542
2543 value_init(res->EP.d);
2544 value_set_si(res->EP.d, 0);
2545
2546 /* Create a context vector size dim+2 */
2547 context = (Value *)malloc((hdim + 1) * sizeof(Value));
2548 for (i = 0; i <= (hdim); i++)
2549 value_init(context[i]);
2550 Vector_Set(context, 0, (hdim + 1));
2551
2552 /* Set context[hdim] = 1 (the constant) */
2553 value_set_si(context[hdim], 1);
2554
2556 fprintf(stderr, "Enumerate: arithmetic overflow error.\n");
2557 fprintf(stderr, "You should rebuild PolyLib using GNU-MP "
2558 "or increasing the size of integers.\n");
2561 }
2562 TRY {
2563 res->EP.x.p = P_Enum(L, LQ, context, 1, nb_param, dim, lcm, param_name);
2565 }
2566
2567 for (i = 0; i <= (hdim); i++)
2568 value_clear(context[i]);
2569 free(context);
2570 Domain_Free(L);
2571 Domain_Free(LQ);
2572
2573#ifdef EDEBUG5
2574 if (param_name) {
2575 fprintf(stdout, "\nEhrhart Polynomial (before simplification):\n");
2576 print_evalue(stdout, &res->EP, param_name);
2577 }
2578
2579 /* BM: divide EP by denom_det, the expansion factor */
2580 fprintf(stdout, "\nEhrhart Polynomial (before division):\n");
2581 print_evalue(stdout, &(res->EP), param_name);
2582#endif
2583
2584 evalue_div(&(res->EP), expansion_det);
2585
2586 /* Try to simplify the result */
2587 reduce_evalue(&res->EP);
2588
2589 /* Put back the original parameters into result */
2590 /* (equalities have been eliminated) */
2591 if (CT)
2592 addeliminatedparams_evalue(&res->EP, CT);
2593
2594 if (param_name) {
2595 fprintf(stdout, "\nEhrhart Polynomial:\n");
2596 print_evalue(stdout, &res->EP, param_name);
2597 fprintf(stdout, "\n");
2598 /* sometimes the final \n lacks (when a single constant is printed)
2599 */
2600 }
2601 }
2602 }
2603 value_clear(expansion_det);
2604
2605 if (P != Pi)
2606 Polyhedron_Free(P);
2607 /* Clear all the 'Value' variables */
2608 for (np = 0; np < nb_param; np++) {
2609 value_clear(lcm[np]);
2610 value_clear(m1[np]);
2611 }
2612 value_clear(hdv);
2613
2614 return res;
2615} /* Ehrhart_Quick_Apx_Full_Dim */
2616
2617/**
2618 * Computes the approximation of the Ehrhart polynomial of a polyhedron
2619 * (implicit form -> matrix), treating the non-full-dimensional case.
2620 * @param M a polyhedron under implicit form
2621 * @param C M's context under implicit form
2622 * @param Validity_Lattice a pointer to the parameter's validity lattice
2623 * @param MAXRAYS the needed "working space" for other polylib functions used
2624 * here
2625 * @param param_name the names of the parameters,
2626 */
2628 unsigned maxRays) {
2629 /* char ** param_name) {*/
2630
2631 /* 0- compute a full-dimensional polyhedron with the same number of points,
2632 and its parameter's validity lattice */
2633 Matrix *M_full;
2634 Polyhedron *P, *PC;
2635 Enumeration *en;
2636
2637 M_full = full_dimensionize(M, C->NbColumns - 2, Validity_Lattice);
2638 /* 1- apply the same tranformation to the context that what has been applied
2639 to the parameters space of the polyhedron. */
2640 mpolyhedron_compress_last_vars(C, *Validity_Lattice);
2641 show_matrix(M_full);
2642 P = Constraints2Polyhedron(M_full, maxRays);
2644 Matrix_Free(M_full);
2645 /* compute the Ehrhart polynomial of the "equivalent" polyhedron */
2646 en = Ehrhart_Quick_Apx_Full_Dim(P, PC, maxRays, NULL);
2647
2648 /* clean up */
2649 Polyhedron_Free(P);
2650 Polyhedron_Free(PC);
2651 return en;
2652} /* Ehrhart_Quick_Apx */
2653
2654/**
2655 * Computes the approximation of the Ehrhart polynomial of a polyhedron
2656 * (implicit form -> matrix), treating the non-full-dimensional case. If there
2657 * are some equalities involving only parameters, these are used to eliminate
2658 * useless parameters.
2659 * @param M a polyhedron under implicit form
2660 * @param C M's context under implicit form
2661 * @param validityLattice a pointer to the parameter's validity lattice
2662 * (returned)
2663 * @param parmsEqualities Equalities involving only the parameters
2664 * @param maxRays the needed "working space" for other polylib functions used
2665 * here
2666 * @param elimParams array of the indices of the eliminated parameters
2667 * (returned)
2668 */
2670 Matrix **validityLattice,
2671 Matrix **parmEqualities,
2672 unsigned int **elimParms,
2673 unsigned maxRays) {
2674 Enumeration *EP;
2675 Matrix *Mp = Matrix_Copy(M);
2676 Matrix *Cp = Matrix_Copy(C);
2677 /* remove useless equalities involving only parameters, using these
2678 equalities to remove parameters. */
2679 (*parmEqualities) = Constraints_Remove_parm_eqs(&Mp, &Cp, 0, elimParms);
2680 if (Mp->NbRows >= 0) { /* if there is no contradiction */
2681 EP = Ehrhart_Quick_Apx(Mp, Cp, validityLattice, maxRays);
2682 return EP;
2683 } else {
2684 /* if there are contradictions, return a zero Ehrhart polynomial */
2685 return NULL;
2686 }
2687}
2688
2689/**
2690 * Returns the array of parameter names after some of them have been eliminated.
2691 * @param parmNames the initial names of the parameters
2692 * @param elimParms a list of parameters that have been eliminated from the
2693 * original parameters. The first element of this array is the number of
2694 * elements.
2695 * <p> Note: does not copy the parameters names themselves. </p>
2696 * @param nbParms the initial number of parameters
2697 */
2698const char **parmsWithoutElim(char const **parmNames,
2699 unsigned int const *elimParms,
2700 unsigned int nbParms) {
2701 int i = 0, j = 0, k;
2702 int newParmNb = nbParms - elimParms[0];
2703 const char **newParmNames = (const char **)malloc(newParmNb * sizeof(char *));
2704 for (k = 1; k <= elimParms[0]; k++) {
2705 while (i != elimParms[k]) {
2706 newParmNames[i - k + 1] = parmNames[i];
2707 i++;
2708 }
2709 }
2710 return newParmNames;
2711}
2712
2713/**
2714 * returns a constant Ehrhart polynomial whose value is zero for any value of
2715 * the parameters.
2716 * @param nbParms the number of parameters, i.e., the number of arguments to
2717 * the Ehrhart polynomial
2718 */
2719Enumeration *Enumeration_zero(unsigned int nbParms, unsigned int maxRays) {
2720 Matrix *Mz = Matrix_Alloc(1, nbParms + 3);
2721 Polyhedron *emptyP;
2722 Polyhedron *universe;
2723 Enumeration *zero;
2724 /* 1- build an empty polyhedron with the right dimension */
2725 /* here we choose to take 2i = -1 */
2726 value_set_si(Mz->p[0][1], 2);
2727 value_set_si(Mz->p[0][nbParms + 2], 1);
2728 emptyP = Constraints2Polyhedron(Mz, maxRays);
2729 Matrix_Free(Mz);
2730 universe = Universe_Polyhedron(nbParms);
2731 zero = Polyhedron_Enumerate(emptyP, universe, maxRays, NULL);
2732 Polyhedron_Free(emptyP);
2733 Polyhedron_Free(universe);
2734 return zero;
2735} /* Enumeration_zero() */
Matrix * Matrix_Copy(Matrix const *Src)
Definition: Matop.c:98
#define CATCH(what)
#define UNCATCH(what)
#define TRY
#define value_pos_p(val)
Definition: arithmetique.h:571
#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_le(v1, v2)
Definition: arithmetique.h:507
#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_negz_p(val)
Definition: arithmetique.h:574
#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_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_notmone_p(val)
Definition: arithmetique.h:580
#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_subtract(ref, val1, val2)
Definition: arithmetique.h:544
#define value_addto(ref, val1, val2)
Definition: arithmetique.h:537
#define value_ge(v1, v2)
Definition: arithmetique.h:505
#define value_neg_p(val)
Definition: arithmetique.h:572
#define value_init(val)
Definition: arithmetique.h:481
#define value_posz_p(val)
Definition: arithmetique.h:573
#define assert(ex)
Definition: assert.h:16
Matrix * Constraints_Remove_parm_eqs(Matrix **M1, Matrix **Ctxt1, int renderSpace, unsigned int **elimParms)
Removes the equalities that involve only parameters, by eliminating some parameters in the polyhedron...
Matrix * full_dimensionize(Matrix const *M, int nbParms, Matrix **validityLattice)
Given a matrix with m parameterized equations, compress the nb_parms parameters and n-m variables so ...
static int eequal(evalue *e1, evalue *e2)
Definition: ehrhart.c:234
Enumeration * Constraints_EhrhartQuickApx(Matrix const *M, Matrix const *C, Matrix **validityLattice, Matrix **parmEqualities, unsigned int **elimParms, unsigned maxRays)
Computes the approximation of the Ehrhart polynomial of a polyhedron (implicit form -> matrix),...
Definition: ehrhart.c:2669
Polyhedron * old_Polyhedron_Preprocess(Polyhedron *D, Value size, unsigned MAXRAYS)
This procedure adds additional constraints to D so that as each parameter is scanned,...
Definition: ehrhart.c:1060
void edot(enode *v1, enode *v2, evalue *res)
computes the inner product of two vectors.
Definition: ehrhart.c:514
void evalue_div(evalue *e, Value n)
Divides the evalue e by the integer n recursive function Warning : modifies e.
Definition: ehrhart.c:2247
Enumeration * Enumerate_NoParameters(Polyhedron *P, Polyhedron *C, Matrix *CT, Polyhedron *CEq, unsigned MAXRAYS, const char **param_name)
Procedure to count points in a non-parameterized polytope.
Definition: ehrhart.c:1750
Enumeration * Polyhedron_Enumerate(Polyhedron *Pi, Polyhedron *C, unsigned MAXRAYS, const char **param_name)
Procedure to count points in a parameterized polytope.
Definition: ehrhart.c:1870
Enumeration * Enumeration_zero(unsigned int nbParms, unsigned int maxRays)
returns a constant Ehrhart polynomial whose value is zero for any value of the parameters.
Definition: ehrhart.c:2719
static void emul(evalue *e1, evalue *e2, evalue *res)
multiplies two evalues and puts the result in res
Definition: ehrhart.c:344
const char ** parmsWithoutElim(char const **parmNames, unsigned int const *elimParms, unsigned int nbParms)
Returns the array of parameter names after some of them have been eliminated.
Definition: ehrhart.c:2698
enode * new_enode(enode_type type, int size, int pos)
EHRHART POLYNOMIAL SYMBOLIC ALGEBRA SYSTEM.
Definition: ehrhart.c:90
void eadd(evalue *e1, evalue *res)
adds one evalue to evalue 'res.
Definition: ehrhart.c:385
int cherche_min(Value *min, Polyhedron *D, int pos)
Definition: ehrhart.c:624
static void aep_evalue(evalue *e, int *ref)
local recursive function used in the following ref contains the new position for each old index posit...
Definition: ehrhart.c:557
Polyhedron * Polyhedron_Preprocess(Polyhedron *D, Value *size, unsigned MAXRAYS)
This procedure finds the smallest parallelepiped of size 'size[i]' for every dimension i,...
Definition: ehrhart.c:738
void print_enode(FILE *DST, enode *p, const char **pname)
prints the enode to DST
Definition: ehrhart.c:190
Enumeration * Ehrhart_Quick_Apx_Full_Dim(Polyhedron *Pi, Polyhedron *C, unsigned MAXRAYS, const char **param_name)
Ehrhart_Quick_Apx_Full_Dim(P, C, MAXRAYS, param_names)
Definition: ehrhart.c:2282
void free_evalue_refs(evalue *e)
releases all memory referenced by e.
Definition: ehrhart.c:115
void print_evalue(FILE *DST, evalue *e, const char **pname)
Definition: ehrhart.c:169
Polyhedron * Polyhedron_Preprocess2(Polyhedron *D, Value *size, Value *lcm, unsigned MAXRAYS)
This procedure finds an hypercube of size 'size', containing polyhedron D increases size and lcm if n...
Definition: ehrhart.c:891
#define MAXITER
This procedure finds an integer point contained in polyhedron D / first checks for positive values,...
Definition: ehrhart.c:623
static enode * P_Enum(Polyhedron *L, Polyhedron *LQ, Value *context, int pos, int nb_param, int dim, Value *lcm, const char **param_name)
Definition: ehrhart.c:1265
static void addeliminatedparams_evalue(evalue *e, Matrix *CT)
Comments.
Definition: ehrhart.c:577
int overflow_warning_flag
Definition: ehrhart.c:74
enode * ecopy(enode *e)
Definition: ehrhart.c:144
void count_points(int pos, Polyhedron *P, Value *context, Value *res)
PROCEDURES TO COMPUTE ENUMERATION.
Definition: ehrhart.c:1154
void reduce_evalue(evalue *e)
Definition: ehrhart.c:271
void Enumeration_Free(Enumeration *en)
Definition: ehrhart.c:2225
static void Scan_Vertices(Param_Polyhedron *PP, Param_Domain *Q, Matrix *CT, Value *lcm, int nbp, const char **param_name)
Definition: ehrhart.c:1679
Enumeration * Ehrhart_Quick_Apx(Matrix *M, Matrix *C, Matrix **Validity_Lattice, unsigned maxRays)
Computes the approximation of the Ehrhart polynomial of a polyhedron (implicit form -> matrix),...
Definition: ehrhart.c:2627
unsigned int overflow_error
Definition: errors.c:96
Polyhedron * homogenize(Polyhedron *P, unsigned MAXRAYS)
homogenization.h – Bavo Nootaert
void dehomogenize_evalue(evalue *ep, int nb_param)
dehomogenize an evalue.
Matrix * Matrix_Alloc(unsigned NbRows, unsigned NbColumns)
Definition: matrix.c:24
void Matrix_Print(FILE *Dst, const char *Format, Matrix *Mat)
Definition: matrix.c:115
void Matrix_Free(Matrix *Mat)
Definition: matrix.c:71
void mpolyhedron_compress_last_vars(Matrix *M, Matrix *compression)
compress the last vars/pars of the polyhedron M expressed as a polylib matrix
Definition: matrix_addon.c:261
#define show_matrix(M)
Polylib matrix addons Mainly, deals with polyhedra represented in implicit form (set of constraints).
Definition: matrix_addon.h:15
int PolyhedronIncludes(Polyhedron *Pol1, Polyhedron *Pol2)
Definition: polyhedron.c:2404
void Polyhedron_Free(Polyhedron *Pol)
Definition: polyhedron.c:1614
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 * 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
Polyhedron * DomainSimplify(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Definition: polyhedron.c:3346
Polyhedron * Universe_Polyhedron(unsigned Dimension)
Definition: polyhedron.c:1754
int lower_upper_bounds(int pos, Polyhedron *P, Value *context, Value *LBp, Value *UBp)
Definition: polyhedron.c:3905
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
void Domain_Free(Polyhedron *Pol)
Definition: polyhedron.c:1626
#define POL_ENSURE_VERTICES(P)
Definition: polyhedron.h:17
#define POL_ENSURE_FACETS(P)
Definition: polyhedron.h:13
void Param_Vertices_Free(Param_Vertices *PV)
Definition: polyparam.c:1563
static Matrix * Pi
Definition: polyparam.c:283
void Param_Polyhedron_Free(Param_Polyhedron *P)
Definition: polyparam.c:1875
void Param_Polyhedron_Scale_Integer(Param_Polyhedron *PP, Polyhedron **P, Value *det, unsigned MaxRays)
Definition: polyparam.c:1892
Matrix * VertexCT(Matrix *V, Matrix *CT)
Definition: polyparam.c:1651
static int n
Definition: polyparam.c:276
Param_Polyhedron * Polyhedron2Param_SimplifiedDomain(Polyhedron **Din, Polyhedron *Cin, int working_space, Polyhedron **CEq, Matrix **CT)
Definition: polyparam.c:1804
void Print_Vertex(FILE *DST, Matrix *V, const char **param_names)
Definition: polyparam.c:1583
void Print_Domain(FILE *DST, Polyhedron *D, const char **pname)
Definition: polyparam.c:1680
char s[128]
Definition: polytest.c:8
struct _Param_Domain * next
Definition: types.h:138
Polyhedron * Domain
Definition: types.h:137
unsigned * F
Definition: types.h:136
Param_Vertices * V
Definition: types.h:143
Param_Domain * D
Definition: types.h:144
struct _Param_Vertex * next
Definition: types.h:132
Matrix * Vertex
Definition: types.h:126
Definition: types.h:182
int pos
Definition: types.h:185
evalue arr[1]
Definition: types.h:186
enode_type type
Definition: types.h:183
int size
Definition: types.h:184
Polyhedron * ValidityDomain
Definition: types.h:191
evalue EP
Definition: types.h:192
struct _enumeration * next
Definition: types.h:193
Definition: types.h:173
Value d
Definition: types.h:174
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
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 NbEq
Definition: types.h:94
#define maxRays
enode_type
Definition: types.h:165
@ periodic
Definition: types.h:165
@ polynomial
Definition: types.h:165
@ evector
Definition: types.h:165
#define MSB
Definition: types.h:48
#define emptyQ(P)
Definition: types.h:118
#define POL_ISSET(flags, f)
Definition: types.h:68
#define NEXT(j, b)
Definition: types.h:54
#define UB_INFINITY
Definition: types.h:44
#define POL_NO_DUAL
Definition: types.h:66
#define LB_INFINITY
Definition: types.h:43
#define P_VALUE_FMT
Definition: types.h:39
void Vector_Set(Value *p, int n, unsigned length)
Definition: vector.c:227
void Vector_Combine(Value *p1, Value *p2, Value *p3, Value lambda, Value mu, unsigned length)
Definition: vector.c:425
void Vector_Normalize(Value *p, unsigned length)
Definition: vector.c:555
void Vector_Copy(Value *p1, Value *p2, unsigned length)
Definition: vector.c:256
Value min
Definition: verif_ehrhart.c:43
#define MAXRAYS
Definition: verif_ehrhart.c:20