polylib 7.01
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, 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, 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*/
738 unsigned MAXRAYS) {
739 Matrix *M;
740 int i, j, d;
741 Polyhedron *T, *S, *H, *C;
742 Vector *min;
743
744 d = D->Dimension;
745 if (MAXRAYS < 2 * D->NbConstraints)
746 MAXRAYS = 2 * D->NbConstraints;
747 M = Matrix_Alloc(MAXRAYS, D->Dimension + 2);
748 M->NbRows = D->NbConstraints;
749
750 /* Original constraints */
751 for (i = 0; i < D->NbConstraints; i++)
752 Vector_Copy(D->Constraint[i], M->p[i], (d + 2));
753
754#ifdef EDEBUG6
755 fprintf(stderr, "M for PreProcess : ");
756 Matrix_Print(stderr, P_VALUE_FMT, M);
757 fprintf(stderr, "\nsize == ");
758 for (i = 0; i < d; i++)
759 value_print(stderr, P_VALUE_FMT, size[i]);
760 fprintf(stderr, "\n");
761#endif
762
763 /* Additionnal constraints */
764 for (i = 0; i < D->NbConstraints; i++) {
765 if (value_zero_p(D->Constraint[i][0])) {
766 fprintf(stderr, "Polyhedron_Preprocess: ");
767 fprintf(stderr,
768 "an equality was found where I did expect an inequality.\n");
769 fprintf(stderr, "Trying to continue...\n");
770 continue;
771 }
772 Vector_Copy(D->Constraint[i], M->p[M->NbRows], (d + 2));
773 for (j = 1; j <= d; j++)
774 if (value_neg_p(D->Constraint[i][j])) {
775 value_addmul(M->p[M->NbRows][d + 1], D->Constraint[i][j], size[j - 1]);
776 }
777
778 /* If anything changed, add this new constraint */
779 if (value_ne(M->p[M->NbRows][d + 1], D->Constraint[i][d + 1]))
780 M->NbRows++;
781 }
782
783#ifdef EDEBUG6
784 fprintf(stderr, "M used to find min : ");
785 Matrix_Print(stderr, P_VALUE_FMT, M);
786#endif
787
789 Matrix_Free(M);
790 if (!T || emptyQ(T)) {
791 if (T)
793 return (NULL);
794 }
795
796 /* Ok, now find the lexicographical min of T */
797 min = Vector_Alloc(d+2);
798 value_set_si(min->p[d+1], 1);
799 C = Universe_Polyhedron(0);
800 S = Polyhedron_Scan(T, C, MAXRAYS);
803
804#ifdef EDEBUG6
805 for (i = 0; i <= (d + 1); i++) {
806 value_print(stderr, P_VALUE_FMT, min[i]);
807 fprintf(stderr, " ,");
808 }
809 fprintf(stderr, "\n");
810 Polyhedron_Print(stderr, P_VALUE_FMT, S);
811 fprintf(stderr, "\n");
812#endif
813
814 if (!cherche_min(min->p, S, 1)) {
815 for (i = 0; i <= (d + 1); i++)
816 value_clear(min->p[i]);
817 return (NULL);
818 }
819 Domain_Free(S);
820
821#ifdef EDEBUG6
822 fprintf(stderr, "min->p = ( ");
823 value_print(stderr, P_VALUE_FMT, min->p[1]);
824 for (i = 2; i <= d; i++) {
825 fprintf(stderr, ", ");
826 value_print(stderr, P_VALUE_FMT, min->p[i]);
827 }
828 fprintf(stderr, ")\n");
829#endif
830
831 /* Min->p is the point from which we can construct the hypercube */
832 M = Matrix_Alloc(d * 2, d + 2);
833 for (i = 0; i < d; i++) {
834
835 /* Creates inequality 1 0..0 1 0..0 -min->p[i+1] */
836 value_set_si(M->p[2 * i][0], 1);
837 for (j = 1; j <= d; j++)
838 value_set_si(M->p[2 * i][j], 0);
839 value_set_si(M->p[2 * i][i + 1], 1);
840 value_oppose(M->p[2 * i][d + 1], min->p[i + 1]);
841
842 /* Creates inequality 1 0..0 -1 0..0 min->p[i+1]+size -1 */
843 value_set_si(M->p[2 * i + 1][0], 1);
844 for (j = 1; j <= d; j++)
845 value_set_si(M->p[2 * i + 1][j], 0);
846 value_set_si(M->p[2 * i + 1][i + 1], -1);
847 value_addto(M->p[2 * i + 1][d + 1], min->p[i + 1], size[i]);
848 value_sub_int(M->p[2 * i + 1][d + 1], M->p[2 * i + 1][d + 1], 1);
849 }
850
851#ifdef EDEBUG6
852 fprintf(stderr, "PolyhedronPreprocess: constraints H = ");
853 Matrix_Print(stderr, P_VALUE_FMT, M);
854#endif
855
857
858#ifdef EDEBUG6
859 Polyhedron_Print(stderr, P_VALUE_FMT, H);
860 fprintf(stderr, "\n");
861#endif
862
863 Matrix_Free(M);
865 assert(!emptyQ(H));
866 return (H);
867} /* Polyhedron_Preprocess */
868
869/** This procedure finds an hypercube of size 'size', containing
870polyhedron D increases size and lcm if necessary (and not "too big")
871If this is not possible, an empty polyhedron is returned
872
873<p>
874
875<pre> written by vin100, 2001, for version 4.19</pre>
876
877@param D
878@param size
879@param lcm
880@param MAXRAYS
881
882*/
884 unsigned MAXRAYS) {
885
886 Matrix *c;
887 Polyhedron *H;
888 int i, j, r;
889 Value n; /* smallest/biggest value */
890 Value s; /* size in this dimension */
891 Value tmp1, tmp2;
892
893#ifdef EDEBUG62
894 int np;
895#endif
896
897 value_init(n);
898 value_init(s);
899 value_init(tmp1);
900 value_init(tmp2);
901 c = Matrix_Alloc(D->Dimension * 2, D->Dimension + 2);
902
903#ifdef EDEBUG62
904 fprintf(stderr, "\nPreProcess2 : starting\n");
905 fprintf(stderr, "lcm = ");
906 for (np = 0; np < D->Dimension; np++)
907 value_print(stderr, VALUE_FMT, lcm[np]);
908 fprintf(stderr, ", size = ");
909 for (np = 0; np < D->Dimension; np++)
910 value_print(stderr, VALUE_FMT, size[np]);
911 fprintf(stderr, "\n");
912#endif
913
914 for (i = 0; i < D->Dimension; i++) {
915
916 /* Create constraint 1 0..0 1 0..0 -min */
917 value_set_si(c->p[2 * i][0], 1);
918 for (j = 0; j < D->Dimension; j++)
919 value_set_si(c->p[2 * i][1 + j], 0);
920 value_division(n, D->Ray[0][i + 1], D->Ray[0][D->Dimension + 1]);
921 for (r = 1; r < D->NbRays; r++) {
922 value_division(tmp1, D->Ray[r][i + 1], D->Ray[r][D->Dimension + 1]);
923 if (value_gt(n, tmp1)) {
924
925 /* New min */
926 value_division(n, D->Ray[r][i + 1], D->Ray[r][D->Dimension + 1]);
927 }
928 }
929 value_set_si(c->p[2 * i][i + 1], 1);
930 value_oppose(c->p[2 * i][D->Dimension + 1], n);
931
932 /* Create constraint 1 0..0 -1 0..0 max */
933 value_set_si(c->p[2 * i + 1][0], 1);
934 for (j = 0; j < D->Dimension; j++)
935 value_set_si(c->p[2 * i + 1][1 + j], 0);
936
937 /* n = (num+den-1)/den */
938 value_addto(tmp1, D->Ray[0][i + 1], D->Ray[0][D->Dimension + 1]);
939 value_sub_int(tmp1, tmp1, 1);
940 value_division(n, tmp1, D->Ray[0][D->Dimension + 1]);
941 for (r = 1; r < D->NbRays; r++) {
942 value_addto(tmp1, D->Ray[r][i + 1], D->Ray[r][D->Dimension + 1]);
943 value_sub_int(tmp1, tmp1, 1);
944 value_division(tmp1, tmp1, D->Ray[r][D->Dimension + 1]);
945 if (value_lt(n, tmp1)) {
946
947 /* New max */
948 value_addto(tmp1, D->Ray[r][i + 1], D->Ray[r][D->Dimension + 1]);
949 value_sub_int(tmp1, tmp1, 1);
950 value_division(n, tmp1, D->Ray[r][D->Dimension + 1]);
951 }
952 }
953 value_set_si(c->p[2 * i + 1][i + 1], -1);
954 value_assign(c->p[2 * i + 1][D->Dimension + 1], n);
955 value_addto(s, c->p[2 * i + 1][D->Dimension + 1],
956 c->p[2 * i][D->Dimension + 1]);
957
958 /* Now test if the dimension of the cube is greater than the size */
959 if (value_gt(s, size[i])) {
960
961#ifdef EDEBUG62
962 fprintf(stderr, "size on dimension %d\n", i);
963 fprintf(stderr, "lcm = ");
964 for (np = 0; np < D->Dimension; np++)
965 value_print(stderr, VALUE_FMT, lcm[np]);
966 fprintf(stderr, ", size = ");
967 for (np = 0; np < D->Dimension; np++)
968 value_print(stderr, VALUE_FMT, size[np]);
969 fprintf(stderr, "\n");
970 fprintf(stderr, "required size (s) = ");
971 value_print(stderr, VALUE_FMT, s);
972 fprintf(stderr, "\n");
973#endif
974
975 /* If the needed size is "small enough"(<=20 or less than
976 twice *size),
977 then increase *size, and artificially increase lcm too !*/
978 value_set_si(tmp1, 20);
979 value_addto(tmp2, size[i], size[i]);
980 if (value_le(s, tmp1) || value_le(s, tmp2)) {
981
982 if (value_zero_p(lcm[i]))
983 value_set_si(lcm[i], 1);
984 /* lcm divides size... */
985 value_division(tmp1, size[i], lcm[i]);
986
987 /* lcm = ceil(s/h) */
988 value_addto(tmp2, s, tmp1);
989 value_add_int(tmp2, tmp2, 1);
990 value_division(lcm[i], tmp2, tmp1);
991
992 /* new size = lcm*h */
993 value_multiply(size[i], lcm[i], tmp1);
994
995#ifdef EDEBUG62
996 fprintf(stderr, "new size = ");
997 for (np = 0; np < D->Dimension; np++)
998 value_print(stderr, VALUE_FMT, size[np]);
999 fprintf(stderr, ", new lcm = ");
1000 for (np = 0; np < D->Dimension; np++)
1001 value_print(stderr, VALUE_FMT, lcm[np]);
1002 fprintf(stderr, "\n");
1003#endif
1004
1005 } else {
1006
1007#ifdef EDEBUG62
1008 fprintf(stderr, "Failed on dimension %d.\n", i);
1009#endif
1010 break;
1011 }
1012 }
1013 }
1014 if (i != D->Dimension) {
1015 Matrix_Free(c);
1016 value_clear(n);
1017 value_clear(s);
1018 value_clear(tmp1);
1019 value_clear(tmp2);
1020 return (NULL);
1021 }
1022 for (i = 0; i < D->Dimension; i++) {
1023 value_subtract(c->p[2 * i + 1][D->Dimension + 1], size[i],
1024 c->p[2 * i][D->Dimension + 1]);
1025 }
1026
1027#ifdef EDEBUG62
1028 fprintf(stderr, "PreProcess2 : c =");
1029 Matrix_Print(stderr, P_VALUE_FMT, c);
1030#endif
1031
1033 Matrix_Free(c);
1034 value_clear(n);
1035 value_clear(s);
1036 value_clear(tmp1);
1037 value_clear(tmp2);
1038 return (H);
1039} /* Polyhedron_Preprocess2 */
1040
1041/**
1042
1043This procedure adds additional constraints to D so that as each
1044parameter is scanned, it will have a minimum of 'size' points If this
1045is not possible, an empty polyhedron is returned
1046
1047@param D
1048@param size
1049@param MAXRAYS
1050
1051*/
1053 unsigned MAXRAYS) {
1054
1055 int p, p1, ub, lb;
1056 Value a, a1, b, b1, g, aa;
1057 Value abs_a, abs_b, size_copy;
1058 int dim, con, newi, needed;
1059 Value **C;
1060 Matrix *M;
1061 Polyhedron *D1;
1062
1063 value_init(a);
1064 value_init(a1);
1065 value_init(b);
1066 value_init(b1);
1067 value_init(g);
1068 value_init(aa);
1069 value_init(abs_a);
1070 value_init(abs_b);
1071 value_init(size_copy);
1072
1073 dim = D->Dimension;
1074 con = D->NbConstraints;
1075 M = Matrix_Alloc(MAXRAYS, dim + 2);
1076 newi = 0;
1077 value_assign(size_copy, size);
1078 C = D->Constraint;
1079 for (p = 1; p <= dim; p++) {
1080 for (ub = 0; ub < con; ub++) {
1081 value_assign(a, C[ub][p]);
1082 if (value_posz_p(a)) /* a >= 0 */
1083 continue; /* not an upper bound */
1084 for (lb = 0; lb < con; lb++) {
1085 value_assign(b, C[lb][p]);
1086 if (value_negz_p(b))
1087 continue; /* not a lower bound */
1088
1089 /* Check if a new constraint is needed for this (ub,lb) pair */
1090 /* a constraint is only needed if a previously scanned */
1091 /* parameter (1..p-1) constrains this parameter (p) */
1092 needed = 0;
1093 for (p1 = 1; p1 < p; p1++) {
1094 if (value_notzero_p(C[ub][p1]) || value_notzero_p(C[lb][p1])) {
1095 needed = 1;
1096 break;
1097 }
1098 }
1099 if (!needed)
1100 continue;
1101 value_absolute(abs_a, a);
1102 value_absolute(abs_b, b);
1103
1104 /* Create new constraint: b*UB-a*LB >= a*b*size */
1105 value_gcd(g, abs_a, abs_b);
1106 value_divexact(a1, a, g);
1107 value_divexact(b1, b, g);
1108 value_set_si(M->p[newi][0], 1);
1109 value_oppose(abs_a, a1); /* abs_a = -a1 */
1110 Vector_Combine(&(C[ub][1]), &(C[lb][1]), &(M->p[newi][1]), b1, abs_a,
1111 dim + 1);
1112 value_multiply(aa, a1, b1);
1113 value_addmul(M->p[newi][dim + 1], aa, size_copy);
1114 Vector_Normalize(&(M->p[newi][1]), (dim + 1));
1115 newi++;
1116 }
1117 }
1118 }
1119 D1 = AddConstraints(M->p_Init, newi, D, MAXRAYS);
1120 Matrix_Free(M);
1121
1122 value_clear(a);
1123 value_clear(a1);
1124 value_clear(b);
1125 value_clear(b1);
1126 value_clear(g);
1127 value_clear(aa);
1128 value_clear(abs_a);
1129 value_clear(abs_b);
1130 value_clear(size_copy);
1131 return D1;
1132} /* old_Polyhedron_Preprocess */
1133
1134/**
1135
1136PROCEDURES TO COMPUTE ENUMERATION. recursive procedure, recurse for
1137each imbriquation
1138
1139@param pos index position of current loop index (1..hdim-1)
1140@param P loop domain
1141@param context context values for fixed indices
1142@param res the number of integer points in this
1143polyhedron
1144
1145*/
1146void count_points(int pos, Polyhedron *P, Value *context, Value *res) {
1147
1148 Value LB, UB, c;
1149
1152
1153 if (emptyQ(P)) {
1154 value_set_si(*res, 0);
1155 return;
1156 }
1157
1158 value_init(LB);
1159 value_init(UB);
1160 // value_set_si(LB, 0);
1161 // value_set_si(UB, 0);
1162
1163 if (lower_upper_bounds(pos, P, context, &LB, &UB) != 0) {
1164
1165 /* Problem if UB or LB is INFINITY */
1166 fprintf(stderr, "count_points: ? infinite domain\n");
1167 value_clear(LB);
1168 value_clear(UB);
1169 value_set_si(*res, -1);
1170 return;
1171 }
1172
1173 #ifdef EDEBUG1
1174 if (!P->next) {
1175 int i;
1176 for (value_assign(k, LB); value_le(k, UB); value_increment(k, k)) {
1177 fprintf(stderr, "(");
1178 for (i = 1; i < pos; i++) {
1179 value_print(stderr, P_VALUE_FMT, context[i]);
1180 fprintf(stderr, ",");
1181 }
1182 value_print(stderr, P_VALUE_FMT, k);
1183 fprintf(stderr, ")\n");
1184 }
1185 }
1186 #endif
1187
1188 value_set_si(context[pos], 0);
1189 if (value_lt(UB, LB)) {
1190 value_clear(LB);
1191 value_clear(UB);
1192 value_set_si(*res, 0);
1193 return;
1194 }
1195 if (!P->next) {
1196 // last polyhedron to scan, just return nb iterations
1197 value_subtract(LB, UB, LB);
1198 value_add_int(LB, LB, 1);
1199 value_assign(*res, LB);
1200 value_clear(LB);
1201 value_clear(UB);
1202 return;
1203 }
1204
1205 /*-----------------------------------------------------------------*/
1206 /* Optimization idea */
1207 /* If inner loops are not a function of k (the current index) */
1208 /* i.e. if P->Constraint[i][pos]==0 for all P following this and */
1209 /* for all i, */
1210 /* Then CNT = (UB-LB+1)*count_points(pos+1, P->next, context) */
1211 /* (skip the for loop) */
1212 /*-----------------------------------------------------------------*/
1213
1214 value_init(c);
1215 value_set_si(*res, 0);
1216 // iterate on LB -> UB
1217 for(; value_le(LB, UB); value_increment(LB, LB)) {
1218 /* Insert LB in context */
1219 value_assign(context[pos], LB);
1220 count_points(pos + 1, P->next, context, &c);
1221 if (value_notmone_p(c))
1222 value_addto(*res, *res, c);
1223 else {
1224 value_set_si(*res, -1);
1225 break;
1226 }
1227 }
1228 value_clear(c);
1229
1230#ifdef EDEBUG11
1231 fprintf(stderr, "%d\n", CNT);
1232#endif
1233
1234 /* Reset context */
1235 value_set_si(context[pos], 0);
1236 value_clear(LB);
1237 value_clear(UB);
1238 return;
1239} /* count_points */
1240
1241/*-------------------------------------------------------------------*/
1242/* enode *P_Enum(L, LQ, context, pos, nb_param, dim, lcm,param_name) */
1243/* L : list of polyhedra for the loop nest */
1244/* LQ : list of polyhedra for the parameter loop nest */
1245/* pos : 1..nb_param, position of the parameter */
1246/* nb_param : number of parameters total */
1247/* dim : total dimension of the polyhedron, param incl. */
1248/* lcm : denominator array [0..dim-1] of the polyhedron */
1249/* param_name : name of the parameters */
1250/* Returns an enode tree representing the pseudo polynomial */
1251/* expression for the enumeration of the polyhedron. */
1252/* A recursive procedure. */
1253/*-------------------------------------------------------------------*/
1254static enode *P_Enum(Polyhedron *L, Polyhedron *LQ, Value *context, int pos,
1255 int nb_param, int dim, Value *lcm,
1256 char **param_name) {
1257 enode *res, *B, *C;
1258 int hdim, i, j, rank, flag;
1259 Value n, g, nLB, nUB, nlcm, noff, nexp, k1, nm, hdv, k, lcm_copy;
1260 Value tmp;
1261 Matrix *A;
1262
1263#ifdef EDEBUG
1264 fprintf(stderr, "-------------------- begin P_Enum -------------------\n");
1265 fprintf(stderr, "Calling P_Enum with pos = %d\n", pos);
1266#endif
1267
1268 /* Initialize all the 'Value' variables */
1269 value_init(n);
1270 value_init(g);
1271 value_init(nLB);
1272 value_init(nUB);
1273 value_init(nlcm);
1274 value_init(noff);
1275 value_init(nexp);
1276 value_init(k1);
1277 value_init(nm);
1278 value_init(hdv);
1279 value_init(k);
1280 value_init(tmp);
1281 value_init(lcm_copy);
1282
1283 if (value_zero_p(lcm[pos - 1])) {
1284 hdim = 1;
1285 value_set_si(lcm_copy, 1);
1286 } else {
1287 /* hdim is the degree of the polynomial + 1 */
1288 hdim = dim - nb_param + 1; /* homogenous dim w/o parameters */
1289 value_assign(lcm_copy, lcm[pos - 1]);
1290 }
1291
1292 /* code to limit generation of equations to valid parameters only */
1293 /*----------------------------------------------------------------*/
1294 flag = lower_upper_bounds(pos, LQ, &context[dim - nb_param], &nLB, &nUB);
1295 if (flag & LB_INFINITY) {
1296 if (!(flag & UB_INFINITY)) {
1297
1298 /* Only an upper limit: set lower limit */
1299 /* Compute nLB such that (nUB-nLB+1) >= (hdim*lcm) */
1300 value_sub_int(nLB, nUB, 1);
1301 value_set_si(hdv, hdim);
1302 value_multiply(tmp, hdv, lcm_copy);
1303 value_subtract(nLB, nLB, tmp);
1304 if (value_pos_p(nLB))
1305 value_set_si(nLB, 0);
1306 } else {
1307 value_set_si(nLB, 0);
1308
1309 /* No upper nor lower limit: set lower limit to 0 */
1310 value_set_si(hdv, hdim);
1311 value_multiply(nUB, hdv, lcm_copy);
1312 value_add_int(nUB, nUB, 1);
1313 }
1314 }
1315
1316 /* if (nUB-nLB+1) < (hdim*lcm) then we have more unknowns than equations */
1317 /* We can: 1. Find more equations by changing the context parameters, or */
1318 /* 2. Assign extra unknowns values in such a way as to simplify result. */
1319 /* Think about ways to scan parameter space to get as much info out of it*/
1320 /* as possible. */
1321
1322#ifdef REDUCE_DEGREE
1323 if (pos == 1 && (flag & UB_INFINITY) == 0) {
1324 /* only for finite upper bound on first parameter */
1325 /* NOTE: only first parameter because subsequent parameters may
1326 be artificially limited by the choice of the first parameter */
1327
1328#ifdef EDEBUG
1329 fprintf(stderr, "*************** n **********\n");
1330 value_print(stderr, VALUE_FMT, n);
1331 fprintf(stderr, "\n");
1332#endif
1333
1334 value_subtract(n, nUB, nLB);
1336
1337#ifdef EDEBUG
1338 value_print(stderr, VALUE_FMT, n);
1339 fprintf(stderr, "\n*************** n ************\n");
1340#endif
1341
1342 /* Total number of samples>0 */
1343 if (value_neg_p(n))
1344 i = 0;
1345 else {
1346 value_modulus(tmp, n, lcm_copy);
1347 if (value_notzero_p(tmp)) {
1348 value_division(tmp, n, lcm_copy);
1349 value_increment(tmp, tmp);
1350 i = VALUE_TO_INT(tmp);
1351 } else {
1352 value_division(tmp, n, lcm_copy);
1353 i = VALUE_TO_INT(tmp); /* ceiling of n/lcm */
1354 }
1355 }
1356
1357#ifdef EDEBUG
1358 value_print(stderr, VALUE_FMT, n);
1359 fprintf(stderr, "\n*************** n ************\n");
1360#endif
1361
1362 /* Reduce degree of polynomial based on number of sample points */
1363 if (i < hdim) {
1364 hdim = i;
1365
1366#ifdef EDEBUG4
1367 fprintf(stdout, "Parameter #%d: LB=", pos);
1368 value_print(stdout, VALUE_FMT, nLB);
1369 fprintf(stdout, " UB=");
1370 value_print(stdout, VALUE_FMT, nUB);
1371 fprintf(stdout, " lcm=");
1372 value_print(stdout, VALUE_FMT, lcm_copy);
1373 fprintf(stdout, " degree reduced to %d\n", hdim - 1);
1374#endif
1375 }
1376 }
1377#endif /* REDUCE_DEGREE */
1378
1379 /* hdim is now set */
1380 /* allocate result structure */
1381 res = new_enode(polynomial, hdim, pos);
1382 for (i = 0; i < hdim; i++) {
1383 int l;
1384 l = VALUE_TO_INT(lcm_copy);
1385 res->arr[i].x.p = new_enode(periodic, l, pos);
1386 }
1387
1388 /* Utility arrays */
1389 A = Matrix_Alloc(hdim, 2 * hdim + 1); /* used for Gauss */
1390 B = new_enode(evector, hdim, 0);
1391 C = new_enode(evector, hdim, 0);
1392
1393 /* We'll create these again when we need them */
1394 for (j = 0; j < hdim; ++j)
1395 free_evalue_refs(&C->arr[j]);
1396
1397 /*----------------------------------------------------------------*/
1398 /* */
1399 /* 0<-----+---k---------> */
1400 /* |---------noff----------------->-nlcm->-------lcm----> */
1401 /* |--- . . . -----|--------------|------+-------|------+-------|-*/
1402 /* 0 (q-1)*lcm q*lcm | (q+1)*lcm | */
1403 /* nLB nLB+lcm */
1404 /* */
1405 /*----------------------------------------------------------------*/
1406 if (value_neg_p(nLB)) {
1407 value_modulus(nlcm, nLB, lcm_copy);
1408 value_addto(nlcm, nlcm, lcm_copy);
1409 } else {
1410 value_modulus(nlcm, nLB, lcm_copy);
1411 }
1412
1413 /* noff is a multiple of lcm */
1414 value_subtract(noff, nLB, nlcm);
1415 value_addto(tmp, lcm_copy, nlcm);
1416 for (value_assign(k, nlcm); value_lt(k, tmp);) {
1417
1418#ifdef EDEBUG
1419 fprintf(stderr, "Finding ");
1420 value_print(stderr, VALUE_FMT, k);
1421 fprintf(stderr, "-th elements of periodic coefficients\n");
1422#endif
1423
1424 value_set_si(hdv, hdim);
1425 value_multiply(nm, hdv, lcm_copy);
1426 value_addto(nm, nm, nLB);
1427 i = 0;
1428 for (value_addto(n, k, noff); value_lt(n, nm);
1429 value_addto(n, n, lcm_copy), i++) {
1430
1431 /* n == i*lcm + k + noff; */
1432 /* nlcm <= k < nlcm+lcm */
1433 /* n mod lcm == k1 */
1434
1435#ifdef ALL_OVERFLOW_WARNINGS
1436 if (((flag & UB_INFINITY) == 0) && value_gt(n, nUB)) {
1437 fprintf(stdout, "Domain Overflow: Parameter #%d:", pos);
1438 fprintf(stdout, "nLB=");
1439 value_print(stdout, VALUE_FMT, nLB);
1440 fprintf(stdout, " n=");
1441 value_print(stdout, VALUE_FMT, n);
1442 fprintf(stdout, " nUB=");
1443 value_print(stdout, VALUE_FMT, nUB);
1444 fprintf(stdout, "\n");
1445 }
1446#else
1447 if (overflow_warning_flag && ((flag & UB_INFINITY) == 0) &&
1448 value_gt(n, nUB)) {
1449 fprintf(stdout, "\nWARNING: Parameter Domain Overflow.");
1450 fprintf(stdout, " Result may be incorrect on this domain.\n");
1452 }
1453#endif
1454
1455 /* Set parameter to n */
1456 value_assign(context[dim - nb_param + pos], n);
1457
1458#ifdef EDEBUG1
1459 if (param_name) {
1460 fprintf(stderr, "%s = ", param_name[pos - 1]);
1461 value_print(stderr, VALUE_FMT, n);
1462 fprintf(stderr, " (hdim=%d, lcm[%d]=", hdim, pos - 1);
1463 value_print(stderr, VALUE_FMT, lcm_copy);
1464 fprintf(stderr, ")\n");
1465 } else {
1466 fprintf(stderr, "P%d = ", pos);
1467 value_print(stderr, VALUE_FMT, n);
1468 fprintf(stderr, " (hdim=%d, lcm[%d]=", hdim, pos - 1);
1469 value_print(stderr, VALUE_FMT, lcm_copy);
1470 fprintf(stderr, ")\n");
1471 }
1472#endif
1473
1474 /* Setup B vector */
1475 if (pos == nb_param) {
1476
1477#ifdef EDEBUG
1478 fprintf(stderr, "Yes\n");
1479#endif
1480
1481 /* call count */
1482 /* count can only be called when the context is fully specified */
1483 value_set_si(B->arr[i].d, 1);
1484 value_init(B->arr[i].x.n);
1485 count_points(1, L, context, &B->arr[i].x.n);
1486
1487#ifdef EDEBUG3
1488 for (j = 1; j < pos; j++)
1489 fputs(" ", stdout);
1490 fprintf(stdout, "E(");
1491 for (j = 1; j < nb_param; j++) {
1492 value_print(stdout, VALUE_FMT, context[dim - nb_param + j]);
1493 fprintf(stdout, ",");
1494 }
1495 value_print(stdout, VALUE_FMT, n);
1496 fprintf(stdout, ") = ");
1497 value_print(stdout, VALUE_FMT, B->arr[i].x.n);
1498 fprintf(stdout, " =");
1499#endif
1500
1501 }
1502 else {
1503 /* count is a function of other parameters */
1504 /* call P_Enum recursively */
1505 value_set_si(B->arr[i].d, 0);
1506 B->arr[i].x.p = P_Enum(L, LQ->next, context, pos + 1, nb_param, dim,
1507 lcm, param_name);
1508
1509#ifdef EDEBUG3
1510 if (param_name) {
1511 for (j = 1; j < pos; j++)
1512 fputs(" ", stdout);
1513 fprintf(stdout, "E(");
1514 for (j = 1; j <= pos; j++) {
1515 value_print(stdout, VALUE_FMT, context[dim - nb_param + j]);
1516 fprintf(stdout, ",");
1517 }
1518 for (j = pos + 1; j < nb_param; j++)
1519 fprintf(stdout, "%s,", param_name[j]);
1520 fprintf(stdout, "%s) = ", param_name[j]);
1521 print_enode(stdout, B->arr[i].x.p, param_name);
1522 fprintf(stdout, " =");
1523 }
1524#endif
1525 }
1526
1527 /* Create i-th equation*/
1528 /* K_0 + K_1 * n**1 + ... + K_dim * n**dim | Identity Matrix */
1529
1530 value_set_si(A->p[i][0], 0); /* status bit = equality */
1531 value_set_si(nexp, 1);
1532 for (j = 1; j <= hdim; j++) {
1533 value_assign(A->p[i][j], nexp);
1534 value_set_si(A->p[i][j + hdim], 0);
1535
1536#ifdef EDEBUG3
1537 fprintf(stdout, " + ");
1538 value_print(stdout, VALUE_FMT, nexp);
1539 fprintf(stdout, " c%d", j);
1540#endif
1541 value_multiply(nexp, nexp, n);
1542 }
1543
1544#ifdef EDEBUG3
1545 fprintf(stdout, "\n");
1546#endif
1547
1548 value_set_si(A->p[i][i + 1 + hdim], 1);
1549 }
1550
1551 /* Assertion check */
1552 if (i != hdim)
1553 fprintf(stderr, "P_Enum: ?expecting i==hdim\n");
1554
1555#ifdef EDEBUG
1556 if (param_name) {
1557 fprintf(stderr, "B (enode) =\n");
1558 print_enode(stderr, B, param_name);
1559 }
1560 fprintf(stderr, "A (Before Gauss) =\n");
1561 Matrix_Print(stderr, P_VALUE_FMT, A);
1562#endif
1563
1564 /* Solve hdim (=dim+1) equations with hdim unknowns, result in CNT */
1565 rank = Gauss(A, hdim, 2 * hdim);
1566
1567#ifdef EDEBUG
1568 fprintf(stderr, "A (After Gauss) =\n");
1569 Matrix_Print(stderr, P_VALUE_FMT, A);
1570#endif
1571
1572 /* Assertion check */
1573 if (rank != hdim) {
1574 fprintf(stderr, "P_Enum: ?expecting rank==hdim\n");
1575 }
1576
1577 /* if (rank < hdim) then set the last hdim-rank coefficients to ? */
1578 /* if (rank == 0) then set all coefficients to 0 */
1579 /* copy result as k1-th element of periodic numbers */
1580 if (value_lt(k, lcm_copy))
1581 value_assign(k1, k);
1582 else
1583 value_subtract(k1, k, lcm_copy);
1584
1585 for (i = 0; i < rank; i++) {
1586
1587 /* Set up coefficient vector C from i-th row of inverted matrix */
1588 for (j = 0; j < rank; j++) {
1589 value_gcd(g, A->p[i][i + 1], A->p[i][j + 1 + hdim]);
1590 value_init(C->arr[j].d);
1591 value_divexact(C->arr[j].d, A->p[i][i + 1], g);
1592 value_init(C->arr[j].x.n);
1593 value_divexact(C->arr[j].x.n, A->p[i][j + 1 + hdim], g);
1594 }
1595
1596#ifdef EDEBUG
1597 if (param_name) {
1598 fprintf(stderr, "C (enode) =\n");
1599 print_enode(stderr, C, param_name);
1600 }
1601#endif
1602
1603 /* The i-th enode is the lcm-periodic coefficient of term n**i */
1604 edot(B, C, &(res->arr[i].x.p->arr[VALUE_TO_INT(k1)]));
1605
1606#ifdef EDEBUG
1607 if (param_name) {
1608 fprintf(stderr, "B.C (evalue)=\n");
1609 print_evalue(stderr, &(res->arr[i].x.p->arr[VALUE_TO_INT(k1)]),
1610 param_name);
1611 fprintf(stderr, "\n");
1612 }
1613#endif
1614
1615 for (j = 0; j < rank; ++j)
1616 free_evalue_refs(&C->arr[j]);
1617 }
1618 value_addto(tmp, lcm_copy, nlcm);
1619
1620 value_increment(k, k);
1621 for (i = 0; i < hdim; ++i) {
1622 free_evalue_refs(&B->arr[i]);
1623 if (value_lt(k, tmp))
1624 value_init(B->arr[i].d);
1625 }
1626 }
1627
1628#ifdef EDEBUG
1629 if (param_name) {
1630 fprintf(stderr, "res (enode) =\n");
1631 print_enode(stderr, res, param_name);
1632 }
1633 fprintf(stderr, "-------------------- end P_Enum -----------------------\n");
1634#endif
1635
1636 /* Reset context */
1637 value_set_si(context[dim - nb_param + pos], 0);
1638
1639 /* Release memory */
1640 Matrix_Free(A);
1641 free(B);
1642 free(C);
1643
1644 /* Clear all the 'Value' variables */
1645 value_clear(n);
1646 value_clear(g);
1647 value_clear(nLB);
1648 value_clear(nUB);
1649 value_clear(nlcm);
1650 value_clear(noff);
1651 value_clear(nexp);
1652 value_clear(k1);
1653 value_clear(nm);
1654 value_clear(hdv);
1655 value_clear(k);
1656 value_clear(tmp);
1657 value_clear(lcm_copy);
1658 return res;
1659} /* P_Enum */
1660
1661/*----------------------------------------------------------------*/
1662/* Scan_Vertices(PP, Q, CT) */
1663/* PP : ParamPolyhedron */
1664/* Q : Domain */
1665/* CT : Context transformation matrix */
1666/* lcm : lcm array (output) */
1667/* nbp : number of parameters */
1668/* param_name : name of the parameters */
1669/*----------------------------------------------------------------*/
1671 Value *lcm, int nbp, char **param_name) {
1672 Param_Vertices *V;
1673 int i, j, ix, l, np;
1674 unsigned bx;
1675 Value k, m1;
1676
1677 /* Compute the denominator of P */
1678 /* lcm = Least Common Multiple of the denominators of the vertices of P */
1679 /* and print the vertices */
1680
1681 value_init(k);
1682 value_init(m1);
1683 for (np = 0; np < nbp; np++)
1684 value_set_si(lcm[np], 0);
1685
1686 if (param_name)
1687 fprintf(stdout, "Vertices:\n");
1688
1689 for (i = 0, ix = 0, bx = MSB, V = PP->V; V && i < PP->nbV; i++, V = V->next) {
1690 if (Q->F[ix] & bx) {
1691 if (param_name) {
1692 if (CT) {
1693 Matrix *v;
1694 v = VertexCT(V->Vertex, CT);
1695 Print_Vertex(stdout, v, param_name);
1696 Matrix_Free(v);
1697 } else
1698 Print_Vertex(stdout, V->Vertex, param_name);
1699 fprintf(stdout, "\n");
1700 }
1701
1702 for (j = 0; j < V->Vertex->NbRows; j++) {
1703 /* A matrix */
1704 for (l = 0; l < V->Vertex->NbColumns - 1; l++) {
1705 if (value_notzero_p(V->Vertex->p[j][l])) {
1706 value_gcd(m1, V->Vertex->p[j][V->Vertex->NbColumns - 1],
1707 V->Vertex->p[j][l]);
1708 value_divexact(k, V->Vertex->p[j][V->Vertex->NbColumns - 1], m1);
1709 if (value_notzero_p(lcm[l])) {
1710 /* lcm[l] = lcm[l] * k / gcd(k,lcm[l]) */
1711 if (value_notzero_p(k) && value_notone_p(k)) {
1712 value_gcd(m1, lcm[l], k);
1713 value_divexact(k, k, m1);
1714 value_multiply(lcm[l], lcm[l], k);
1715 }
1716 } else {
1717 value_assign(lcm[l], k);
1718 }
1719 }
1720 }
1721 }
1722 }
1723 NEXT(ix, bx);
1724 }
1725 value_clear(k);
1726 value_clear(m1);
1727} /* Scan_Vertices */
1728
1729/**
1730
1731Procedure to count points in a non-parameterized polytope.
1732
1733@param P Polyhedron to count
1734@param C Parameter Context domain
1735@param CT Matrix to transform context to original
1736@param CEq additionnal equalities in context
1737@param MAXRAYS workspace size
1738@param param_name parameter names
1739
1740*/
1742 Polyhedron *CEq, unsigned MAXRAYS,
1743 char **param_name) {
1744 Polyhedron *L;
1745 Enumeration *res;
1746 Vector *context;
1747 int hdim = P->Dimension + 1;
1748 int r, i;
1749
1750 /* Create a context vector size dim+2 */
1751 context = Vector_Alloc((hdim + 1));
1752
1753 res = (Enumeration *)malloc(sizeof(Enumeration));
1754 res->next = NULL;
1755 res->ValidityDomain = Universe_Polyhedron(0); /* no parameters */
1756 value_init(res->EP.d);
1757 value_set_si(res->EP.d, 0);
1759
1760#ifdef EDEBUG2
1761 fprintf(stderr, "L = \n");
1762 Polyhedron_Print(stderr, P_VALUE_FMT, L);
1763#endif
1764
1765 if (CT) {
1766 Polyhedron *Dt;
1767
1768 /* Add parameters to validity domain */
1771 res->ValidityDomain = DomainIntersection(Dt, CEq, MAXRAYS);
1772 Polyhedron_Free(Dt);
1773 }
1774
1775 if (param_name) {
1776 fprintf(stdout, "---------------------------------------\n");
1777 fprintf(stdout, "Domain:\n");
1778 Print_Domain(stdout, res->ValidityDomain, param_name);
1779
1780 /* Print the vertices */
1781 printf("Vertices:\n");
1782 for (r = 0; r < P->NbRays; ++r) {
1783 if (value_zero_p(P->Ray[r][0]))
1784 printf("(line) ");
1785 printf("[");
1786 if (P->Dimension > 0)
1787 value_print(stdout, P_VALUE_FMT, P->Ray[r][1]);
1788 for (i = 1; i < P->Dimension; i++) {
1789 printf(", ");
1790 value_print(stdout, P_VALUE_FMT, P->Ray[r][i + 1]);
1791 }
1792 printf("]");
1793 if (value_notone_p(P->Ray[r][P->Dimension + 1])) {
1794 printf("/");
1795 value_print(stdout, P_VALUE_FMT, P->Ray[r][P->Dimension + 1]);
1796 }
1797 printf("\n");
1798 }
1799 }
1800
1801 res->EP.x.p = new_enode(polynomial, 1, 0);
1802 ;
1803 value_set_si(res->EP.x.p->arr[0].d, 1);
1804 value_init(res->EP.x.p->arr[0].x.n);
1805
1806 if (emptyQ(P)) {
1807 value_set_si(res->EP.x.p->arr[0].x.n, 0);
1808 } else if (!L) {
1809 /* Non-empty zero-dimensional domain */
1810 value_set_si(res->EP.x.p->arr[0].x.n, 1);
1811 } else {
1813 fprintf(stderr, "Enumerate: arithmetic overflow error.\n");
1814 fprintf(stderr, "You should rebuild PolyLib using GNU-MP"
1815 " or increasing the size of integers.\n");
1818 }
1819 TRY {
1820
1821 Vector_Set(context->p, 0, (hdim + 1));
1822
1823 /* Set context->p[hdim] = 1 (the constant) */
1824 value_set_si(context->p[hdim], 1);
1825 count_points(1, L, context->p, &res->EP.x.p->arr[0].x.n);
1827 }
1828 }
1829
1830 Domain_Free(L);
1831
1832 /* **USELESS, there are no references to parameters in res**
1833 if( CT )
1834 addeliminatedparams_evalue(&res->EP, CT);
1835 */
1836
1837 if (param_name) {
1838 fprintf(stdout, "\nEhrhart Polynomial:\n");
1839 print_evalue(stdout, &res->EP, param_name);
1840 fprintf(stdout, "\n");
1841 }
1842
1843 Vector_Free(context);
1844 return (res);
1845} /* Enumerate_NoParameters */
1846
1847/** Procedure to count points in a parameterized polytope.
1848
1849@param Pi Polyhedron to enumerate
1850@param C Context Domain
1851@param MAXRAYS size of workspace
1852@param param_name parameter names (array of strings), may be NULL
1853@return a list of validity domains + evalues EP
1854
1855*/
1857 unsigned MAXRAYS, char **param_name) {
1858 Polyhedron *L, *CQ, *CQ2, *LQ, *U, *CEq, *rVD, *P, *Ph = NULL;
1859 Matrix *CT;
1860 Param_Polyhedron *PP;
1861 Param_Domain *Q;
1862 int hdim, dim, nb_param, np;
1863 Vector *lcm, *m1, *context;
1864 Value hdv;
1865 Enumeration *en, *res;
1866
1868 MAXRAYS = 0;
1869
1874
1875 res = NULL;
1876 P = Pi;
1877
1878#ifdef EDEBUG2
1879 fprintf(stderr, "C = \n");
1880 Polyhedron_Print(stderr, P_VALUE_FMT, C);
1881 fprintf(stderr, "P = \n");
1882 Polyhedron_Print(stderr, P_VALUE_FMT, P);
1883#endif
1884
1885 hdim = P->Dimension + 1;
1886 dim = P->Dimension;
1887 nb_param = C->Dimension;
1888
1889 /* Don't call Polyhedron2Param_Domain if there are no parameters */
1890 if (nb_param == 0) {
1891
1892 return (Enumerate_NoParameters(P, C, NULL, NULL, MAXRAYS, param_name));
1893 }
1894 if (nb_param == dim) {
1895 res = (Enumeration *)malloc(sizeof(Enumeration));
1896 res->next = 0;
1898 value_init(res->EP.d);
1899 value_init(res->EP.x.n);
1900 value_set_si(res->EP.d, 1);
1901 value_set_si(res->EP.x.n, 1);
1902 if (param_name) {
1903 fprintf(stdout, "---------------------------------------\n");
1904 fprintf(stdout, "Domain:\n");
1905 Print_Domain(stdout, res->ValidityDomain, param_name);
1906 fprintf(stdout, "\nEhrhart Polynomial:\n");
1907 print_evalue(stdout, &res->EP, param_name);
1908 fprintf(stdout, "\n");
1909 }
1910 return res;
1911 }
1912 PP = Polyhedron2Param_SimplifiedDomain(&P, C, MAXRAYS, &CEq, &CT);
1913 if (!PP) {
1914 if (param_name)
1915 fprintf(stdout, "\nEhrhart Polynomial:\nNULL\n");
1916
1917 return (NULL);
1918 }
1919
1920 /* CT : transformation matrix to eliminate useless ("false") parameters */
1921 if (CT) {
1922 nb_param -= CT->NbColumns - CT->NbRows;
1923 dim -= CT->NbColumns - CT->NbRows;
1924 hdim -= CT->NbColumns - CT->NbRows;
1925
1926 /* Don't call Polyhedron2Param_Domain if there are no parameters */
1927 if (nb_param == 0) {
1928 res = Enumerate_NoParameters(P, C, CT, CEq, MAXRAYS, param_name);
1930 goto out;
1931 }
1932 }
1933
1934 /* get memory for vector of Values */
1935 // value_alloc()
1936 lcm = Vector_Alloc((nb_param + 1));
1937 m1 = Vector_Alloc((nb_param + 1));
1938 value_init(hdv);
1939
1940 for (Q = PP->D; Q; Q = Q->next) {
1941 int hom = 0;
1942 if (CT) {
1943 Polyhedron *Dt;
1944 CQ = Q->Domain;
1945 Dt = Polyhedron_Preimage(Q->Domain, CT, MAXRAYS);
1946 rVD = DomainIntersection(Dt, CEq, MAXRAYS);
1947
1948 /* if rVD is empty or too small in geometric dimension */
1949 if (!rVD || emptyQ(rVD) ||
1950 (rVD->Dimension - rVD->NbEq < Dt->Dimension - Dt->NbEq - CEq->NbEq)) {
1951 if (rVD)
1952 Polyhedron_Free(rVD);
1953 Polyhedron_Free(Dt);
1954 Polyhedron_Free(CQ);
1955 continue; /* empty validity domain */
1956 }
1957 Polyhedron_Free(Dt);
1958 } else
1959 rVD = CQ = Q->Domain;
1960 en = (Enumeration *)malloc(sizeof(Enumeration));
1961 en->next = res;
1962 res = en;
1963 res->ValidityDomain = rVD;
1964
1965 if (param_name) {
1966 fprintf(stdout, "---------------------------------------\n");
1967 fprintf(stdout, "Domain:\n");
1968
1969#ifdef EPRINT_ALL_VALIDITY_CONSTRAINTS
1970 Print_Domain(stdout, res->ValidityDomain, param_name);
1971#else
1972 {
1973 Polyhedron *VD;
1974 VD = DomainSimplify(res->ValidityDomain, C, MAXRAYS);
1975 Print_Domain(stdout, VD, param_name);
1976 Domain_Free(VD);
1977 }
1978#endif /* EPRINT_ALL_VALIDITY_CONSTRAINTS */
1979 }
1980
1982
1983 /* Scan the vertices and compute lcm */
1984 Scan_Vertices(PP, Q, CT, lcm->p, nb_param, param_name);
1985
1986#ifdef EDEBUG2
1987 fprintf(stderr, "Denominator = ");
1988 for (np = 0; np < nb_param; np++)
1989 value_print(stderr, P_VALUE_FMT, lcm->p[np]);
1990 fprintf(stderr, " and hdim == %d \n", hdim);
1991#endif
1992
1993#ifdef EDEBUG2
1994 fprintf(stderr, "CQ = \n");
1995 Polyhedron_Print(stderr, P_VALUE_FMT, CQ);
1996#endif
1997
1998 /* Before scanning, add constraints to ensure at least hdim*lcm->p */
1999 /* points in every dimension */
2000 value_set_si(hdv, hdim - nb_param);
2001
2002 for (np = 0; np < nb_param + 1; np++) {
2003 if (value_notzero_p(lcm->p[np]))
2004 value_multiply(m1->p[np], hdv, lcm->p[np]);
2005 else
2006 value_set_si(m1->p[np], 1);
2007 }
2008
2009#ifdef EDEBUG2
2010 fprintf(stderr, "m1->p == ");
2011 for (np = 0; np < nb_param; np++)
2012 value_print(stderr, P_VALUE_FMT, m1->p[np]);
2013 fprintf(stderr, "\n");
2014#endif
2015
2017 fprintf(stderr, "Enumerate: arithmetic overflow error.\n");
2018 CQ2 = NULL;
2019 }
2020 TRY {
2021 CQ2 = Polyhedron_Preprocess(CQ, m1->p, MAXRAYS);
2022
2023#ifdef EDEBUG2
2024 fprintf(stderr, "After preprocess, CQ2 = ");
2025 Polyhedron_Print(stderr, P_VALUE_FMT, CQ2);
2026#endif
2027
2029 }
2030
2031 /* Vin100, Feb 2001 */
2032 /* in case of degenerate, try to find a domain _containing_ CQ */
2033 if ((!CQ2 || emptyQ(CQ2)) && CQ->NbBid == 0) {
2034 int r;
2035
2036#ifdef EDEBUG2
2037 fprintf(stderr, "Trying to call Polyhedron_Preprocess2 : CQ = \n");
2038 Polyhedron_Print(stderr, P_VALUE_FMT, CQ);
2039#endif
2040
2041 /* Check if CQ is bounded */
2042 for (r = 0; r < CQ->NbRays; r++) {
2043 if (value_zero_p(CQ->Ray[r][0]) ||
2044 value_zero_p(CQ->Ray[r][CQ->Dimension + 1]))
2045 break;
2046 }
2047 if (r == CQ->NbRays) {
2048
2049 /* ok, CQ is bounded */
2050 /* now find if CQ is contained in a hypercube of size m1->p */
2051 CQ2 = Polyhedron_Preprocess2(CQ, m1->p, lcm->p, MAXRAYS);
2052 }
2053 }
2054
2055 if (!CQ2) {
2056 Polyhedron *tmp;
2057#ifdef EDEBUG2
2058 fprintf(stderr, "Homogenize.\n");
2059#endif
2060 hom = 1;
2061 tmp = homogenize(CQ, MAXRAYS);
2062 CQ2 = Polyhedron_Preprocess(tmp, m1->p, MAXRAYS);
2063 Polyhedron_Free(tmp);
2064 if (!Ph)
2065 Ph = homogenize(P, MAXRAYS);
2066 for (np = 0; np < nb_param + 1; np++)
2067 if (value_notzero_p(lcm->p[np]))
2068 value_addto(m1->p[np], m1->p[np], lcm->p[np]);
2069 }
2070
2071 if (!CQ2 || emptyQ(CQ2)) {
2072#ifdef EDEBUG2
2073 fprintf(stderr, "Degenerate.\n");
2074#endif
2075 fprintf(stdout, "Degenerate Domain. Can not continue.\n");
2076 value_init(res->EP.d);
2077 value_init(res->EP.x.n);
2078 value_set_si(res->EP.d, 1);
2079 value_set_si(res->EP.x.n, -1);
2080 } else {
2081
2082#ifdef EDEBUG2
2083 fprintf(stderr, "CQ2 = \n");
2084 Polyhedron_Print(stderr, P_VALUE_FMT, CQ2);
2085 if (!PolyhedronIncludes(CQ, CQ2))
2086 fprintf(stderr, "CQ does not include CQ2 !\n");
2087 else
2088 fprintf(stderr, "CQ includes CQ2.\n");
2089 if (!PolyhedronIncludes(res->ValidityDomain, CQ2))
2090 fprintf(stderr, "CQ2 is *not* included in validity domain !\n");
2091 else
2092 fprintf(stderr, "CQ2 is included in validity domain.\n");
2093#endif
2094
2095 /* L is used in counting the number of points in the base cases */
2096 L = Polyhedron_Scan(hom ? Ph : P, CQ2, MAXRAYS);
2097 U = Universe_Polyhedron(0);
2098
2099 /* LQ is used to scan the parameter space */
2100 LQ = Polyhedron_Scan(CQ2, U, MAXRAYS); /* bounds on parameters */
2101 Domain_Free(U);
2102 if (CT) /* we did compute another Q->Domain */
2103 Domain_Free(CQ);
2104
2105 /* Else, CQ was Q->Domain (used in res) */
2106 Domain_Free(CQ2);
2107
2108#ifdef EDEBUG2
2109 fprintf(stderr, "L = \n");
2110 Polyhedron_Print(stderr, P_VALUE_FMT, L);
2111 fprintf(stderr, "LQ = \n");
2112 Polyhedron_Print(stderr, P_VALUE_FMT, LQ);
2113#endif
2114#ifdef EDEBUG3
2115 fprintf(stdout, "\nSystem of Equations:\n");
2116#endif
2117
2118 value_init(res->EP.d);
2119 value_set_si(res->EP.d, 0);
2120
2121 /* Create a context vector size dim+2 */
2122 context = Vector_Alloc((hdim + 1 + hom));
2123 /* Set context[hdim] = 1 (the constant) */
2124 value_set_si(context->p[hdim + hom], 1);
2125
2127 fprintf(stderr, "Enumerate: arithmetic overflow error.\n");
2128 fprintf(stderr, "You should rebuild PolyLib using GNU-MP "
2129 "or increasing the size of integers.\n");
2132 }
2133 TRY {
2134 res->EP.x.p = P_Enum(L, LQ, context->p, 1, nb_param + hom, dim + hom,
2135 lcm->p, param_name);
2137 }
2138 if (hom)
2139 dehomogenize_evalue(&res->EP, nb_param + 1);
2140
2141 Vector_Free(context);
2142 Domain_Free(L);
2143 Domain_Free(LQ);
2144
2145#ifdef EDEBUG5
2146 if (param_name) {
2147 fprintf(stdout, "\nEhrhart Polynomial (before simplification):\n");
2148 print_evalue(stdout, &res->EP, param_name);
2149 }
2150#endif
2151
2152 /* Try to simplify the result */
2153 reduce_evalue(&res->EP);
2154
2155 /* Put back the original parameters into result */
2156 /* (equalities have been eliminated) */
2157 if (CT)
2158 addeliminatedparams_evalue(&res->EP, CT);
2159
2160 if (param_name) {
2161 fprintf(stdout, "\nEhrhart Polynomial:\n");
2162 print_evalue(stdout, &res->EP, param_name);
2163 fprintf(stdout, "\n");
2164 /* sometimes the final \n lacks (when a single constant is printed) */
2165 }
2166 }
2167 }
2168
2169 if (Ph)
2170 Polyhedron_Free(Ph);
2171 /* Clear all the 'Value' variables */
2172 value_clear(hdv);
2173 Vector_Free(lcm);
2174 Vector_Free(m1);
2175 /* We can't simply call Param_Polyhedron_Free because we've reused the domains
2176 */
2178 while (PP->D) {
2179 Q = PP->D;
2180 PP->D = PP->D->next;
2181 free(Q->F);
2182 free(Q);
2183 }
2184 free(PP);
2185
2186out:
2187 if (CEq)
2188 Polyhedron_Free(CEq);
2189 if (CT)
2190 Matrix_Free(CT);
2191 if (P != Pi)
2192 Polyhedron_Free(P);
2193
2194 return res;
2195} /* Polyhedron_Enumerate */
2196
2198 Enumeration *ee;
2199
2200 while (en) {
2201 free_evalue_refs(&(en->EP));
2203 ee = en->next;
2204 free(en);
2205 en = ee;
2206 }
2207}
2208
2209/* adds by B. Meister for Ehrhart Polynomial approximation */
2210
2211/**
2212 * Divides the evalue e by the integer n<br/>
2213 * recursive function<br/>
2214 * Warning : modifies e
2215 * @param e an evalue (to be divided by n)
2216 * @param n
2217 */
2218
2220 int i;
2221 Value gc;
2222 value_init(gc);
2223 if (value_zero_p(e->d)) {
2224 for (i = 0; i < e->x.p->size; i++) {
2225 evalue_div(&(e->x.p->arr[i]), n);
2226 }
2227 } else {
2228 value_multiply(e->d, e->d, n);
2229 /* simplify the new rational if needed */
2230 value_gcd(gc, e->x.n, e->d);
2231 if (value_notone_p(gc)) {
2232 value_divexact(e->d, e->d, gc);
2233 value_divexact(e->x.n, e->x.n, gc);
2234 }
2235 }
2236 value_clear(gc);
2237} /* evalue_div */
2238
2239/**
2240
2241Ehrhart_Quick_Apx_Full_Dim(P, C, MAXRAYS, param_names)
2242
2243Procedure to estimate the number of points in a parameterized polytope.
2244Returns a list of validity domains + evalues EP
2245B.M.
2246The most rough and quick approximation by variables expansion
2247Deals with the full-dimensional case.
2248@param Pi : Polyhedron to enumerate (approximatively)
2249@param C : Context Domain
2250@param MAXRAYS : size of workspace
2251@param param_name : names for the parameters (char strings)
2252
2253*/
2255 unsigned MAXRAYS,
2256 char **param_name) {
2257 Polyhedron *L, *CQ, *CQ2, *LQ, *U, *CEq, *rVD, *P;
2258 Matrix *CT;
2259 Param_Polyhedron *PP;
2260 Param_Domain *Q;
2261 int i, hdim, dim, nb_param, np;
2262 Vector *lcm, *m1, *context;
2263 Value hdv;
2264 Enumeration *en, *res;
2265 Value expansion_det;
2266 Polyhedron *Expanded;
2267
2268 res = NULL;
2269 P = Pi;
2270
2271#ifdef EDEBUG2
2272 fprintf(stderr, "C = \n");
2273 Polyhedron_Print(stderr, P_VALUE_FMT, C);
2274 fprintf(stderr, "P = \n");
2275 Polyhedron_Print(stderr, P_VALUE_FMT, P);
2276#endif
2277
2278 hdim = P->Dimension + 1;
2279 dim = P->Dimension;
2280 nb_param = C->Dimension;
2281
2282 /* Don't call Polyhedron2Param_Domain if there are no parameters */
2283 if (nb_param == 0) {
2284
2285 return (Enumerate_NoParameters(P, C, NULL, NULL, MAXRAYS, param_name));
2286 }
2287
2288#if EDEBUG2
2289 printf("Enumerating polyhedron : \n");
2290 Polyhedron_Print(stdout, P_VALUE_FMT, P);
2291#endif
2292
2293 PP = Polyhedron2Param_SimplifiedDomain(&P, C, MAXRAYS, &CEq, &CT);
2294 if (!PP) {
2295 if (param_name)
2296 fprintf(stdout, "\nEhrhart Polynomial:\nNULL\n");
2297
2298 return (NULL);
2299 }
2300
2301 /* CT : transformation matrix to eliminate useless ("false") parameters */
2302 if (CT) {
2303 nb_param -= CT->NbColumns - CT->NbRows;
2304 dim -= CT->NbColumns - CT->NbRows;
2305 hdim -= CT->NbColumns - CT->NbRows;
2306
2307 /* Don't call Polyhedron2Param_Domain if there are no parameters */
2308 if (nb_param == 0) {
2309 res = Enumerate_NoParameters(P, C, CT, CEq, MAXRAYS, param_name);
2310 if (P != Pi)
2311 Polyhedron_Free(P);
2312 return (res);
2313 }
2314 }
2315
2316 if (!PP->nbV)
2317 /* Leaks memory */
2318 return NULL;
2319
2320 /* get memory for Values */
2321 lcm = Vector_Alloc(nb_param);
2322 m1 = Vector_Alloc(nb_param);
2323 value_init(hdv);
2324 value_init(expansion_det);
2325
2326#if EDEBUG2
2327 Polyhedron_Print(stderr, P_VALUE_FMT, P);
2328#endif
2329
2330 Expanded = P;
2331 Param_Polyhedron_Scale_Integer(PP, &Expanded, &expansion_det, MAXRAYS);
2332
2333#if EDEBUG2
2334 Polyhedron_Print(stderr, P_VALUE_FMT, Expanded);
2335#endif
2336
2337 if (P != Expanded)
2338 Polyhedron_Free(P);
2339 P = Expanded;
2340
2341 /* formerly : Scan the vertices and compute lcm
2342 Scan_Vertices_Quick_Apx(PP,Q,CT,lcm,nb_param); */
2343 /* now : lcm = 1 (by construction) */
2344 /* OPT : A lot among what happens after this point can be simplified by
2345 knowing that lcm[i] = 1 for now, we just conservatively fool the rest of
2346 the function with lcm = 1 */
2347 for (i = 0; i < nb_param; i++)
2348 value_set_si(lcm->p[i], 1);
2349
2350 for (Q = PP->D; Q; Q = Q->next) {
2351 if (CT) {
2352 Polyhedron *Dt;
2353 CQ = Q->Domain;
2354 Dt = Polyhedron_Preimage(Q->Domain, CT, MAXRAYS);
2355 rVD = DomainIntersection(Dt, CEq, MAXRAYS);
2356
2357 /* if rVD is empty or too small in geometric dimension */
2358 if (!rVD || emptyQ(rVD) ||
2359 (rVD->Dimension - rVD->NbEq < Dt->Dimension - Dt->NbEq - CEq->NbEq)) {
2360 if (rVD)
2361 Polyhedron_Free(rVD);
2362 Polyhedron_Free(Dt);
2363 continue; /* empty validity domain */
2364 }
2365 Polyhedron_Free(Dt);
2366 } else
2367 rVD = CQ = Q->Domain;
2368 en = (Enumeration *)malloc(sizeof(Enumeration));
2369 en->next = res;
2370 res = en;
2371 res->ValidityDomain = rVD;
2372
2373 if (param_name) {
2374 fprintf(stdout, "---------------------------------------\n");
2375 fprintf(stdout, "Domain:\n");
2376
2377#ifdef EPRINT_ALL_VALIDITY_CONSTRAINTS
2378 Print_Domain(stdout, res->ValidityDomain, param_name);
2379#else
2380 {
2381 Polyhedron *VD;
2382 VD = DomainSimplify(res->ValidityDomain, C, MAXRAYS);
2383 Print_Domain(stdout, VD, param_name);
2384 Domain_Free(VD);
2385 }
2386#endif /* EPRINT_ALL_VALIDITY_CONSTRAINTS */
2387 }
2388
2390
2391#ifdef EDEBUG2
2392 fprintf(stderr, "Denominator = ");
2393 for (np = 0; np < nb_param; np++)
2394 value_print(stderr, P_VALUE_FMT, lcm->p[np]);
2395 fprintf(stderr, " and hdim == %d \n", hdim);
2396#endif
2397
2398#ifdef EDEBUG2
2399 fprintf(stderr, "CQ = \n");
2400 Polyhedron_Print(stderr, P_VALUE_FMT, CQ);
2401#endif
2402
2403 /* Before scanning, add constraints to ensure at least hdim*lcm->p */
2404 /* points in every dimension */
2405 value_set_si(hdv, hdim - nb_param);
2406
2407 for (np = 0; np < nb_param; np++) {
2408 if (value_notzero_p(lcm->p[np]))
2409 value_multiply(m1->p[np], hdv, lcm->p[np]);
2410 else
2411 value_set_si(m1->p[np], 1);
2412 }
2413
2414#ifdef EDEBUG2
2415 fprintf(stderr, "m1->p == ");
2416 for (np = 0; np < nb_param; np++)
2417 value_print(stderr, P_VALUE_FMT, m1->p[np]);
2418 fprintf(stderr, "\n");
2419#endif
2420
2422 fprintf(stderr, "Enumerate: arithmetic overflow error.\n");
2423 CQ2 = NULL;
2424 }
2425 TRY {
2426 CQ2 = Polyhedron_Preprocess(CQ, m1->p, MAXRAYS);
2427
2428#ifdef EDEBUG2
2429 fprintf(stderr, "After preprocess, CQ2 = ");
2430 Polyhedron_Print(stderr, P_VALUE_FMT, CQ2);
2431#endif
2432
2434 }
2435
2436 /* Vin100, Feb 2001 */
2437 /* in case of degenerate, try to find a domain _containing_ CQ */
2438 if ((!CQ2 || emptyQ(CQ2)) && CQ->NbBid == 0) {
2439 int r;
2440
2441#ifdef EDEBUG2
2442 fprintf(stderr, "Trying to call Polyhedron_Preprocess2 : CQ = \n");
2443 Polyhedron_Print(stderr, P_VALUE_FMT, CQ);
2444#endif
2445
2446 /* Check if CQ is bounded */
2447 for (r = 0; r < CQ->NbRays; r++) {
2448 if (value_zero_p(CQ->Ray[r][0]) ||
2449 value_zero_p(CQ->Ray[r][CQ->Dimension + 1]))
2450 break;
2451 }
2452 if (r == CQ->NbRays) {
2453
2454 /* ok, CQ is bounded */
2455 /* now find if CQ is contained in a hypercube of size m1->p */
2456 CQ2 = Polyhedron_Preprocess2(CQ, m1->p, lcm->p, MAXRAYS);
2457 }
2458 }
2459 if (!CQ2 || emptyQ(CQ2)) {
2460#ifdef EDEBUG2
2461 fprintf(stderr, "Degenerate.\n");
2462#endif
2463 fprintf(stdout, "Degenerate Domain. Can not continue.\n");
2464 value_init(res->EP.d);
2465 value_init(res->EP.x.n);
2466 value_set_si(res->EP.d, 1);
2467 value_set_si(res->EP.x.n, -1);
2468 } else {
2469
2470#ifdef EDEBUG2
2471 fprintf(stderr, "CQ2 = \n");
2472 Polyhedron_Print(stderr, P_VALUE_FMT, CQ2);
2473 if (!PolyhedronIncludes(CQ, CQ2))
2474 fprintf(stderr, "CQ does not include CQ2 !\n");
2475 else
2476 fprintf(stderr, "CQ includes CQ2.\n");
2477 if (!PolyhedronIncludes(res->ValidityDomain, CQ2))
2478 fprintf(stderr, "CQ2 is *not* included in validity domain !\n");
2479 else
2480 fprintf(stderr, "CQ2 is included in validity domain.\n");
2481#endif
2482
2483 /* L is used in counting the number of points in the base cases */
2484 L = Polyhedron_Scan(P, CQ, MAXRAYS);
2485 U = Universe_Polyhedron(0);
2486
2487 /* LQ is used to scan the parameter space */
2488 LQ = Polyhedron_Scan(CQ2, U, MAXRAYS); /* bounds on parameters */
2489 Domain_Free(U);
2490 if (CT) /* we did compute another Q->Domain */
2491 Domain_Free(CQ);
2492
2493 /* Else, CQ was Q->Domain (used in res) */
2494 Domain_Free(CQ2);
2495
2496#ifdef EDEBUG2
2497 fprintf(stderr, "L = \n");
2498 Polyhedron_Print(stderr, P_VALUE_FMT, L);
2499 fprintf(stderr, "LQ = \n");
2500 Polyhedron_Print(stderr, P_VALUE_FMT, LQ);
2501#endif
2502#ifdef EDEBUG3
2503 fprintf(stdout, "\nSystem of Equations:\n");
2504#endif
2505
2506 value_init(res->EP.d);
2507 value_set_si(res->EP.d, 0);
2508
2509 /* Create a context vector size dim+2 */
2510 context = Vector_Alloc(hdim + 1);
2511 /* Set context[hdim] = 1 (the constant) */
2512 value_set_si(context->p[hdim], 1);
2513
2515 fprintf(stderr, "Enumerate: arithmetic overflow error.\n");
2516 fprintf(stderr, "You should rebuild PolyLib using GNU-MP "
2517 "or increasing the size of integers.\n");
2520 }
2521 TRY {
2522 res->EP.x.p = P_Enum(L, LQ, context->p, 1, nb_param, dim, lcm->p, param_name);
2524 }
2525
2526 Vector_Free(context);
2527 Domain_Free(L);
2528 Domain_Free(LQ);
2529
2530#ifdef EDEBUG5
2531 if (param_name) {
2532 fprintf(stdout, "\nEhrhart Polynomial (before simplification):\n");
2533 print_evalue(stdout, &res->EP, param_name);
2534 }
2535
2536 /* BM: divide EP by denom_det, the expansion factor */
2537 fprintf(stdout, "\nEhrhart Polynomial (before division):\n");
2538 print_evalue(stdout, &(res->EP), param_name);
2539#endif
2540
2541 evalue_div(&(res->EP), expansion_det);
2542
2543 /* Try to simplify the result */
2544 reduce_evalue(&res->EP);
2545
2546 /* Put back the original parameters into result */
2547 /* (equalities have been eliminated) */
2548 if (CT)
2549 addeliminatedparams_evalue(&res->EP, CT);
2550
2551 if (param_name) {
2552 fprintf(stdout, "\nEhrhart Polynomial:\n");
2553 print_evalue(stdout, &res->EP, param_name);
2554 fprintf(stdout, "\n");
2555 /* sometimes the final \n lacks (when a single constant is printed)
2556 */
2557 }
2558 }
2559 }
2560 value_clear(expansion_det);
2561
2562 if (P != Pi)
2563 Polyhedron_Free(P);
2564 /* Clear all the 'Value' variables */
2565 for (np = 0; np < nb_param; np++) {
2566 value_clear(lcm->p[np]);
2567 value_clear(m1->p[np]);
2568 }
2569 value_clear(hdv);
2570
2571 return res;
2572} /* Ehrhart_Quick_Apx_Full_Dim */
2573
2574/**
2575 * Computes the approximation of the Ehrhart polynomial of a polyhedron
2576 * (implicit form -> matrix), treating the non-full-dimensional case.
2577 * @param M a polyhedron under implicit form
2578 * @param C M's context under implicit form
2579 * @param Validity_Lattice a pointer to the parameter's validity lattice
2580 * @param MAXRAYS the needed "working space" for other polylib functions used
2581 * here
2582 * @param param_name the names of the parameters,
2583 */
2585 unsigned maxRays) {
2586 /* char ** param_name) {*/
2587
2588 /* 0- compute a full-dimensional polyhedron with the same number of points,
2589 and its parameter's validity lattice */
2590 Matrix *M_full;
2591 Polyhedron *P, *PC;
2592 Enumeration *en;
2593
2594 M_full = full_dimensionize(M, C->NbColumns - 2, Validity_Lattice);
2595 /* 1- apply the same tranformation to the context that what has been applied
2596 to the parameters space of the polyhedron. */
2597 mpolyhedron_compress_last_vars(C, *Validity_Lattice);
2598 show_matrix(M_full);
2599 P = Constraints2Polyhedron(M_full, maxRays);
2601 Matrix_Free(M_full);
2602 /* compute the Ehrhart polynomial of the "equivalent" polyhedron */
2603 en = Ehrhart_Quick_Apx_Full_Dim(P, PC, maxRays, NULL);
2604
2605 /* clean up */
2606 Polyhedron_Free(P);
2607 Polyhedron_Free(PC);
2608 return en;
2609} /* Ehrhart_Quick_Apx */
2610
2611/**
2612 * Computes the approximation of the Ehrhart polynomial of a polyhedron
2613 * (implicit form -> matrix), treating the non-full-dimensional case. If there
2614 * are some equalities involving only parameters, these are used to eliminate
2615 * useless parameters.
2616 * @param M a polyhedron under implicit form
2617 * @param C M's context under implicit form
2618 * @param validityLattice a pointer to the parameter's validity lattice
2619 * (returned)
2620 * @param parmsEqualities Equalities involving only the parameters
2621 * @param maxRays the needed "working space" for other polylib functions used
2622 * here
2623 * @param elimParams array of the indices of the eliminated parameters
2624 * (returned)
2625 */
2627 Matrix **validityLattice,
2628 Matrix **parmEqualities,
2629 unsigned int **elimParms,
2630 unsigned maxRays) {
2631 Enumeration *EP;
2632 Matrix *Mp = Matrix_Copy(M);
2633 Matrix *Cp = Matrix_Copy(C);
2634 /* remove useless equalities involving only parameters, using these
2635 equalities to remove parameters. */
2636 (*parmEqualities) = Constraints_Remove_parm_eqs(&Mp, &Cp, 0, elimParms);
2637 if (Mp->NbRows >= 0) { /* if there is no contradiction */
2638 EP = Ehrhart_Quick_Apx(Mp, Cp, validityLattice, maxRays);
2639 return EP;
2640 } else {
2641 /* if there are contradictions, return a zero Ehrhart polynomial */
2642 return NULL;
2643 }
2644}
2645
2646/**
2647 * Returns the array of parameter names after some of them have been eliminated.
2648 * @param parmNames the initial names of the parameters
2649 * @param elimParms a list of parameters that have been eliminated from the
2650 * original parameters. The first element of this array is the number of
2651 * elements.
2652 * <p> Note: does not copy the parameters names themselves. </p>
2653 * @param nbParms the initial number of parameters
2654 */
2655char **parmsWithoutElim(char **parmNames,
2656 unsigned int const *elimParms,
2657 unsigned int nbParms) {
2658 int i = 0, k;
2659 int newParmNb = nbParms - elimParms[0];
2660 char **newParmNames = malloc(newParmNb * sizeof(char *));
2661 for (k = 1; k <= elimParms[0]; k++) {
2662 while (i != elimParms[k]) {
2663 newParmNames[i - k + 1] = parmNames[i];
2664 i++;
2665 }
2666 }
2667 return newParmNames;
2668}
2669
2670/**
2671 * returns a constant Ehrhart polynomial whose value is zero for any value of
2672 * the parameters.
2673 * @param nbParms the number of parameters, i.e., the number of arguments to
2674 * the Ehrhart polynomial
2675 */
2676Enumeration *Enumeration_zero(unsigned int nbParms, unsigned int maxRays) {
2677 Matrix *Mz = Matrix_Alloc(1, nbParms + 3);
2678 Polyhedron *emptyP;
2679 Polyhedron *universe;
2680 Enumeration *zero;
2681 /* 1- build an empty polyhedron with the right dimension */
2682 /* here we choose to take 2i = -1 */
2683 value_set_si(Mz->p[0][1], 2);
2684 value_set_si(Mz->p[0][nbParms + 2], 1);
2685 emptyP = Constraints2Polyhedron(Mz, maxRays);
2686 Matrix_Free(Mz);
2687 universe = Universe_Polyhedron(nbParms);
2688 zero = Polyhedron_Enumerate(emptyP, universe, maxRays, NULL);
2689 Polyhedron_Free(emptyP);
2690 Polyhedron_Free(universe);
2691 return zero;
2692} /* 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:574
#define value_oppose(ref, val)
Definition: arithmetique.h:555
#define value_sub_int(ref, val, vint)
Definition: arithmetique.h:548
#define value_gt(v1, v2)
Definition: arithmetique.h:507
#define VALUE_TO_INT(val)
Definition: arithmetique.h:304
#define value_le(v1, v2)
Definition: arithmetique.h:510
#define value_notzero_p(val)
Definition: arithmetique.h:579
#define value_divexact(ref, val1, val2)
Definition: arithmetique.h:551
#define value_gcd(ref, val1, val2)
Definition: arithmetique.h:559
#define value_notone_p(val)
Definition: arithmetique.h:581
#define value_one_p(val)
Definition: arithmetique.h:580
#define value_negz_p(val)
Definition: arithmetique.h:577
#define value_absolute(ref, val)
Definition: arithmetique.h:556
#define VALUE_FMT
Definition: arithmetique.h:295
#define value_add_int(ref, val, vint)
Definition: arithmetique.h:541
#define value_decrement(ref, val)
Definition: arithmetique.h:549
#define value_ne(v1, v2)
Definition: arithmetique.h:506
#define value_zero_p(val)
Definition: arithmetique.h:578
#define value_assign(v1, v2)
Definition: arithmetique.h:485
#define value_increment(ref, val)
Definition: arithmetique.h:543
int Value
Definition: arithmetique.h:294
#define value_set_si(val, i)
Definition: arithmetique.h:486
#define value_addmul(ref, val1, val2)
Definition: arithmetique.h:542
#define value_notmone_p(val)
Definition: arithmetique.h:583
#define value_clear(val)
Definition: arithmetique.h:488
#define value_division(ref, val1, val2)
Definition: arithmetique.h:550
#define value_multiply(ref, val1, val2)
Definition: arithmetique.h:546
#define value_print(Dst, fmt, val)
Definition: arithmetique.h:490
#define value_lt(v1, v2)
Definition: arithmetique.h:509
#define value_modulus(ref, val1, val2)
Definition: arithmetique.h:552
#define value_subtract(ref, val1, val2)
Definition: arithmetique.h:547
#define value_addto(ref, val1, val2)
Definition: arithmetique.h:540
#define value_ge(v1, v2)
Definition: arithmetique.h:508
#define value_neg_p(val)
Definition: arithmetique.h:575
#define value_init(val)
Definition: arithmetique.h:484
#define value_posz_p(val)
Definition: arithmetique.h:576
#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 * Ehrhart_Quick_Apx_Full_Dim(Polyhedron *Pi, Polyhedron *C, unsigned MAXRAYS, char **param_name)
Ehrhart_Quick_Apx_Full_Dim(P, C, MAXRAYS, param_names)
Definition: ehrhart.c:2254
char ** parmsWithoutElim(char **parmNames, unsigned int const *elimParms, unsigned int nbParms)
Returns the array of parameter names after some of them have been eliminated.
Definition: ehrhart.c:2655
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:2626
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:1052
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:2219
void print_evalue(FILE *DST, evalue *e, char **pname)
Definition: ehrhart.c:169
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:2676
static void emul(evalue *e1, evalue *e2, evalue *res)
multiplies two evalues and puts the result in res
Definition: ehrhart.c:344
Enumeration * Polyhedron_Enumerate(Polyhedron *Pi, Polyhedron *C, unsigned MAXRAYS, char **param_name)
Procedure to count points in a parameterized polytope.
Definition: ehrhart.c:1856
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:737
void free_evalue_refs(evalue *e)
releases all memory referenced by e.
Definition: ehrhart.c:115
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:883
#define MAXITER
This procedure finds an integer point contained in polyhedron D / first checks for positive values,...
Definition: ehrhart.c:623
static void addeliminatedparams_evalue(evalue *e, Matrix *CT)
Comments.
Definition: ehrhart.c:577
static void Scan_Vertices(Param_Polyhedron *PP, Param_Domain *Q, Matrix *CT, Value *lcm, int nbp, char **param_name)
Definition: ehrhart.c:1670
int overflow_warning_flag
Definition: ehrhart.c:74
enode * ecopy(enode *e)
Definition: ehrhart.c:144
void print_enode(FILE *DST, enode *p, char **pname)
prints the enode to DST
Definition: ehrhart.c:190
static enode * P_Enum(Polyhedron *L, Polyhedron *LQ, Value *context, int pos, int nb_param, int dim, Value *lcm, char **param_name)
Definition: ehrhart.c:1254
void count_points(int pos, Polyhedron *P, Value *context, Value *res)
PROCEDURES TO COMPUTE ENUMERATION.
Definition: ehrhart.c:1146
void reduce_evalue(evalue *e)
Definition: ehrhart.c:271
Enumeration * Enumerate_NoParameters(Polyhedron *P, Polyhedron *C, Matrix *CT, Polyhedron *CEq, unsigned MAXRAYS, char **param_name)
Procedure to count points in a non-parameterized polytope.
Definition: ehrhart.c:1741
void Enumeration_Free(Enumeration *en)
Definition: ehrhart.c:2197
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:2584
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:118
void Matrix_Free(Matrix *Mat)
Definition: matrix.c:69
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:2412
void Polyhedron_Free(Polyhedron *Pol)
Definition: polyhedron.c:1621
int Gauss(Matrix *Mat, int NbEq, int Dimension)
Definition: polyhedron.c:834
Polyhedron * Polyhedron_Scan(Polyhedron *D, Polyhedron *C, unsigned NbMaxRays)
Definition: polyhedron.c:3791
Polyhedron * Polyhedron_Preimage(Polyhedron *Pol, Matrix *Func, unsigned NbMaxRays)
Definition: polyhedron.c:4076
Polyhedron * DomainIntersection(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Definition: polyhedron.c:2648
Polyhedron * DomainSimplify(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Definition: polyhedron.c:3291
Polyhedron * Universe_Polyhedron(unsigned Dimension)
Definition: polyhedron.c:1761
int lower_upper_bounds(int pos, Polyhedron *P, Value *context, Value *LBp, Value *UBp)
Definition: polyhedron.c:3859
Polyhedron * Constraints2Polyhedron(Matrix *Constraints, unsigned NbMaxRays)
Given a matrix of constraints ('Constraints'), construct and return a polyhedron.
Definition: polyhedron.c:1912
Polyhedron * AddConstraints(Value *Con, unsigned NbConstraints, Polyhedron *Pol, unsigned NbMaxRays)
Definition: polyhedron.c:2311
void Polyhedron_Print(FILE *Dst, const char *Format, const Polyhedron *Pol)
Definition: polyhedron.c:1646
void Domain_Free(Polyhedron *Pol)
Definition: polyhedron.c:1633
#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:1565
static Matrix * Pi
Definition: polyparam.c:285
void Param_Polyhedron_Free(Param_Polyhedron *P)
Definition: polyparam.c:1877
void Print_Vertex(FILE *DST, Matrix *V, char **param_names)
Definition: polyparam.c:1585
void Param_Polyhedron_Scale_Integer(Param_Polyhedron *PP, Polyhedron **P, Value *det, unsigned MaxRays)
Definition: polyparam.c:1894
void Print_Domain(FILE *DST, Polyhedron *D, char **pname)
Definition: polyparam.c:1682
Matrix * VertexCT(Matrix *V, Matrix *CT)
Definition: polyparam.c:1653
static int n
Definition: polyparam.c:278
Param_Polyhedron * Polyhedron2Param_SimplifiedDomain(Polyhedron **Din, Polyhedron *Cin, int working_space, Polyhedron **CEq, Matrix **CT)
Definition: polyparam.c:1806
char s[128]
Definition: polytest.c:8
Definition: types.h:82
Value * p
Definition: types.h:84
struct _Param_Domain * next
Definition: types.h:157
Polyhedron * Domain
Definition: types.h:156
unsigned * F
Definition: types.h:155
Param_Vertices * V
Definition: types.h:162
Param_Domain * D
Definition: types.h:163
struct _Param_Vertex * next
Definition: types.h:151
Matrix * Vertex
Definition: types.h:145
Definition: types.h:202
int pos
Definition: types.h:205
evalue arr[1]
Definition: types.h:206
enode_type type
Definition: types.h:203
int size
Definition: types.h:204
Polyhedron * ValidityDomain
Definition: types.h:210
evalue EP
Definition: types.h:211
struct _enumeration * next
Definition: types.h:212
Definition: types.h:193
Value d
Definition: types.h:194
Definition: types.h:88
unsigned NbRows
Definition: types.h:89
Value ** p
Definition: types.h:90
unsigned NbColumns
Definition: types.h:89
Value * p_Init
Definition: types.h:91
Value ** Ray
Definition: types.h:112
unsigned Dimension
Definition: types.h:110
unsigned NbConstraints
Definition: types.h:110
unsigned NbRays
Definition: types.h:110
unsigned NbBid
Definition: types.h:110
struct polyhedron * next
Definition: types.h:115
Value ** Constraint
Definition: types.h:111
unsigned NbEq
Definition: types.h:110
#define maxRays
enode_type
Definition: types.h:185
@ periodic
Definition: types.h:185
@ polynomial
Definition: types.h:185
@ evector
Definition: types.h:185
#define MSB
Definition: types.h:57
#define emptyQ(P)
Definition: types.h:134
#define POL_ISSET(flags, f)
Definition: types.h:77
#define NEXT(j, b)
Definition: types.h:63
#define UB_INFINITY
Definition: types.h:53
#define POL_NO_DUAL
Definition: types.h:75
#define LB_INFINITY
Definition: types.h:52
#define P_VALUE_FMT
Definition: types.h:42
void Vector_Free(Vector *vector)
Definition: vector.c:187
void Vector_Set(Value *p, int n, unsigned length)
Definition: vector.c:248
void Vector_Combine(Value *p1, Value *p2, Value *p3, Value lambda, Value mu, unsigned length)
Definition: vector.c:455
void Vector_Normalize(Value *p, unsigned length)
Definition: vector.c:588
Vector * Vector_Alloc(unsigned length)
Definition: vector.c:134
void Vector_Copy(Value *p1, Value *p2, unsigned length)
Definition: vector.c:276
Value min
Definition: verif_ehrhart.c:43
#define MAXRAYS
Definition: verif_ehrhart.c:20