update pet for representing schedule as schedule tree
[barvinok/uuh.git] / evalue.c
blobf692ff7f41033ba1bb3a7673f39a3f9771855823
1 /***********************************************************************/
2 /* copyright 1997, Doran Wilde */
3 /* copyright 1997-2000, Vincent Loechner */
4 /* copyright 1999, Emmanuel Jeannot */
5 /* copyright 2003, Rachid Seghir */
6 /* copyright 2003-2006, Sven Verdoolaege */
7 /* Permission is granted to copy, use, and distribute */
8 /* for any commercial or noncommercial purpose under the terms */
9 /* of the GNU General Public License, either version 2 */
10 /* of the License, or (at your option) any later version. */
11 /* (see file : LICENSE). */
12 /***********************************************************************/
14 #include <assert.h>
15 #include <math.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <barvinok/evalue.h>
19 #include <barvinok/barvinok.h>
20 #include <barvinok/util.h>
21 #include "summate.h"
23 #ifndef value_pmodulus
24 #define value_pmodulus(ref,val1,val2) (mpz_fdiv_r((ref),(val1),(val2)))
25 #endif
27 #define ALLOC(type) (type*)malloc(sizeof(type))
28 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
30 #ifdef __GNUC__
31 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
32 #else
33 #define NALLOC(p,n) p = (void *)malloc((n) * sizeof(*p))
34 #endif
36 void evalue_set_si(evalue *ev, int n, int d) {
37 value_set_si(ev->d, d);
38 value_init(ev->x.n);
39 value_set_si(ev->x.n, n);
42 void evalue_set(evalue *ev, Value n, Value d) {
43 value_assign(ev->d, d);
44 value_init(ev->x.n);
45 value_assign(ev->x.n, n);
48 void evalue_set_reduce(evalue *ev, Value n, Value d) {
49 value_init(ev->x.n);
50 value_gcd(ev->x.n, n, d);
51 value_divexact(ev->d, d, ev->x.n);
52 value_divexact(ev->x.n, n, ev->x.n);
55 evalue* evalue_zero()
57 evalue *EP = ALLOC(evalue);
58 value_init(EP->d);
59 evalue_set_si(EP, 0, 1);
60 return EP;
63 evalue *evalue_nan()
65 evalue *EP = ALLOC(evalue);
66 value_init(EP->d);
67 value_set_si(EP->d, -2);
68 EP->x.p = NULL;
69 return EP;
72 /* returns an evalue that corresponds to
74 * x_var
76 evalue *evalue_var(int var)
78 evalue *EP = ALLOC(evalue);
79 value_init(EP->d);
80 value_set_si(EP->d,0);
81 EP->x.p = new_enode(polynomial, 2, var + 1);
82 evalue_set_si(&EP->x.p->arr[0], 0, 1);
83 evalue_set_si(&EP->x.p->arr[1], 1, 1);
84 return EP;
87 void aep_evalue(evalue *e, int *ref) {
89 enode *p;
90 int i;
92 if (value_notzero_p(e->d))
93 return; /* a rational number, its already reduced */
94 if(!(p = e->x.p))
95 return; /* hum... an overflow probably occured */
97 /* First check the components of p */
98 for (i=0;i<p->size;i++)
99 aep_evalue(&p->arr[i],ref);
101 /* Then p itself */
102 switch (p->type) {
103 case polynomial:
104 case periodic:
105 case evector:
106 p->pos = ref[p->pos-1]+1;
108 return;
109 } /* aep_evalue */
111 /** Comments */
112 void addeliminatedparams_evalue(evalue *e,Matrix *CT) {
114 enode *p;
115 int i, j;
116 int *ref;
118 if (value_notzero_p(e->d))
119 return; /* a rational number, its already reduced */
120 if(!(p = e->x.p))
121 return; /* hum... an overflow probably occured */
123 /* Compute ref */
124 ref = (int *)malloc(sizeof(int)*(CT->NbRows-1));
125 for(i=0;i<CT->NbRows-1;i++)
126 for(j=0;j<CT->NbColumns;j++)
127 if(value_notzero_p(CT->p[i][j])) {
128 ref[i] = j;
129 break;
132 /* Transform the references in e, using ref */
133 aep_evalue(e,ref);
134 free( ref );
135 return;
136 } /* addeliminatedparams_evalue */
138 static void addeliminatedparams_partition(enode *p, Matrix *CT, Polyhedron *CEq,
139 unsigned nparam, unsigned MaxRays)
141 int i;
142 assert(p->type == partition);
143 p->pos = nparam;
145 for (i = 0; i < p->size/2; i++) {
146 Polyhedron *D = EVALUE_DOMAIN(p->arr[2*i]);
147 Polyhedron *T = DomainPreimage(D, CT, MaxRays);
148 Domain_Free(D);
149 if (CEq) {
150 D = T;
151 T = DomainIntersection(D, CEq, MaxRays);
152 Domain_Free(D);
154 EVALUE_SET_DOMAIN(p->arr[2*i], T);
158 void addeliminatedparams_enum(evalue *e, Matrix *CT, Polyhedron *CEq,
159 unsigned MaxRays, unsigned nparam)
161 enode *p;
162 int i;
164 if (CT->NbRows == CT->NbColumns)
165 return;
167 if (EVALUE_IS_ZERO(*e))
168 return;
170 if (value_notzero_p(e->d)) {
171 evalue res;
172 value_init(res.d);
173 value_set_si(res.d, 0);
174 res.x.p = new_enode(partition, 2, nparam);
175 EVALUE_SET_DOMAIN(res.x.p->arr[0],
176 DomainConstraintSimplify(Polyhedron_Copy(CEq), MaxRays));
177 value_clear(res.x.p->arr[1].d);
178 res.x.p->arr[1] = *e;
179 *e = res;
180 return;
183 p = e->x.p;
184 assert(p);
186 addeliminatedparams_partition(p, CT, CEq, nparam, MaxRays);
187 for (i = 0; i < p->size/2; i++)
188 addeliminatedparams_evalue(&p->arr[2*i+1], CT);
191 static int mod_rational_cmp(evalue *e1, evalue *e2)
193 int r;
194 Value m;
195 Value m2;
196 value_init(m);
197 value_init(m2);
199 assert(value_notzero_p(e1->d));
200 assert(value_notzero_p(e2->d));
201 value_multiply(m, e1->x.n, e2->d);
202 value_multiply(m2, e2->x.n, e1->d);
203 if (value_lt(m, m2))
204 r = -1;
205 else if (value_gt(m, m2))
206 r = 1;
207 else
208 r = 0;
209 value_clear(m);
210 value_clear(m2);
212 return r;
215 static int mod_term_cmp_r(evalue *e1, evalue *e2)
217 if (value_notzero_p(e1->d)) {
218 int r;
219 if (value_zero_p(e2->d))
220 return -1;
221 return mod_rational_cmp(e1, e2);
223 if (value_notzero_p(e2->d))
224 return 1;
225 if (e1->x.p->pos < e2->x.p->pos)
226 return -1;
227 else if (e1->x.p->pos > e2->x.p->pos)
228 return 1;
229 else {
230 int r = mod_rational_cmp(&e1->x.p->arr[1], &e2->x.p->arr[1]);
231 return r == 0
232 ? mod_term_cmp_r(&e1->x.p->arr[0], &e2->x.p->arr[0])
233 : r;
237 static int mod_term_cmp(const evalue *e1, const evalue *e2)
239 assert(value_zero_p(e1->d));
240 assert(value_zero_p(e2->d));
241 assert(e1->x.p->type == fractional || e1->x.p->type == flooring);
242 assert(e2->x.p->type == fractional || e2->x.p->type == flooring);
243 return mod_term_cmp_r(&e1->x.p->arr[0], &e2->x.p->arr[0]);
246 static void check_order(const evalue *e)
248 int i;
249 evalue *a;
251 if (value_notzero_p(e->d))
252 return;
254 switch (e->x.p->type) {
255 case partition:
256 for (i = 0; i < e->x.p->size/2; ++i)
257 check_order(&e->x.p->arr[2*i+1]);
258 break;
259 case relation:
260 for (i = 1; i < e->x.p->size; ++i) {
261 a = &e->x.p->arr[i];
262 if (value_notzero_p(a->d))
263 continue;
264 switch (a->x.p->type) {
265 case relation:
266 assert(mod_term_cmp(&e->x.p->arr[0], &a->x.p->arr[0]) < 0);
267 break;
268 case partition:
269 assert(0);
271 check_order(a);
273 break;
274 case polynomial:
275 for (i = 0; i < e->x.p->size; ++i) {
276 a = &e->x.p->arr[i];
277 if (value_notzero_p(a->d))
278 continue;
279 switch (a->x.p->type) {
280 case polynomial:
281 assert(e->x.p->pos < a->x.p->pos);
282 break;
283 case relation:
284 case partition:
285 assert(0);
287 check_order(a);
289 break;
290 case fractional:
291 case flooring:
292 for (i = 1; i < e->x.p->size; ++i) {
293 a = &e->x.p->arr[i];
294 if (value_notzero_p(a->d))
295 continue;
296 switch (a->x.p->type) {
297 case polynomial:
298 case relation:
299 case partition:
300 assert(0);
303 break;
307 /* Negative pos means inequality */
308 /* s is negative of substitution if m is not zero */
309 struct fixed_param {
310 int pos;
311 evalue s;
312 Value d;
313 Value m;
316 struct subst {
317 struct fixed_param *fixed;
318 int n;
319 int max;
322 static int relations_depth(evalue *e)
324 int d;
326 for (d = 0;
327 value_zero_p(e->d) && e->x.p->type == relation;
328 e = &e->x.p->arr[1], ++d);
329 return d;
332 static void poly_denom_not_constant(evalue **pp, Value *d)
334 evalue *p = *pp;
335 value_set_si(*d, 1);
337 while (value_zero_p(p->d)) {
338 assert(p->x.p->type == polynomial);
339 assert(p->x.p->size == 2);
340 assert(value_notzero_p(p->x.p->arr[1].d));
341 value_lcm(*d, *d, p->x.p->arr[1].d);
342 p = &p->x.p->arr[0];
344 *pp = p;
347 static void poly_denom(evalue *p, Value *d)
349 poly_denom_not_constant(&p, d);
350 value_lcm(*d, *d, p->d);
353 static void realloc_substitution(struct subst *s, int d)
355 struct fixed_param *n;
356 int i;
357 NALLOC(n, s->max+d);
358 for (i = 0; i < s->n; ++i)
359 n[i] = s->fixed[i];
360 free(s->fixed);
361 s->fixed = n;
362 s->max += d;
365 static int add_modulo_substitution(struct subst *s, evalue *r)
367 evalue *p;
368 evalue *f;
369 evalue *m;
371 assert(value_zero_p(r->d) && r->x.p->type == relation);
372 m = &r->x.p->arr[0];
374 /* May have been reduced already */
375 if (value_notzero_p(m->d))
376 return 0;
378 assert(value_zero_p(m->d) && m->x.p->type == fractional);
379 assert(m->x.p->size == 3);
381 /* fractional was inverted during reduction
382 * invert it back and move constant in
384 if (!EVALUE_IS_ONE(m->x.p->arr[2])) {
385 assert(value_pos_p(m->x.p->arr[2].d));
386 assert(value_mone_p(m->x.p->arr[2].x.n));
387 value_set_si(m->x.p->arr[2].x.n, 1);
388 value_increment(m->x.p->arr[1].x.n, m->x.p->arr[1].x.n);
389 assert(value_eq(m->x.p->arr[1].x.n, m->x.p->arr[1].d));
390 value_set_si(m->x.p->arr[1].x.n, 1);
391 eadd(&m->x.p->arr[1], &m->x.p->arr[0]);
392 value_set_si(m->x.p->arr[1].x.n, 0);
393 value_set_si(m->x.p->arr[1].d, 1);
396 /* Oops. Nested identical relations. */
397 if (!EVALUE_IS_ZERO(m->x.p->arr[1]))
398 return 0;
400 if (s->n >= s->max) {
401 int d = relations_depth(r);
402 realloc_substitution(s, d);
405 p = &m->x.p->arr[0];
406 assert(value_zero_p(p->d) && p->x.p->type == polynomial);
407 assert(p->x.p->size == 2);
408 f = &p->x.p->arr[1];
410 assert(value_pos_p(f->x.n));
412 value_init(s->fixed[s->n].m);
413 value_assign(s->fixed[s->n].m, f->d);
414 s->fixed[s->n].pos = p->x.p->pos;
415 value_init(s->fixed[s->n].d);
416 value_assign(s->fixed[s->n].d, f->x.n);
417 value_init(s->fixed[s->n].s.d);
418 evalue_copy(&s->fixed[s->n].s, &p->x.p->arr[0]);
419 ++s->n;
421 return 1;
424 static int type_offset(enode *p)
426 return p->type == fractional ? 1 :
427 p->type == flooring ? 1 :
428 p->type == relation ? 1 : 0;
431 static void reorder_terms_about(enode *p, evalue *v)
433 int i;
434 int offset = type_offset(p);
436 for (i = p->size-1; i >= offset+1; i--) {
437 emul(v, &p->arr[i]);
438 eadd(&p->arr[i], &p->arr[i-1]);
439 free_evalue_refs(&(p->arr[i]));
441 p->size = offset+1;
442 free_evalue_refs(v);
445 void evalue_reorder_terms(evalue *e)
447 enode *p;
448 evalue f;
449 int offset;
451 assert(value_zero_p(e->d));
452 p = e->x.p;
453 assert(p->type == fractional ||
454 p->type == flooring ||
455 p->type == polynomial); /* for now */
457 offset = type_offset(p);
458 value_init(f.d);
459 value_set_si(f.d, 0);
460 f.x.p = new_enode(p->type, offset+2, p->pos);
461 if (offset == 1) {
462 value_clear(f.x.p->arr[0].d);
463 f.x.p->arr[0] = p->arr[0];
465 evalue_set_si(&f.x.p->arr[offset], 0, 1);
466 evalue_set_si(&f.x.p->arr[offset+1], 1, 1);
467 reorder_terms_about(p, &f);
468 value_clear(e->d);
469 *e = p->arr[offset];
470 free(p);
473 static void evalue_reduce_size(evalue *e)
475 int i, offset;
476 enode *p;
477 assert(value_zero_p(e->d));
479 p = e->x.p;
480 offset = type_offset(p);
482 /* Try to reduce the degree */
483 for (i = p->size-1; i >= offset+1; i--) {
484 if (!EVALUE_IS_ZERO(p->arr[i]))
485 break;
486 free_evalue_refs(&p->arr[i]);
488 if (i+1 < p->size)
489 p->size = i+1;
491 /* Try to reduce its strength */
492 if (p->type == relation) {
493 if (p->size == 1) {
494 free_evalue_refs(&p->arr[0]);
495 evalue_set_si(e, 0, 1);
496 free(p);
498 } else if (p->size == offset+1) {
499 value_clear(e->d);
500 memcpy(e, &p->arr[offset], sizeof(evalue));
501 if (offset == 1)
502 free_evalue_refs(&p->arr[0]);
503 free(p);
507 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
509 /* This function is called after the argument of the fractional part
510 * in a polynomial expression in this fractional part has been reduced.
511 * If the polynomial expression is of degree at least two, then
512 * check if the argument happens to have been reduced to an affine
513 * expression with denominator two. If so, then emul_fractionals
514 * assumes that the polynomial expression in this fractional part
515 * is affine so we reduce the higher degree polynomial to an affine
516 * expression here.
518 * In particular, since the denominator of the fractional part is two,
519 * then the fractional part can only take on two values, 0 and 1/2.
520 * This means that { f(x)/2 }^2 = 1/2 { f(x)/2 } so that we can repeatedly
521 * replace
523 * a_n { f(x)/2 }^n with n >= 2
525 * by
527 * a_n/2 { f(x)/2 }^{n-1}
529 static void reduce_fractional(evalue *e)
531 int i;
532 evalue d;
534 if (e->x.p->size <= 3)
535 return;
537 value_init(d.d);
538 poly_denom(&e->x.p->arr[0], &d.d);
539 if (value_two_p(d.d)) {
540 value_init(d.x.n);
541 value_set_si(d.x.n, 1);
542 for (i = e->x.p->size - 1; i >= 3; --i) {
543 emul(&d, &e->x.p->arr[i]);
544 eadd(&e->x.p->arr[i], &e->x.p->arr[i - 1]);
545 free_evalue_refs(&e->x.p->arr[i]);
547 e->x.p->size = 3;
548 value_clear(d.x.n);
550 value_clear(d.d);
553 void _reduce_evalue (evalue *e, struct subst *s, int fract) {
555 enode *p;
556 int i, j, k;
557 int add;
559 if (value_notzero_p(e->d)) {
560 if (fract)
561 mpz_fdiv_r(e->x.n, e->x.n, e->d);
562 return; /* a rational number, its already reduced */
565 if(!(p = e->x.p))
566 return; /* hum... an overflow probably occured */
568 /* First reduce the components of p */
569 add = p->type == relation;
570 for (i=0; i<p->size; i++) {
571 if (add && i == 1)
572 add = add_modulo_substitution(s, e);
574 if (i == 0 && p->type==fractional) {
575 _reduce_evalue(&p->arr[i], s, 1);
576 reduce_fractional(e);
577 } else
578 _reduce_evalue(&p->arr[i], s, fract);
580 if (add && i == p->size-1) {
581 --s->n;
582 value_clear(s->fixed[s->n].m);
583 value_clear(s->fixed[s->n].d);
584 free_evalue_refs(&s->fixed[s->n].s);
585 } else if (add && i == 1)
586 s->fixed[s->n-1].pos *= -1;
589 if (p->type==periodic) {
591 /* Try to reduce the period */
592 for (i=1; i<=(p->size)/2; i++) {
593 if ((p->size % i)==0) {
595 /* Can we reduce the size to i ? */
596 for (j=0; j<i; j++)
597 for (k=j+i; k<e->x.p->size; k+=i)
598 if (!eequal(&p->arr[j], &p->arr[k])) goto you_lose;
600 /* OK, lets do it */
601 for (j=i; j<p->size; j++) free_evalue_refs(&p->arr[j]);
602 p->size = i;
603 break;
605 you_lose: /* OK, lets not do it */
606 continue;
610 /* Try to reduce its strength */
611 if (p->size == 1) {
612 value_clear(e->d);
613 memcpy(e,&p->arr[0],sizeof(evalue));
614 free(p);
617 else if (p->type==polynomial) {
618 for (k = 0; s && k < s->n; ++k) {
619 if (s->fixed[k].pos == p->pos) {
620 int divide = value_notone_p(s->fixed[k].d);
621 evalue d;
623 if (value_notzero_p(s->fixed[k].m)) {
624 if (!fract)
625 continue;
626 assert(p->size == 2);
627 if (divide && value_ne(s->fixed[k].d, p->arr[1].x.n))
628 continue;
629 if (!mpz_divisible_p(s->fixed[k].m, p->arr[1].d))
630 continue;
631 divide = 1;
634 if (divide) {
635 value_init(d.d);
636 value_assign(d.d, s->fixed[k].d);
637 value_init(d.x.n);
638 if (value_notzero_p(s->fixed[k].m))
639 value_oppose(d.x.n, s->fixed[k].m);
640 else
641 value_set_si(d.x.n, 1);
644 for (i=p->size-1;i>=1;i--) {
645 emul(&s->fixed[k].s, &p->arr[i]);
646 if (divide)
647 emul(&d, &p->arr[i]);
648 eadd(&p->arr[i], &p->arr[i-1]);
649 free_evalue_refs(&(p->arr[i]));
651 p->size = 1;
652 _reduce_evalue(&p->arr[0], s, fract);
654 if (divide)
655 free_evalue_refs(&d);
657 break;
661 evalue_reduce_size(e);
663 else if (p->type==fractional) {
664 int reorder = 0;
665 evalue v;
667 if (value_notzero_p(p->arr[0].d)) {
668 value_init(v.d);
669 value_assign(v.d, p->arr[0].d);
670 value_init(v.x.n);
671 mpz_fdiv_r(v.x.n, p->arr[0].x.n, p->arr[0].d);
673 reorder = 1;
674 } else {
675 evalue *f, *base;
676 evalue *pp = &p->arr[0];
677 assert(value_zero_p(pp->d) && pp->x.p->type == polynomial);
678 assert(pp->x.p->size == 2);
680 /* search for exact duplicate among the modulo inequalities */
681 do {
682 f = &pp->x.p->arr[1];
683 for (k = 0; s && k < s->n; ++k) {
684 if (-s->fixed[k].pos == pp->x.p->pos &&
685 value_eq(s->fixed[k].d, f->x.n) &&
686 value_eq(s->fixed[k].m, f->d) &&
687 eequal(&s->fixed[k].s, &pp->x.p->arr[0]))
688 break;
690 if (k < s->n) {
691 Value g;
692 value_init(g);
694 /* replace { E/m } by { (E-1)/m } + 1/m */
695 poly_denom(pp, &g);
696 if (reorder) {
697 evalue extra;
698 value_init(extra.d);
699 evalue_set_si(&extra, 1, 1);
700 value_assign(extra.d, g);
701 eadd(&extra, &v.x.p->arr[1]);
702 free_evalue_refs(&extra);
704 /* We've been going in circles; stop now */
705 if (value_ge(v.x.p->arr[1].x.n, v.x.p->arr[1].d)) {
706 free_evalue_refs(&v);
707 value_init(v.d);
708 evalue_set_si(&v, 0, 1);
709 break;
711 } else {
712 value_init(v.d);
713 value_set_si(v.d, 0);
714 v.x.p = new_enode(fractional, 3, -1);
715 evalue_set_si(&v.x.p->arr[1], 1, 1);
716 value_assign(v.x.p->arr[1].d, g);
717 evalue_set_si(&v.x.p->arr[2], 1, 1);
718 evalue_copy(&v.x.p->arr[0], &p->arr[0]);
721 for (f = &v.x.p->arr[0]; value_zero_p(f->d);
722 f = &f->x.p->arr[0])
724 value_division(f->d, g, f->d);
725 value_multiply(f->x.n, f->x.n, f->d);
726 value_assign(f->d, g);
727 value_decrement(f->x.n, f->x.n);
728 mpz_fdiv_r(f->x.n, f->x.n, f->d);
730 value_gcd(g, f->d, f->x.n);
731 value_division(f->d, f->d, g);
732 value_division(f->x.n, f->x.n, g);
734 value_clear(g);
735 pp = &v.x.p->arr[0];
737 reorder = 1;
739 } while (k < s->n);
741 /* reduction may have made this fractional arg smaller */
742 i = reorder ? p->size : 1;
743 for ( ; i < p->size; ++i)
744 if (value_zero_p(p->arr[i].d) &&
745 p->arr[i].x.p->type == fractional &&
746 mod_term_cmp(e, &p->arr[i]) >= 0)
747 break;
748 if (i < p->size) {
749 value_init(v.d);
750 value_set_si(v.d, 0);
751 v.x.p = new_enode(fractional, 3, -1);
752 evalue_set_si(&v.x.p->arr[1], 0, 1);
753 evalue_set_si(&v.x.p->arr[2], 1, 1);
754 evalue_copy(&v.x.p->arr[0], &p->arr[0]);
756 reorder = 1;
759 if (!reorder) {
760 Value m;
761 Value r;
762 evalue *pp = &p->arr[0];
763 value_init(m);
764 value_init(r);
765 poly_denom_not_constant(&pp, &m);
766 mpz_fdiv_r(r, m, pp->d);
767 if (value_notzero_p(r)) {
768 value_init(v.d);
769 value_set_si(v.d, 0);
770 v.x.p = new_enode(fractional, 3, -1);
772 value_multiply(r, m, pp->x.n);
773 value_multiply(v.x.p->arr[1].d, m, pp->d);
774 value_init(v.x.p->arr[1].x.n);
775 mpz_fdiv_r(v.x.p->arr[1].x.n, r, pp->d);
776 mpz_fdiv_q(r, r, pp->d);
778 evalue_set_si(&v.x.p->arr[2], 1, 1);
779 evalue_copy(&v.x.p->arr[0], &p->arr[0]);
780 pp = &v.x.p->arr[0];
781 while (value_zero_p(pp->d))
782 pp = &pp->x.p->arr[0];
784 value_assign(pp->d, m);
785 value_assign(pp->x.n, r);
787 value_gcd(r, pp->d, pp->x.n);
788 value_division(pp->d, pp->d, r);
789 value_division(pp->x.n, pp->x.n, r);
791 reorder = 1;
793 value_clear(m);
794 value_clear(r);
797 if (!reorder) {
798 int invert = 0;
799 Value twice;
800 value_init(twice);
802 for (pp = &p->arr[0]; value_zero_p(pp->d);
803 pp = &pp->x.p->arr[0]) {
804 f = &pp->x.p->arr[1];
805 assert(value_pos_p(f->d));
806 mpz_mul_ui(twice, f->x.n, 2);
807 if (value_lt(twice, f->d))
808 break;
809 if (value_eq(twice, f->d))
810 continue;
811 invert = 1;
812 break;
815 if (invert) {
816 value_init(v.d);
817 value_set_si(v.d, 0);
818 v.x.p = new_enode(fractional, 3, -1);
819 evalue_set_si(&v.x.p->arr[1], 0, 1);
820 poly_denom(&p->arr[0], &twice);
821 value_assign(v.x.p->arr[1].d, twice);
822 value_decrement(v.x.p->arr[1].x.n, twice);
823 evalue_set_si(&v.x.p->arr[2], -1, 1);
824 evalue_copy(&v.x.p->arr[0], &p->arr[0]);
826 for (pp = &v.x.p->arr[0]; value_zero_p(pp->d);
827 pp = &pp->x.p->arr[0]) {
828 f = &pp->x.p->arr[1];
829 value_oppose(f->x.n, f->x.n);
830 mpz_fdiv_r(f->x.n, f->x.n, f->d);
832 value_division(pp->d, twice, pp->d);
833 value_multiply(pp->x.n, pp->x.n, pp->d);
834 value_assign(pp->d, twice);
835 value_oppose(pp->x.n, pp->x.n);
836 value_decrement(pp->x.n, pp->x.n);
837 mpz_fdiv_r(pp->x.n, pp->x.n, pp->d);
839 /* Maybe we should do this during reduction of
840 * the constant.
842 value_gcd(twice, pp->d, pp->x.n);
843 value_division(pp->d, pp->d, twice);
844 value_division(pp->x.n, pp->x.n, twice);
846 reorder = 1;
849 value_clear(twice);
853 if (reorder) {
854 reorder_terms_about(p, &v);
855 _reduce_evalue(&p->arr[1], s, fract);
858 evalue_reduce_size(e);
860 else if (p->type == flooring) {
861 /* Replace floor(constant) by its value */
862 if (value_notzero_p(p->arr[0].d)) {
863 evalue v;
864 value_init(v.d);
865 value_set_si(v.d, 1);
866 value_init(v.x.n);
867 mpz_fdiv_q(v.x.n, p->arr[0].x.n, p->arr[0].d);
868 reorder_terms_about(p, &v);
869 _reduce_evalue(&p->arr[1], s, fract);
871 evalue_reduce_size(e);
873 else if (p->type == relation) {
874 if (p->size == 3 && eequal(&p->arr[1], &p->arr[2])) {
875 free_evalue_refs(&(p->arr[2]));
876 free_evalue_refs(&(p->arr[0]));
877 p->size = 2;
878 value_clear(e->d);
879 *e = p->arr[1];
880 free(p);
881 return;
883 evalue_reduce_size(e);
884 if (value_notzero_p(e->d) || p != e->x.p)
885 return;
886 else {
887 int reduced = 0;
888 evalue *m;
889 m = &p->arr[0];
891 /* Relation was reduced by means of an identical
892 * inequality => remove
894 if (value_zero_p(m->d) && !EVALUE_IS_ZERO(m->x.p->arr[1]))
895 reduced = 1;
897 if (reduced || value_notzero_p(p->arr[0].d)) {
898 if (!reduced && value_zero_p(p->arr[0].x.n)) {
899 value_clear(e->d);
900 memcpy(e,&p->arr[1],sizeof(evalue));
901 if (p->size == 3)
902 free_evalue_refs(&(p->arr[2]));
903 } else {
904 if (p->size == 3) {
905 value_clear(e->d);
906 memcpy(e,&p->arr[2],sizeof(evalue));
907 } else
908 evalue_set_si(e, 0, 1);
909 free_evalue_refs(&(p->arr[1]));
911 free_evalue_refs(&(p->arr[0]));
912 free(p);
916 return;
917 } /* reduce_evalue */
919 static void add_substitution(struct subst *s, Value *row, unsigned dim)
921 int k, l;
922 evalue *r;
924 for (k = 0; k < dim; ++k)
925 if (value_notzero_p(row[k+1]))
926 break;
928 Vector_Normalize_Positive(row+1, dim+1, k);
929 assert(s->n < s->max);
930 value_init(s->fixed[s->n].d);
931 value_init(s->fixed[s->n].m);
932 value_assign(s->fixed[s->n].d, row[k+1]);
933 s->fixed[s->n].pos = k+1;
934 value_set_si(s->fixed[s->n].m, 0);
935 r = &s->fixed[s->n].s;
936 value_init(r->d);
937 for (l = k+1; l < dim; ++l)
938 if (value_notzero_p(row[l+1])) {
939 value_set_si(r->d, 0);
940 r->x.p = new_enode(polynomial, 2, l + 1);
941 value_init(r->x.p->arr[1].x.n);
942 value_oppose(r->x.p->arr[1].x.n, row[l+1]);
943 value_set_si(r->x.p->arr[1].d, 1);
944 r = &r->x.p->arr[0];
946 value_init(r->x.n);
947 value_oppose(r->x.n, row[dim+1]);
948 value_set_si(r->d, 1);
949 ++s->n;
952 static void _reduce_evalue_in_domain(evalue *e, Polyhedron *D, struct subst *s)
954 unsigned dim;
955 Polyhedron *orig = D;
957 s->n = 0;
958 dim = D->Dimension;
959 if (D->next)
960 D = DomainConvex(D, 0);
961 /* We don't perform any substitutions if the domain is a union.
962 * We may therefore miss out on some possible simplifications,
963 * e.g., if a variable is always even in the whole union,
964 * while there is a relation in the evalue that evaluates
965 * to zero for even values of the variable.
967 if (!D->next && D->NbEq) {
968 int j, k;
969 if (s->max < dim) {
970 if (s->max != 0)
971 realloc_substitution(s, dim);
972 else {
973 int d = relations_depth(e);
974 s->max = dim+d;
975 NALLOC(s->fixed, s->max);
978 for (j = 0; j < D->NbEq; ++j)
979 add_substitution(s, D->Constraint[j], dim);
981 if (D != orig)
982 Domain_Free(D);
983 _reduce_evalue(e, s, 0);
984 if (s->n != 0) {
985 int j;
986 for (j = 0; j < s->n; ++j) {
987 value_clear(s->fixed[j].d);
988 value_clear(s->fixed[j].m);
989 free_evalue_refs(&s->fixed[j].s);
994 void reduce_evalue_in_domain(evalue *e, Polyhedron *D)
996 struct subst s = { NULL, 0, 0 };
997 POL_ENSURE_VERTICES(D);
998 if (emptyQ(D)) {
999 if (EVALUE_IS_ZERO(*e))
1000 return;
1001 free_evalue_refs(e);
1002 value_init(e->d);
1003 evalue_set_si(e, 0, 1);
1004 return;
1006 _reduce_evalue_in_domain(e, D, &s);
1007 if (s.max != 0)
1008 free(s.fixed);
1011 void reduce_evalue (evalue *e) {
1012 struct subst s = { NULL, 0, 0 };
1014 if (value_notzero_p(e->d))
1015 return; /* a rational number, its already reduced */
1017 if (e->x.p->type == partition) {
1018 int i;
1019 for (i = 0; i < e->x.p->size/2; ++i) {
1020 Polyhedron *D = EVALUE_DOMAIN(e->x.p->arr[2*i]);
1022 /* This shouldn't really happen;
1023 * Empty domains should not be added.
1025 POL_ENSURE_VERTICES(D);
1026 if (!emptyQ(D))
1027 _reduce_evalue_in_domain(&e->x.p->arr[2*i+1], D, &s);
1029 if (emptyQ(D) || EVALUE_IS_ZERO(e->x.p->arr[2*i+1])) {
1030 free_evalue_refs(&e->x.p->arr[2*i+1]);
1031 Domain_Free(EVALUE_DOMAIN(e->x.p->arr[2*i]));
1032 value_clear(e->x.p->arr[2*i].d);
1033 e->x.p->size -= 2;
1034 e->x.p->arr[2*i] = e->x.p->arr[e->x.p->size];
1035 e->x.p->arr[2*i+1] = e->x.p->arr[e->x.p->size+1];
1036 --i;
1039 if (e->x.p->size == 0) {
1040 free(e->x.p);
1041 evalue_set_si(e, 0, 1);
1043 } else
1044 _reduce_evalue(e, &s, 0);
1045 if (s.max != 0)
1046 free(s.fixed);
1049 static void print_evalue_r(FILE *DST, const evalue *e, const char **pname)
1051 if (EVALUE_IS_NAN(*e)) {
1052 fprintf(DST, "NaN");
1053 return;
1056 if(value_notzero_p(e->d)) {
1057 if(value_notone_p(e->d)) {
1058 value_print(DST,VALUE_FMT,e->x.n);
1059 fprintf(DST,"/");
1060 value_print(DST,VALUE_FMT,e->d);
1062 else {
1063 value_print(DST,VALUE_FMT,e->x.n);
1066 else
1067 print_enode(DST,e->x.p,pname);
1068 return;
1069 } /* print_evalue */
1071 void print_evalue(FILE *DST, const evalue *e, const char **pname)
1073 print_evalue_r(DST, e, pname);
1074 if (value_notzero_p(e->d))
1075 fprintf(DST, "\n");
1078 void print_enode(FILE *DST, enode *p, const char **pname)
1080 int i;
1082 if (!p) {
1083 fprintf(DST, "NULL");
1084 return;
1086 switch (p->type) {
1087 case evector:
1088 fprintf(DST, "{ ");
1089 for (i=0; i<p->size; i++) {
1090 print_evalue_r(DST, &p->arr[i], pname);
1091 if (i!=(p->size-1))
1092 fprintf(DST, ", ");
1094 fprintf(DST, " }\n");
1095 break;
1096 case polynomial:
1097 fprintf(DST, "( ");
1098 for (i=p->size-1; i>=0; i--) {
1099 print_evalue_r(DST, &p->arr[i], pname);
1100 if (i==1) fprintf(DST, " * %s + ", pname[p->pos-1]);
1101 else if (i>1)
1102 fprintf(DST, " * %s^%d + ", pname[p->pos-1], i);
1104 fprintf(DST, " )\n");
1105 break;
1106 case periodic:
1107 fprintf(DST, "[ ");
1108 for (i=0; i<p->size; i++) {
1109 print_evalue_r(DST, &p->arr[i], pname);
1110 if (i!=(p->size-1)) fprintf(DST, ", ");
1112 fprintf(DST," ]_%s", pname[p->pos-1]);
1113 break;
1114 case flooring:
1115 case fractional:
1116 fprintf(DST, "( ");
1117 for (i=p->size-1; i>=1; i--) {
1118 print_evalue_r(DST, &p->arr[i], pname);
1119 if (i >= 2) {
1120 fprintf(DST, " * ");
1121 fprintf(DST, p->type == flooring ? "[" : "{");
1122 print_evalue_r(DST, &p->arr[0], pname);
1123 fprintf(DST, p->type == flooring ? "]" : "}");
1124 if (i>2)
1125 fprintf(DST, "^%d + ", i-1);
1126 else
1127 fprintf(DST, " + ");
1130 fprintf(DST, " )\n");
1131 break;
1132 case relation:
1133 fprintf(DST, "[ ");
1134 print_evalue_r(DST, &p->arr[0], pname);
1135 fprintf(DST, "= 0 ] * \n");
1136 print_evalue_r(DST, &p->arr[1], pname);
1137 if (p->size > 2) {
1138 fprintf(DST, " +\n [ ");
1139 print_evalue_r(DST, &p->arr[0], pname);
1140 fprintf(DST, "!= 0 ] * \n");
1141 print_evalue_r(DST, &p->arr[2], pname);
1143 break;
1144 case partition: {
1145 char **new_names = NULL;
1146 const char **names = pname;
1147 int maxdim = EVALUE_DOMAIN(p->arr[0])->Dimension;
1148 if (!pname || p->pos < maxdim) {
1149 new_names = ALLOCN(char *, maxdim);
1150 for (i = 0; i < p->pos; ++i) {
1151 if (pname)
1152 new_names[i] = (char *)pname[i];
1153 else {
1154 new_names[i] = ALLOCN(char, 10);
1155 snprintf(new_names[i], 10, "%c", 'P'+i);
1158 for ( ; i < maxdim; ++i) {
1159 new_names[i] = ALLOCN(char, 10);
1160 snprintf(new_names[i], 10, "_p%d", i);
1162 names = (const char**)new_names;
1165 for (i=0; i<p->size/2; i++) {
1166 Print_Domain(DST, EVALUE_DOMAIN(p->arr[2*i]), names);
1167 print_evalue_r(DST, &p->arr[2*i+1], names);
1168 if (value_notzero_p(p->arr[2*i+1].d))
1169 fprintf(DST, "\n");
1172 if (!pname || p->pos < maxdim) {
1173 for (i = pname ? p->pos : 0; i < maxdim; ++i)
1174 free(new_names[i]);
1175 free(new_names);
1178 break;
1180 default:
1181 assert(0);
1183 return;
1184 } /* print_enode */
1186 /* Returns
1187 * 0 if toplevels of e1 and e2 are at the same level
1188 * <0 if toplevel of e1 should be outside of toplevel of e2
1189 * >0 if toplevel of e2 should be outside of toplevel of e1
1191 static int evalue_level_cmp(const evalue *e1, const evalue *e2)
1193 if (value_notzero_p(e1->d) && value_notzero_p(e2->d))
1194 return 0;
1195 if (value_notzero_p(e1->d))
1196 return 1;
1197 if (value_notzero_p(e2->d))
1198 return -1;
1199 if (e1->x.p->type == partition && e2->x.p->type == partition)
1200 return 0;
1201 if (e1->x.p->type == partition)
1202 return -1;
1203 if (e2->x.p->type == partition)
1204 return 1;
1205 if (e1->x.p->type == relation && e2->x.p->type == relation) {
1206 if (eequal(&e1->x.p->arr[0], &e2->x.p->arr[0]))
1207 return 0;
1208 return mod_term_cmp(&e1->x.p->arr[0], &e2->x.p->arr[0]);
1210 if (e1->x.p->type == relation)
1211 return -1;
1212 if (e2->x.p->type == relation)
1213 return 1;
1214 if (e1->x.p->type == polynomial && e2->x.p->type == polynomial)
1215 return e1->x.p->pos - e2->x.p->pos;
1216 if (e1->x.p->type == polynomial)
1217 return -1;
1218 if (e2->x.p->type == polynomial)
1219 return 1;
1220 if (e1->x.p->type == periodic && e2->x.p->type == periodic)
1221 return e1->x.p->pos - e2->x.p->pos;
1222 assert(e1->x.p->type != periodic);
1223 assert(e2->x.p->type != periodic);
1224 assert(e1->x.p->type == e2->x.p->type);
1225 if (eequal(&e1->x.p->arr[0], &e2->x.p->arr[0]))
1226 return 0;
1227 return mod_term_cmp(e1, e2);
1230 static void eadd_rev(const evalue *e1, evalue *res)
1232 evalue ev;
1233 value_init(ev.d);
1234 evalue_copy(&ev, e1);
1235 eadd(res, &ev);
1236 free_evalue_refs(res);
1237 *res = ev;
1240 static void eadd_rev_cst(const evalue *e1, evalue *res)
1242 evalue ev;
1243 value_init(ev.d);
1244 evalue_copy(&ev, e1);
1245 eadd(res, &ev.x.p->arr[type_offset(ev.x.p)]);
1246 free_evalue_refs(res);
1247 *res = ev;
1250 struct section { Polyhedron * D; evalue E; };
1252 void eadd_partitions(const evalue *e1, evalue *res)
1254 int n, i, j;
1255 Polyhedron *d, *fd;
1256 struct section *s;
1257 s = (struct section *)
1258 malloc((e1->x.p->size/2+1) * (res->x.p->size/2+1) *
1259 sizeof(struct section));
1260 assert(s);
1261 assert(e1->x.p->pos == res->x.p->pos);
1262 assert(e1->x.p->pos == EVALUE_DOMAIN(e1->x.p->arr[0])->Dimension);
1263 assert(res->x.p->pos == EVALUE_DOMAIN(res->x.p->arr[0])->Dimension);
1265 n = 0;
1266 for (j = 0; j < e1->x.p->size/2; ++j) {
1267 assert(res->x.p->size >= 2);
1268 fd = DomainDifference(EVALUE_DOMAIN(e1->x.p->arr[2*j]),
1269 EVALUE_DOMAIN(res->x.p->arr[0]), 0);
1270 if (!emptyQ(fd))
1271 for (i = 1; i < res->x.p->size/2; ++i) {
1272 Polyhedron *t = fd;
1273 fd = DomainDifference(fd, EVALUE_DOMAIN(res->x.p->arr[2*i]), 0);
1274 Domain_Free(t);
1275 if (emptyQ(fd))
1276 break;
1278 fd = DomainConstraintSimplify(fd, 0);
1279 if (emptyQ(fd)) {
1280 Domain_Free(fd);
1281 continue;
1283 value_init(s[n].E.d);
1284 evalue_copy(&s[n].E, &e1->x.p->arr[2*j+1]);
1285 s[n].D = fd;
1286 ++n;
1288 for (i = 0; i < res->x.p->size/2; ++i) {
1289 fd = EVALUE_DOMAIN(res->x.p->arr[2*i]);
1290 for (j = 0; j < e1->x.p->size/2; ++j) {
1291 Polyhedron *t;
1292 d = DomainIntersection(EVALUE_DOMAIN(e1->x.p->arr[2*j]),
1293 EVALUE_DOMAIN(res->x.p->arr[2*i]), 0);
1294 d = DomainConstraintSimplify(d, 0);
1295 if (emptyQ(d)) {
1296 Domain_Free(d);
1297 continue;
1299 t = fd;
1300 fd = DomainDifference(fd, EVALUE_DOMAIN(e1->x.p->arr[2*j]), 0);
1301 if (t != EVALUE_DOMAIN(res->x.p->arr[2*i]))
1302 Domain_Free(t);
1303 value_init(s[n].E.d);
1304 evalue_copy(&s[n].E, &res->x.p->arr[2*i+1]);
1305 eadd(&e1->x.p->arr[2*j+1], &s[n].E);
1306 s[n].D = d;
1307 ++n;
1309 if (!emptyQ(fd)) {
1310 s[n].E = res->x.p->arr[2*i+1];
1311 s[n].D = fd;
1312 ++n;
1313 } else {
1314 free_evalue_refs(&res->x.p->arr[2*i+1]);
1315 Domain_Free(fd);
1317 if (fd != EVALUE_DOMAIN(res->x.p->arr[2*i]))
1318 Domain_Free(EVALUE_DOMAIN(res->x.p->arr[2*i]));
1319 value_clear(res->x.p->arr[2*i].d);
1322 free(res->x.p);
1323 assert(n > 0);
1324 res->x.p = new_enode(partition, 2*n, e1->x.p->pos);
1325 for (j = 0; j < n; ++j) {
1326 EVALUE_SET_DOMAIN(res->x.p->arr[2*j], s[j].D);
1327 value_clear(res->x.p->arr[2*j+1].d);
1328 res->x.p->arr[2*j+1] = s[j].E;
1331 free(s);
1334 static void explicit_complement(evalue *res)
1336 enode *rel = new_enode(relation, 3, 0);
1337 assert(rel);
1338 value_clear(rel->arr[0].d);
1339 rel->arr[0] = res->x.p->arr[0];
1340 value_clear(rel->arr[1].d);
1341 rel->arr[1] = res->x.p->arr[1];
1342 value_set_si(rel->arr[2].d, 1);
1343 value_init(rel->arr[2].x.n);
1344 value_set_si(rel->arr[2].x.n, 0);
1345 free(res->x.p);
1346 res->x.p = rel;
1349 static void reduce_constant(evalue *e)
1351 Value g;
1352 value_init(g);
1354 value_gcd(g, e->x.n, e->d);
1355 if (value_notone_p(g)) {
1356 value_division(e->d, e->d,g);
1357 value_division(e->x.n, e->x.n,g);
1359 value_clear(g);
1362 /* Add two rational numbers */
1363 static void eadd_rationals(const evalue *e1, evalue *res)
1365 if (value_eq(e1->d, res->d))
1366 value_addto(res->x.n, res->x.n, e1->x.n);
1367 else {
1368 value_multiply(res->x.n, res->x.n, e1->d);
1369 value_addmul(res->x.n, e1->x.n, res->d);
1370 value_multiply(res->d,e1->d,res->d);
1372 reduce_constant(res);
1375 static void eadd_relations(const evalue *e1, evalue *res)
1377 int i;
1379 if (res->x.p->size < 3 && e1->x.p->size == 3)
1380 explicit_complement(res);
1381 for (i = 1; i < e1->x.p->size; ++i)
1382 eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
1385 static void eadd_arrays(const evalue *e1, evalue *res, int n)
1387 int i;
1389 // add any element in e1 to the corresponding element in res
1390 i = type_offset(res->x.p);
1391 if (i == 1)
1392 assert(eequal(&e1->x.p->arr[0], &res->x.p->arr[0]));
1393 for (; i < n; i++)
1394 eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
1397 static void eadd_poly(const evalue *e1, evalue *res)
1399 if (e1->x.p->size > res->x.p->size)
1400 eadd_rev(e1, res);
1401 else
1402 eadd_arrays(e1, res, e1->x.p->size);
1406 * Product or sum of two periodics of the same parameter
1407 * and different periods
1409 static void combine_periodics(const evalue *e1, evalue *res,
1410 void (*op)(const evalue *, evalue*))
1412 Value es, rs;
1413 int i, size;
1414 enode *p;
1416 value_init(es);
1417 value_init(rs);
1418 value_set_si(es, e1->x.p->size);
1419 value_set_si(rs, res->x.p->size);
1420 value_lcm(rs, es, rs);
1421 size = (int)mpz_get_si(rs);
1422 value_clear(es);
1423 value_clear(rs);
1424 p = new_enode(periodic, size, e1->x.p->pos);
1425 for (i = 0; i < res->x.p->size; i++) {
1426 value_clear(p->arr[i].d);
1427 p->arr[i] = res->x.p->arr[i];
1429 for (i = res->x.p->size; i < size; i++)
1430 evalue_copy(&p->arr[i], &res->x.p->arr[i % res->x.p->size]);
1431 for (i = 0; i < size; i++)
1432 op(&e1->x.p->arr[i % e1->x.p->size], &p->arr[i]);
1433 free(res->x.p);
1434 res->x.p = p;
1437 static void eadd_periodics(const evalue *e1, evalue *res)
1439 int i;
1440 int x, y, p;
1441 evalue *ne;
1443 if (e1->x.p->size == res->x.p->size) {
1444 eadd_arrays(e1, res, e1->x.p->size);
1445 return;
1448 combine_periodics(e1, res, eadd);
1451 void evalue_assign(evalue *dst, const evalue *src)
1453 if (value_pos_p(dst->d) && value_pos_p(src->d)) {
1454 value_assign(dst->d, src->d);
1455 value_assign(dst->x.n, src->x.n);
1456 return;
1458 free_evalue_refs(dst);
1459 value_init(dst->d);
1460 evalue_copy(dst, src);
1463 void eadd(const evalue *e1, evalue *res)
1465 int cmp;
1467 if (EVALUE_IS_ZERO(*e1))
1468 return;
1470 if (EVALUE_IS_NAN(*res))
1471 return;
1473 if (EVALUE_IS_NAN(*e1)) {
1474 evalue_assign(res, e1);
1475 return;
1478 if (EVALUE_IS_ZERO(*res)) {
1479 evalue_assign(res, e1);
1480 return;
1483 cmp = evalue_level_cmp(res, e1);
1484 if (cmp > 0) {
1485 switch (e1->x.p->type) {
1486 case polynomial:
1487 case flooring:
1488 case fractional:
1489 eadd_rev_cst(e1, res);
1490 break;
1491 default:
1492 eadd_rev(e1, res);
1494 } else if (cmp == 0) {
1495 if (value_notzero_p(e1->d)) {
1496 eadd_rationals(e1, res);
1497 } else {
1498 switch (e1->x.p->type) {
1499 case partition:
1500 eadd_partitions(e1, res);
1501 break;
1502 case relation:
1503 eadd_relations(e1, res);
1504 break;
1505 case evector:
1506 assert(e1->x.p->size == res->x.p->size);
1507 case polynomial:
1508 case flooring:
1509 case fractional:
1510 eadd_poly(e1, res);
1511 break;
1512 case periodic:
1513 eadd_periodics(e1, res);
1514 break;
1515 default:
1516 assert(0);
1519 } else {
1520 int i;
1521 switch (res->x.p->type) {
1522 case polynomial:
1523 case flooring:
1524 case fractional:
1525 /* Add to the constant term of a polynomial */
1526 eadd(e1, &res->x.p->arr[type_offset(res->x.p)]);
1527 break;
1528 case periodic:
1529 /* Add to all elements of a periodic number */
1530 for (i = 0; i < res->x.p->size; i++)
1531 eadd(e1, &res->x.p->arr[i]);
1532 break;
1533 case evector:
1534 fprintf(stderr, "eadd: cannot add const with vector\n");
1535 break;
1536 case partition:
1537 assert(0);
1538 case relation:
1539 /* Create (zero) complement if needed */
1540 if (res->x.p->size < 3)
1541 explicit_complement(res);
1542 for (i = 1; i < res->x.p->size; ++i)
1543 eadd(e1, &res->x.p->arr[i]);
1544 break;
1545 default:
1546 assert(0);
1549 } /* eadd */
1551 static void emul_rev(const evalue *e1, evalue *res)
1553 evalue ev;
1554 value_init(ev.d);
1555 evalue_copy(&ev, e1);
1556 emul(res, &ev);
1557 free_evalue_refs(res);
1558 *res = ev;
1561 static void emul_poly(const evalue *e1, evalue *res)
1563 int i, j, offset = type_offset(res->x.p);
1564 evalue tmp;
1565 enode *p;
1566 int size = (e1->x.p->size + res->x.p->size - offset - 1);
1568 p = new_enode(res->x.p->type, size, res->x.p->pos);
1570 for (i = offset; i < e1->x.p->size-1; ++i)
1571 if (!EVALUE_IS_ZERO(e1->x.p->arr[i]))
1572 break;
1574 /* special case pure power */
1575 if (i == e1->x.p->size-1) {
1576 if (offset) {
1577 value_clear(p->arr[0].d);
1578 p->arr[0] = res->x.p->arr[0];
1580 for (i = offset; i < e1->x.p->size-1; ++i)
1581 evalue_set_si(&p->arr[i], 0, 1);
1582 for (i = offset; i < res->x.p->size; ++i) {
1583 value_clear(p->arr[i+e1->x.p->size-offset-1].d);
1584 p->arr[i+e1->x.p->size-offset-1] = res->x.p->arr[i];
1585 emul(&e1->x.p->arr[e1->x.p->size-1],
1586 &p->arr[i+e1->x.p->size-offset-1]);
1588 free(res->x.p);
1589 res->x.p = p;
1590 return;
1593 value_init(tmp.d);
1594 value_set_si(tmp.d,0);
1595 tmp.x.p = p;
1596 if (offset)
1597 evalue_copy(&p->arr[0], &e1->x.p->arr[0]);
1598 for (i = offset; i < e1->x.p->size; i++) {
1599 evalue_copy(&tmp.x.p->arr[i], &e1->x.p->arr[i]);
1600 emul(&res->x.p->arr[offset], &tmp.x.p->arr[i]);
1602 for (; i<size; i++)
1603 evalue_set_si(&tmp.x.p->arr[i], 0, 1);
1604 for (i = offset+1; i<res->x.p->size; i++)
1605 for (j = offset; j<e1->x.p->size; j++) {
1606 evalue ev;
1607 value_init(ev.d);
1608 evalue_copy(&ev, &e1->x.p->arr[j]);
1609 emul(&res->x.p->arr[i], &ev);
1610 eadd(&ev, &tmp.x.p->arr[i+j-offset]);
1611 free_evalue_refs(&ev);
1613 free_evalue_refs(res);
1614 *res = tmp;
1617 void emul_partitions(const evalue *e1, evalue *res)
1619 int n, i, j, k;
1620 Polyhedron *d;
1621 struct section *s;
1622 s = (struct section *)
1623 malloc((e1->x.p->size/2) * (res->x.p->size/2) *
1624 sizeof(struct section));
1625 assert(s);
1626 assert(e1->x.p->pos == res->x.p->pos);
1627 assert(e1->x.p->pos == EVALUE_DOMAIN(e1->x.p->arr[0])->Dimension);
1628 assert(res->x.p->pos == EVALUE_DOMAIN(res->x.p->arr[0])->Dimension);
1630 n = 0;
1631 for (i = 0; i < res->x.p->size/2; ++i) {
1632 for (j = 0; j < e1->x.p->size/2; ++j) {
1633 d = DomainIntersection(EVALUE_DOMAIN(e1->x.p->arr[2*j]),
1634 EVALUE_DOMAIN(res->x.p->arr[2*i]), 0);
1635 d = DomainConstraintSimplify(d, 0);
1636 if (emptyQ(d)) {
1637 Domain_Free(d);
1638 continue;
1641 /* This code is only needed because the partitions
1642 are not true partitions.
1644 for (k = 0; k < n; ++k) {
1645 if (DomainIncludes(s[k].D, d))
1646 break;
1647 if (DomainIncludes(d, s[k].D)) {
1648 Domain_Free(s[k].D);
1649 free_evalue_refs(&s[k].E);
1650 if (n > k)
1651 s[k] = s[--n];
1652 --k;
1655 if (k < n) {
1656 Domain_Free(d);
1657 continue;
1660 value_init(s[n].E.d);
1661 evalue_copy(&s[n].E, &res->x.p->arr[2*i+1]);
1662 emul(&e1->x.p->arr[2*j+1], &s[n].E);
1663 s[n].D = d;
1664 ++n;
1666 Domain_Free(EVALUE_DOMAIN(res->x.p->arr[2*i]));
1667 value_clear(res->x.p->arr[2*i].d);
1668 free_evalue_refs(&res->x.p->arr[2*i+1]);
1671 free(res->x.p);
1672 if (n == 0)
1673 evalue_set_si(res, 0, 1);
1674 else {
1675 res->x.p = new_enode(partition, 2*n, e1->x.p->pos);
1676 for (j = 0; j < n; ++j) {
1677 EVALUE_SET_DOMAIN(res->x.p->arr[2*j], s[j].D);
1678 value_clear(res->x.p->arr[2*j+1].d);
1679 res->x.p->arr[2*j+1] = s[j].E;
1683 free(s);
1686 /* Product of two rational numbers */
1687 static void emul_rationals(const evalue *e1, evalue *res)
1689 value_multiply(res->d, e1->d, res->d);
1690 value_multiply(res->x.n, e1->x.n, res->x.n);
1691 reduce_constant(res);
1694 static void emul_relations(const evalue *e1, evalue *res)
1696 int i;
1698 if (e1->x.p->size < 3 && res->x.p->size == 3) {
1699 free_evalue_refs(&res->x.p->arr[2]);
1700 res->x.p->size = 2;
1702 for (i = 1; i < res->x.p->size; ++i)
1703 emul(&e1->x.p->arr[i], &res->x.p->arr[i]);
1706 static void emul_periodics(const evalue *e1, evalue *res)
1708 int i;
1709 evalue *newp;
1710 Value x, y, z;
1711 int ix, iy, lcm;
1713 if (e1->x.p->size == res->x.p->size) {
1714 /* Product of two periodics of the same parameter and period */
1715 for (i = 0; i < res->x.p->size; i++)
1716 emul(&(e1->x.p->arr[i]), &(res->x.p->arr[i]));
1717 return;
1720 combine_periodics(e1, res, emul);
1723 /* Multiply two polynomial expressions in the same fractional part.
1725 * If the denominator of the fractional part is two, then the fractional
1726 * part can only take on two values, 0 and 1/2.
1727 * This means that { f(x)/2 }^2 = 1/2 { f(x)/2 } so that
1729 * (a0 + a1 { f(x)/2 }) * (b0 + b1 { f(x)/2 })
1730 * = a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { f(x)/2 }
1732 * Since we can always reduce higher degree polynomials this way
1733 * we assume that the inputs are degree-1 polynomials.
1734 * Note in particular that we always start out with degree-1 polynomials
1735 * and that if we obtain an argument with a denominator of two
1736 * as a result of a substitution, then the polynomial expression
1737 * is reduced in reduce_fractional.
1739 static void emul_fractionals(const evalue *e1, evalue *res)
1741 evalue d;
1742 value_init(d.d);
1743 poly_denom(&e1->x.p->arr[0], &d.d);
1744 if (!value_two_p(d.d))
1745 emul_poly(e1, res);
1746 else {
1747 evalue tmp;
1748 value_init(d.x.n);
1749 value_set_si(d.x.n, 1);
1750 /* { x }^2 == { x }/2 */
1751 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1752 assert(e1->x.p->size == 3);
1753 assert(res->x.p->size == 3);
1754 value_init(tmp.d);
1755 evalue_copy(&tmp, &res->x.p->arr[2]);
1756 emul(&d, &tmp);
1757 eadd(&res->x.p->arr[1], &tmp);
1758 emul(&e1->x.p->arr[2], &tmp);
1759 emul(&e1->x.p->arr[1], &res->x.p->arr[1]);
1760 emul(&e1->x.p->arr[1], &res->x.p->arr[2]);
1761 eadd(&tmp, &res->x.p->arr[2]);
1762 free_evalue_refs(&tmp);
1763 value_clear(d.x.n);
1765 value_clear(d.d);
1768 /* Computes the product of two evalues "e1" and "res" and puts
1769 * the result in "res". You need to make a copy of "res"
1770 * before calling this function if you still need it afterward.
1771 * The vector type of evalues is not treated here
1773 void emul(const evalue *e1, evalue *res)
1775 int cmp;
1777 assert(!(value_zero_p(e1->d) && e1->x.p->type == evector));
1778 assert(!(value_zero_p(res->d) && res->x.p->type == evector));
1780 if (EVALUE_IS_ZERO(*res))
1781 return;
1783 if (EVALUE_IS_ONE(*e1))
1784 return;
1786 if (EVALUE_IS_ZERO(*e1)) {
1787 evalue_assign(res, e1);
1788 return;
1791 if (EVALUE_IS_NAN(*res))
1792 return;
1794 if (EVALUE_IS_NAN(*e1)) {
1795 evalue_assign(res, e1);
1796 return;
1799 cmp = evalue_level_cmp(res, e1);
1800 if (cmp > 0) {
1801 emul_rev(e1, res);
1802 } else if (cmp == 0) {
1803 if (value_notzero_p(e1->d)) {
1804 emul_rationals(e1, res);
1805 } else {
1806 switch (e1->x.p->type) {
1807 case partition:
1808 emul_partitions(e1, res);
1809 break;
1810 case relation:
1811 emul_relations(e1, res);
1812 break;
1813 case polynomial:
1814 case flooring:
1815 emul_poly(e1, res);
1816 break;
1817 case periodic:
1818 emul_periodics(e1, res);
1819 break;
1820 case fractional:
1821 emul_fractionals(e1, res);
1822 break;
1825 } else {
1826 int i;
1827 switch (res->x.p->type) {
1828 case partition:
1829 for (i = 0; i < res->x.p->size/2; ++i)
1830 emul(e1, &res->x.p->arr[2*i+1]);
1831 break;
1832 case relation:
1833 case polynomial:
1834 case periodic:
1835 case flooring:
1836 case fractional:
1837 for (i = type_offset(res->x.p); i < res->x.p->size; ++i)
1838 emul(e1, &res->x.p->arr[i]);
1839 break;
1844 /* Frees mask content ! */
1845 void emask(evalue *mask, evalue *res) {
1846 int n, i, j;
1847 Polyhedron *d, *fd;
1848 struct section *s;
1849 evalue mone;
1850 int pos;
1852 if (EVALUE_IS_ZERO(*res)) {
1853 free_evalue_refs(mask);
1854 return;
1857 assert(value_zero_p(mask->d));
1858 assert(mask->x.p->type == partition);
1859 assert(value_zero_p(res->d));
1860 assert(res->x.p->type == partition);
1861 assert(mask->x.p->pos == res->x.p->pos);
1862 assert(res->x.p->pos == EVALUE_DOMAIN(res->x.p->arr[0])->Dimension);
1863 assert(mask->x.p->pos == EVALUE_DOMAIN(mask->x.p->arr[0])->Dimension);
1864 pos = res->x.p->pos;
1866 s = (struct section *)
1867 malloc((mask->x.p->size/2+1) * (res->x.p->size/2) *
1868 sizeof(struct section));
1869 assert(s);
1871 value_init(mone.d);
1872 evalue_set_si(&mone, -1, 1);
1874 n = 0;
1875 for (j = 0; j < res->x.p->size/2; ++j) {
1876 assert(mask->x.p->size >= 2);
1877 fd = DomainDifference(EVALUE_DOMAIN(res->x.p->arr[2*j]),
1878 EVALUE_DOMAIN(mask->x.p->arr[0]), 0);
1879 if (!emptyQ(fd))
1880 for (i = 1; i < mask->x.p->size/2; ++i) {
1881 Polyhedron *t = fd;
1882 fd = DomainDifference(fd, EVALUE_DOMAIN(mask->x.p->arr[2*i]), 0);
1883 Domain_Free(t);
1884 if (emptyQ(fd))
1885 break;
1887 if (emptyQ(fd)) {
1888 Domain_Free(fd);
1889 continue;
1891 value_init(s[n].E.d);
1892 evalue_copy(&s[n].E, &res->x.p->arr[2*j+1]);
1893 s[n].D = fd;
1894 ++n;
1896 for (i = 0; i < mask->x.p->size/2; ++i) {
1897 if (EVALUE_IS_ONE(mask->x.p->arr[2*i+1]))
1898 continue;
1900 fd = EVALUE_DOMAIN(mask->x.p->arr[2*i]);
1901 eadd(&mone, &mask->x.p->arr[2*i+1]);
1902 emul(&mone, &mask->x.p->arr[2*i+1]);
1903 for (j = 0; j < res->x.p->size/2; ++j) {
1904 Polyhedron *t;
1905 d = DomainIntersection(EVALUE_DOMAIN(res->x.p->arr[2*j]),
1906 EVALUE_DOMAIN(mask->x.p->arr[2*i]), 0);
1907 if (emptyQ(d)) {
1908 Domain_Free(d);
1909 continue;
1911 t = fd;
1912 fd = DomainDifference(fd, EVALUE_DOMAIN(res->x.p->arr[2*j]), 0);
1913 if (t != EVALUE_DOMAIN(mask->x.p->arr[2*i]))
1914 Domain_Free(t);
1915 value_init(s[n].E.d);
1916 evalue_copy(&s[n].E, &res->x.p->arr[2*j+1]);
1917 emul(&mask->x.p->arr[2*i+1], &s[n].E);
1918 s[n].D = d;
1919 ++n;
1922 if (!emptyQ(fd)) {
1923 /* Just ignore; this may have been previously masked off */
1925 if (fd != EVALUE_DOMAIN(mask->x.p->arr[2*i]))
1926 Domain_Free(fd);
1929 free_evalue_refs(&mone);
1930 free_evalue_refs(mask);
1931 free_evalue_refs(res);
1932 value_init(res->d);
1933 if (n == 0)
1934 evalue_set_si(res, 0, 1);
1935 else {
1936 res->x.p = new_enode(partition, 2*n, pos);
1937 for (j = 0; j < n; ++j) {
1938 EVALUE_SET_DOMAIN(res->x.p->arr[2*j], s[j].D);
1939 value_clear(res->x.p->arr[2*j+1].d);
1940 res->x.p->arr[2*j+1] = s[j].E;
1944 free(s);
1947 void evalue_copy(evalue *dst, const evalue *src)
1949 value_assign(dst->d, src->d);
1950 if (EVALUE_IS_NAN(*dst)) {
1951 dst->x.p = NULL;
1952 return;
1954 if (value_pos_p(src->d)) {
1955 value_init(dst->x.n);
1956 value_assign(dst->x.n, src->x.n);
1957 } else
1958 dst->x.p = ecopy(src->x.p);
1961 evalue *evalue_dup(const evalue *e)
1963 evalue *res = ALLOC(evalue);
1964 value_init(res->d);
1965 evalue_copy(res, e);
1966 return res;
1969 enode *new_enode(enode_type type,int size,int pos) {
1971 enode *res;
1972 int i;
1974 if(size == 0) {
1975 fprintf(stderr, "Allocating enode of size 0 !\n" );
1976 return NULL;
1978 res = (enode *) malloc(sizeof(enode) + (size-1)*sizeof(evalue));
1979 res->type = type;
1980 res->size = size;
1981 res->pos = pos;
1982 for(i=0; i<size; i++) {
1983 value_init(res->arr[i].d);
1984 value_set_si(res->arr[i].d,0);
1985 res->arr[i].x.p = 0;
1987 return res;
1988 } /* new_enode */
1990 enode *ecopy(enode *e) {
1992 enode *res;
1993 int i;
1995 res = new_enode(e->type,e->size,e->pos);
1996 for(i=0;i<e->size;++i) {
1997 value_assign(res->arr[i].d,e->arr[i].d);
1998 if(value_zero_p(res->arr[i].d))
1999 res->arr[i].x.p = ecopy(e->arr[i].x.p);
2000 else if (EVALUE_IS_DOMAIN(res->arr[i]))
2001 EVALUE_SET_DOMAIN(res->arr[i], Domain_Copy(EVALUE_DOMAIN(e->arr[i])));
2002 else {
2003 value_init(res->arr[i].x.n);
2004 value_assign(res->arr[i].x.n,e->arr[i].x.n);
2007 return(res);
2008 } /* ecopy */
2010 int ecmp(const evalue *e1, const evalue *e2)
2012 enode *p1, *p2;
2013 int i;
2014 int r;
2016 if (value_notzero_p(e1->d) && value_notzero_p(e2->d)) {
2017 Value m, m2;
2018 value_init(m);
2019 value_init(m2);
2020 value_multiply(m, e1->x.n, e2->d);
2021 value_multiply(m2, e2->x.n, e1->d);
2023 if (value_lt(m, m2))
2024 r = -1;
2025 else if (value_gt(m, m2))
2026 r = 1;
2027 else
2028 r = 0;
2030 value_clear(m);
2031 value_clear(m2);
2033 return r;
2035 if (value_notzero_p(e1->d))
2036 return -1;
2037 if (value_notzero_p(e2->d))
2038 return 1;
2040 p1 = e1->x.p;
2041 p2 = e2->x.p;
2043 if (p1->type != p2->type)
2044 return p1->type - p2->type;
2045 if (p1->pos != p2->pos)
2046 return p1->pos - p2->pos;
2047 if (p1->size != p2->size)
2048 return p1->size - p2->size;
2050 for (i = p1->size-1; i >= 0; --i)
2051 if ((r = ecmp(&p1->arr[i], &p2->arr[i])) != 0)
2052 return r;
2054 return 0;
2057 int eequal(const evalue *e1, const evalue *e2)
2059 int i;
2060 enode *p1, *p2;
2062 if (value_ne(e1->d,e2->d))
2063 return 0;
2065 if (EVALUE_IS_DOMAIN(*e1))
2066 return PolyhedronIncludes(EVALUE_DOMAIN(*e2), EVALUE_DOMAIN(*e1)) &&
2067 PolyhedronIncludes(EVALUE_DOMAIN(*e1), EVALUE_DOMAIN(*e2));
2069 if (EVALUE_IS_NAN(*e1))
2070 return 1;
2072 assert(value_posz_p(e1->d));
2074 /* e1->d == e2->d */
2075 if (value_notzero_p(e1->d)) {
2076 if (value_ne(e1->x.n,e2->x.n))
2077 return 0;
2079 /* e1->d == e2->d != 0 AND e1->n == e2->n */
2080 return 1;
2083 /* e1->d == e2->d == 0 */
2084 p1 = e1->x.p;
2085 p2 = e2->x.p;
2086 if (p1->type != p2->type) return 0;
2087 if (p1->size != p2->size) return 0;
2088 if (p1->pos != p2->pos) return 0;
2089 for (i=0; i<p1->size; i++)
2090 if (!eequal(&p1->arr[i], &p2->arr[i]) )
2091 return 0;
2092 return 1;
2093 } /* eequal */
2095 void free_evalue_refs(evalue *e) {
2097 enode *p;
2098 int i;
2100 if (EVALUE_IS_NAN(*e)) {
2101 value_clear(e->d);
2102 return;
2105 if (EVALUE_IS_DOMAIN(*e)) {
2106 Domain_Free(EVALUE_DOMAIN(*e));
2107 value_clear(e->d);
2108 return;
2109 } else if (value_pos_p(e->d)) {
2111 /* 'e' stores a constant */
2112 value_clear(e->d);
2113 value_clear(e->x.n);
2114 return;
2116 assert(value_zero_p(e->d));
2117 value_clear(e->d);
2118 p = e->x.p;
2119 if (!p) return; /* null pointer */
2120 for (i=0; i<p->size; i++) {
2121 free_evalue_refs(&(p->arr[i]));
2123 free(p);
2124 return;
2125 } /* free_evalue_refs */
2127 void evalue_free(evalue *e)
2129 free_evalue_refs(e);
2130 free(e);
2133 static void mod2table_r(evalue *e, Vector *periods, Value m, int p,
2134 Vector * val, evalue *res)
2136 unsigned nparam = periods->Size;
2138 if (p == nparam) {
2139 double d = compute_evalue(e, val->p);
2140 d *= VALUE_TO_DOUBLE(m);
2141 if (d > 0)
2142 d += .25;
2143 else
2144 d -= .25;
2145 value_assign(res->d, m);
2146 value_init(res->x.n);
2147 value_set_double(res->x.n, d);
2148 mpz_fdiv_r(res->x.n, res->x.n, m);
2149 return;
2151 if (value_one_p(periods->p[p]))
2152 mod2table_r(e, periods, m, p+1, val, res);
2153 else {
2154 Value tmp;
2155 value_init(tmp);
2157 value_assign(tmp, periods->p[p]);
2158 value_set_si(res->d, 0);
2159 res->x.p = new_enode(periodic, VALUE_TO_INT(tmp), p+1);
2160 do {
2161 value_decrement(tmp, tmp);
2162 value_assign(val->p[p], tmp);
2163 mod2table_r(e, periods, m, p+1, val,
2164 &res->x.p->arr[VALUE_TO_INT(tmp)]);
2165 } while (value_pos_p(tmp));
2167 value_clear(tmp);
2171 static void rel2table(evalue *e, int zero)
2173 if (value_pos_p(e->d)) {
2174 if (value_zero_p(e->x.n) == zero)
2175 value_set_si(e->x.n, 1);
2176 else
2177 value_set_si(e->x.n, 0);
2178 value_set_si(e->d, 1);
2179 } else {
2180 int i;
2181 for (i = 0; i < e->x.p->size; ++i)
2182 rel2table(&e->x.p->arr[i], zero);
2186 void evalue_mod2table(evalue *e, int nparam)
2188 enode *p;
2189 int i;
2191 if (EVALUE_IS_DOMAIN(*e) || value_pos_p(e->d))
2192 return;
2193 p = e->x.p;
2194 for (i=0; i<p->size; i++) {
2195 evalue_mod2table(&(p->arr[i]), nparam);
2197 if (p->type == relation) {
2198 evalue copy;
2200 if (p->size > 2) {
2201 value_init(copy.d);
2202 evalue_copy(&copy, &p->arr[0]);
2204 rel2table(&p->arr[0], 1);
2205 emul(&p->arr[0], &p->arr[1]);
2206 if (p->size > 2) {
2207 rel2table(&copy, 0);
2208 emul(&copy, &p->arr[2]);
2209 eadd(&p->arr[2], &p->arr[1]);
2210 free_evalue_refs(&p->arr[2]);
2211 free_evalue_refs(&copy);
2213 free_evalue_refs(&p->arr[0]);
2214 value_clear(e->d);
2215 *e = p->arr[1];
2216 free(p);
2217 } else if (p->type == fractional) {
2218 Vector *periods = Vector_Alloc(nparam);
2219 Vector *val = Vector_Alloc(nparam);
2220 Value tmp;
2221 evalue *ev;
2222 evalue EP, res;
2224 value_init(tmp);
2225 value_set_si(tmp, 1);
2226 Vector_Set(periods->p, 1, nparam);
2227 Vector_Set(val->p, 0, nparam);
2228 for (ev = &p->arr[0]; value_zero_p(ev->d); ev = &ev->x.p->arr[0]) {
2229 enode *p = ev->x.p;
2231 assert(p->type == polynomial);
2232 assert(p->size == 2);
2233 value_assign(periods->p[p->pos-1], p->arr[1].d);
2234 value_lcm(tmp, tmp, p->arr[1].d);
2236 value_lcm(tmp, tmp, ev->d);
2237 value_init(EP.d);
2238 mod2table_r(&p->arr[0], periods, tmp, 0, val, &EP);
2240 value_init(res.d);
2241 evalue_set_si(&res, 0, 1);
2242 /* Compute the polynomial using Horner's rule */
2243 for (i=p->size-1;i>1;i--) {
2244 eadd(&p->arr[i], &res);
2245 emul(&EP, &res);
2247 eadd(&p->arr[1], &res);
2249 free_evalue_refs(e);
2250 free_evalue_refs(&EP);
2251 *e = res;
2253 value_clear(tmp);
2254 Vector_Free(val);
2255 Vector_Free(periods);
2257 } /* evalue_mod2table */
2259 /********************************************************/
2260 /* function in domain */
2261 /* check if the parameters in list_args */
2262 /* verifies the constraints of Domain P */
2263 /********************************************************/
2264 int in_domain(Polyhedron *P, Value *list_args)
2266 int row, in = 1;
2267 Value v; /* value of the constraint of a row when
2268 parameters are instantiated*/
2270 if (P->Dimension == 0)
2271 return !emptyQ(P);
2273 value_init(v);
2275 for (row = 0; row < P->NbConstraints; row++) {
2276 Inner_Product(P->Constraint[row]+1, list_args, P->Dimension, &v);
2277 value_addto(v, v, P->Constraint[row][P->Dimension+1]); /*constant part*/
2278 if (value_neg_p(v) ||
2279 (value_zero_p(P->Constraint[row][0]) && value_notzero_p(v))) {
2280 in = 0;
2281 break;
2285 value_clear(v);
2286 return in || (P->next && in_domain(P->next, list_args));
2287 } /* in_domain */
2289 /****************************************************/
2290 /* function compute enode */
2291 /* compute the value of enode p with parameters */
2292 /* list "list_args */
2293 /* compute the polynomial or the periodic */
2294 /****************************************************/
2296 static double compute_enode(enode *p, Value *list_args) {
2298 int i;
2299 Value m, param;
2300 double res=0.0;
2302 if (!p)
2303 return(0.);
2305 value_init(m);
2306 value_init(param);
2308 if (p->type == polynomial) {
2309 if (p->size > 1)
2310 value_assign(param,list_args[p->pos-1]);
2312 /* Compute the polynomial using Horner's rule */
2313 for (i=p->size-1;i>0;i--) {
2314 res +=compute_evalue(&p->arr[i],list_args);
2315 res *=VALUE_TO_DOUBLE(param);
2317 res +=compute_evalue(&p->arr[0],list_args);
2319 else if (p->type == fractional) {
2320 double d = compute_evalue(&p->arr[0], list_args);
2321 d -= floor(d+1e-10);
2323 /* Compute the polynomial using Horner's rule */
2324 for (i=p->size-1;i>1;i--) {
2325 res +=compute_evalue(&p->arr[i],list_args);
2326 res *=d;
2328 res +=compute_evalue(&p->arr[1],list_args);
2330 else if (p->type == flooring) {
2331 double d = compute_evalue(&p->arr[0], list_args);
2332 d = floor(d+1e-10);
2334 /* Compute the polynomial using Horner's rule */
2335 for (i=p->size-1;i>1;i--) {
2336 res +=compute_evalue(&p->arr[i],list_args);
2337 res *=d;
2339 res +=compute_evalue(&p->arr[1],list_args);
2341 else if (p->type == periodic) {
2342 value_assign(m,list_args[p->pos-1]);
2344 /* Choose the right element of the periodic */
2345 value_set_si(param,p->size);
2346 value_pmodulus(m,m,param);
2347 res = compute_evalue(&p->arr[VALUE_TO_INT(m)],list_args);
2349 else if (p->type == relation) {
2350 if (fabs(compute_evalue(&p->arr[0], list_args)) < 1e-10)
2351 res = compute_evalue(&p->arr[1], list_args);
2352 else if (p->size > 2)
2353 res = compute_evalue(&p->arr[2], list_args);
2355 else if (p->type == partition) {
2356 int dim = EVALUE_DOMAIN(p->arr[0])->Dimension;
2357 Value *vals = list_args;
2358 if (p->pos < dim) {
2359 NALLOC(vals, dim);
2360 for (i = 0; i < dim; ++i) {
2361 value_init(vals[i]);
2362 if (i < p->pos)
2363 value_assign(vals[i], list_args[i]);
2366 for (i = 0; i < p->size/2; ++i)
2367 if (DomainContains(EVALUE_DOMAIN(p->arr[2*i]), vals, p->pos, 0, 1)) {
2368 res = compute_evalue(&p->arr[2*i+1], vals);
2369 break;
2371 if (p->pos < dim) {
2372 for (i = 0; i < dim; ++i)
2373 value_clear(vals[i]);
2374 free(vals);
2377 else
2378 assert(0);
2379 value_clear(m);
2380 value_clear(param);
2381 return res;
2382 } /* compute_enode */
2384 /*************************************************/
2385 /* return the value of Ehrhart Polynomial */
2386 /* It returns a double, because since it is */
2387 /* a recursive function, some intermediate value */
2388 /* might not be integral */
2389 /*************************************************/
2391 double compute_evalue(const evalue *e, Value *list_args)
2393 double res;
2395 if (value_notzero_p(e->d)) {
2396 if (value_notone_p(e->d))
2397 res = VALUE_TO_DOUBLE(e->x.n) / VALUE_TO_DOUBLE(e->d);
2398 else
2399 res = VALUE_TO_DOUBLE(e->x.n);
2401 else
2402 res = compute_enode(e->x.p,list_args);
2403 return res;
2404 } /* compute_evalue */
2407 /****************************************************/
2408 /* function compute_poly : */
2409 /* Check for the good validity domain */
2410 /* return the number of point in the Polyhedron */
2411 /* in allocated memory */
2412 /* Using the Ehrhart pseudo-polynomial */
2413 /****************************************************/
2414 Value *compute_poly(Enumeration *en,Value *list_args) {
2416 Value *tmp;
2417 /* double d; int i; */
2419 tmp = (Value *) malloc (sizeof(Value));
2420 assert(tmp != NULL);
2421 value_init(*tmp);
2422 value_set_si(*tmp,0);
2424 if(!en)
2425 return(tmp); /* no ehrhart polynomial */
2426 if(en->ValidityDomain) {
2427 if(!en->ValidityDomain->Dimension) { /* no parameters */
2428 value_set_double(*tmp,compute_evalue(&en->EP,list_args)+.25);
2429 return(tmp);
2432 else
2433 return(tmp); /* no Validity Domain */
2434 while(en) {
2435 if(in_domain(en->ValidityDomain,list_args)) {
2437 #ifdef EVAL_EHRHART_DEBUG
2438 Print_Domain(stdout,en->ValidityDomain);
2439 print_evalue(stdout,&en->EP);
2440 #endif
2442 /* d = compute_evalue(&en->EP,list_args);
2443 i = d;
2444 printf("(double)%lf = %d\n", d, i ); */
2445 value_set_double(*tmp,compute_evalue(&en->EP,list_args)+.25);
2446 return(tmp);
2448 else
2449 en=en->next;
2451 value_set_si(*tmp,0);
2452 return(tmp); /* no compatible domain with the arguments */
2453 } /* compute_poly */
2455 static evalue *eval_polynomial(const enode *p, int offset,
2456 evalue *base, Value *values)
2458 int i;
2459 evalue *res, *c;
2461 res = evalue_zero();
2462 for (i = p->size-1; i > offset; --i) {
2463 c = evalue_eval(&p->arr[i], values);
2464 eadd(c, res);
2465 evalue_free(c);
2466 emul(base, res);
2468 c = evalue_eval(&p->arr[offset], values);
2469 eadd(c, res);
2470 evalue_free(c);
2472 return res;
2475 evalue *evalue_eval(const evalue *e, Value *values)
2477 evalue *res = NULL;
2478 evalue param;
2479 evalue *param2;
2480 int i;
2482 if (value_notzero_p(e->d)) {
2483 res = ALLOC(evalue);
2484 value_init(res->d);
2485 evalue_copy(res, e);
2486 return res;
2488 switch (e->x.p->type) {
2489 case polynomial:
2490 value_init(param.x.n);
2491 value_assign(param.x.n, values[e->x.p->pos-1]);
2492 value_init(param.d);
2493 value_set_si(param.d, 1);
2495 res = eval_polynomial(e->x.p, 0, &param, values);
2496 free_evalue_refs(&param);
2497 break;
2498 case fractional:
2499 param2 = evalue_eval(&e->x.p->arr[0], values);
2500 mpz_fdiv_r(param2->x.n, param2->x.n, param2->d);
2502 res = eval_polynomial(e->x.p, 1, param2, values);
2503 evalue_free(param2);
2504 break;
2505 case flooring:
2506 param2 = evalue_eval(&e->x.p->arr[0], values);
2507 mpz_fdiv_q(param2->x.n, param2->x.n, param2->d);
2508 value_set_si(param2->d, 1);
2510 res = eval_polynomial(e->x.p, 1, param2, values);
2511 evalue_free(param2);
2512 break;
2513 case relation:
2514 param2 = evalue_eval(&e->x.p->arr[0], values);
2515 if (value_zero_p(param2->x.n))
2516 res = evalue_eval(&e->x.p->arr[1], values);
2517 else if (e->x.p->size > 2)
2518 res = evalue_eval(&e->x.p->arr[2], values);
2519 else
2520 res = evalue_zero();
2521 evalue_free(param2);
2522 break;
2523 case partition:
2524 assert(e->x.p->pos == EVALUE_DOMAIN(e->x.p->arr[0])->Dimension);
2525 for (i = 0; i < e->x.p->size/2; ++i)
2526 if (in_domain(EVALUE_DOMAIN(e->x.p->arr[2*i]), values)) {
2527 res = evalue_eval(&e->x.p->arr[2*i+1], values);
2528 break;
2530 if (!res)
2531 res = evalue_zero();
2532 break;
2533 default:
2534 assert(0);
2536 return res;
2539 size_t value_size(Value v) {
2540 return (v[0]._mp_size > 0 ? v[0]._mp_size : -v[0]._mp_size)
2541 * sizeof(v[0]._mp_d[0]);
2544 size_t domain_size(Polyhedron *D)
2546 int i, j;
2547 size_t s = sizeof(*D);
2549 for (i = 0; i < D->NbConstraints; ++i)
2550 for (j = 0; j < D->Dimension+2; ++j)
2551 s += value_size(D->Constraint[i][j]);
2554 for (i = 0; i < D->NbRays; ++i)
2555 for (j = 0; j < D->Dimension+2; ++j)
2556 s += value_size(D->Ray[i][j]);
2559 return D->next ? s+domain_size(D->next) : s;
2562 size_t enode_size(enode *p) {
2563 size_t s = sizeof(*p) - sizeof(p->arr[0]);
2564 int i;
2566 if (p->type == partition)
2567 for (i = 0; i < p->size/2; ++i) {
2568 s += domain_size(EVALUE_DOMAIN(p->arr[2*i]));
2569 s += evalue_size(&p->arr[2*i+1]);
2571 else
2572 for (i = 0; i < p->size; ++i) {
2573 s += evalue_size(&p->arr[i]);
2575 return s;
2578 size_t evalue_size(evalue *e)
2580 size_t s = sizeof(*e);
2581 s += value_size(e->d);
2582 if (value_notzero_p(e->d))
2583 s += value_size(e->x.n);
2584 else
2585 s += enode_size(e->x.p);
2586 return s;
2589 static evalue *find_second(evalue *base, evalue *cst, evalue *e, Value m)
2591 evalue *found = NULL;
2592 evalue offset;
2593 evalue copy;
2594 int i;
2596 if (value_pos_p(e->d) || e->x.p->type != fractional)
2597 return NULL;
2599 value_init(offset.d);
2600 value_init(offset.x.n);
2601 poly_denom(&e->x.p->arr[0], &offset.d);
2602 value_lcm(offset.d, m, offset.d);
2603 value_set_si(offset.x.n, 1);
2605 value_init(copy.d);
2606 evalue_copy(&copy, cst);
2608 eadd(&offset, cst);
2609 mpz_fdiv_r(cst->x.n, cst->x.n, cst->d);
2611 if (eequal(base, &e->x.p->arr[0]))
2612 found = &e->x.p->arr[0];
2613 else {
2614 value_set_si(offset.x.n, -2);
2616 eadd(&offset, cst);
2617 mpz_fdiv_r(cst->x.n, cst->x.n, cst->d);
2619 if (eequal(base, &e->x.p->arr[0]))
2620 found = base;
2622 free_evalue_refs(cst);
2623 free_evalue_refs(&offset);
2624 *cst = copy;
2626 for (i = 1; !found && i < e->x.p->size; ++i)
2627 found = find_second(base, cst, &e->x.p->arr[i], m);
2629 return found;
2632 static evalue *find_relation_pair(evalue *e)
2634 int i;
2635 evalue *found = NULL;
2637 if (EVALUE_IS_DOMAIN(*e) || value_pos_p(e->d))
2638 return NULL;
2640 if (e->x.p->type == fractional) {
2641 Value m;
2642 evalue *cst;
2644 value_init(m);
2645 poly_denom(&e->x.p->arr[0], &m);
2647 for (cst = &e->x.p->arr[0]; value_zero_p(cst->d);
2648 cst = &cst->x.p->arr[0])
2651 for (i = 1; !found && i < e->x.p->size; ++i)
2652 found = find_second(&e->x.p->arr[0], cst, &e->x.p->arr[i], m);
2654 value_clear(m);
2657 i = e->x.p->type == relation;
2658 for (; !found && i < e->x.p->size; ++i)
2659 found = find_relation_pair(&e->x.p->arr[i]);
2661 return found;
2664 void evalue_mod2relation(evalue *e) {
2665 evalue *d;
2667 if (value_zero_p(e->d) && e->x.p->type == partition) {
2668 int i;
2670 for (i = 0; i < e->x.p->size/2; ++i) {
2671 evalue_mod2relation(&e->x.p->arr[2*i+1]);
2672 if (EVALUE_IS_ZERO(e->x.p->arr[2*i+1])) {
2673 value_clear(e->x.p->arr[2*i].d);
2674 free_evalue_refs(&e->x.p->arr[2*i+1]);
2675 e->x.p->size -= 2;
2676 if (2*i < e->x.p->size) {
2677 e->x.p->arr[2*i] = e->x.p->arr[e->x.p->size];
2678 e->x.p->arr[2*i+1] = e->x.p->arr[e->x.p->size+1];
2680 --i;
2683 if (e->x.p->size == 0) {
2684 free(e->x.p);
2685 evalue_set_si(e, 0, 1);
2688 return;
2691 while ((d = find_relation_pair(e)) != NULL) {
2692 evalue split;
2693 evalue *ev;
2695 value_init(split.d);
2696 value_set_si(split.d, 0);
2697 split.x.p = new_enode(relation, 3, 0);
2698 evalue_set_si(&split.x.p->arr[1], 1, 1);
2699 evalue_set_si(&split.x.p->arr[2], 1, 1);
2701 ev = &split.x.p->arr[0];
2702 value_set_si(ev->d, 0);
2703 ev->x.p = new_enode(fractional, 3, -1);
2704 evalue_set_si(&ev->x.p->arr[1], 0, 1);
2705 evalue_set_si(&ev->x.p->arr[2], 1, 1);
2706 evalue_copy(&ev->x.p->arr[0], d);
2708 emul(&split, e);
2710 reduce_evalue(e);
2712 free_evalue_refs(&split);
2716 static int evalue_comp(const void * a, const void * b)
2718 const evalue *e1 = *(const evalue **)a;
2719 const evalue *e2 = *(const evalue **)b;
2720 return ecmp(e1, e2);
2723 void evalue_combine(evalue *e)
2725 evalue **evs;
2726 int i, k;
2727 enode *p;
2728 evalue tmp;
2730 if (value_notzero_p(e->d) || e->x.p->type != partition)
2731 return;
2733 NALLOC(evs, e->x.p->size/2);
2734 for (i = 0; i < e->x.p->size/2; ++i)
2735 evs[i] = &e->x.p->arr[2*i+1];
2736 qsort(evs, e->x.p->size/2, sizeof(evs[0]), evalue_comp);
2737 p = new_enode(partition, e->x.p->size, e->x.p->pos);
2738 for (i = 0, k = 0; i < e->x.p->size/2; ++i) {
2739 if (k == 0 || ecmp(&p->arr[2*k-1], evs[i]) != 0) {
2740 value_clear(p->arr[2*k].d);
2741 value_clear(p->arr[2*k+1].d);
2742 p->arr[2*k] = *(evs[i]-1);
2743 p->arr[2*k+1] = *(evs[i]);
2744 ++k;
2745 } else {
2746 Polyhedron *D = EVALUE_DOMAIN(*(evs[i]-1));
2747 Polyhedron *L = D;
2749 value_clear((evs[i]-1)->d);
2751 while (L->next)
2752 L = L->next;
2753 L->next = EVALUE_DOMAIN(p->arr[2*k-2]);
2754 EVALUE_SET_DOMAIN(p->arr[2*k-2], D);
2755 free_evalue_refs(evs[i]);
2759 for (i = 2*k ; i < p->size; ++i)
2760 value_clear(p->arr[i].d);
2762 free(evs);
2763 free(e->x.p);
2764 p->size = 2*k;
2765 e->x.p = p;
2767 for (i = 0; i < e->x.p->size/2; ++i) {
2768 Polyhedron *H;
2769 if (value_notzero_p(e->x.p->arr[2*i+1].d))
2770 continue;
2771 H = DomainConvex(EVALUE_DOMAIN(e->x.p->arr[2*i]), 0);
2772 if (H == NULL)
2773 continue;
2774 for (k = 0; k < e->x.p->size/2; ++k) {
2775 Polyhedron *D, *N, **P;
2776 if (i == k)
2777 continue;
2778 P = &EVALUE_DOMAIN(e->x.p->arr[2*k]);
2779 D = *P;
2780 if (D == NULL)
2781 continue;
2782 for (; D; D = N) {
2783 *P = D;
2784 N = D->next;
2785 if (D->NbEq <= H->NbEq) {
2786 P = &D->next;
2787 continue;
2790 value_init(tmp.d);
2791 tmp.x.p = new_enode(partition, 2, e->x.p->pos);
2792 EVALUE_SET_DOMAIN(tmp.x.p->arr[0], Polyhedron_Copy(D));
2793 evalue_copy(&tmp.x.p->arr[1], &e->x.p->arr[2*i+1]);
2794 reduce_evalue(&tmp);
2795 if (value_notzero_p(tmp.d) ||
2796 ecmp(&tmp.x.p->arr[1], &e->x.p->arr[2*k+1]) != 0)
2797 P = &D->next;
2798 else {
2799 D->next = EVALUE_DOMAIN(e->x.p->arr[2*i]);
2800 EVALUE_DOMAIN(e->x.p->arr[2*i]) = D;
2801 *P = NULL;
2803 free_evalue_refs(&tmp);
2806 Polyhedron_Free(H);
2809 for (i = 0; i < e->x.p->size/2; ++i) {
2810 Polyhedron *H, *E;
2811 Polyhedron *D = EVALUE_DOMAIN(e->x.p->arr[2*i]);
2812 if (!D) {
2813 value_clear(e->x.p->arr[2*i].d);
2814 free_evalue_refs(&e->x.p->arr[2*i+1]);
2815 e->x.p->size -= 2;
2816 if (2*i < e->x.p->size) {
2817 e->x.p->arr[2*i] = e->x.p->arr[e->x.p->size];
2818 e->x.p->arr[2*i+1] = e->x.p->arr[e->x.p->size+1];
2820 --i;
2821 continue;
2823 if (!D->next)
2824 continue;
2825 H = DomainConvex(D, 0);
2826 E = DomainDifference(H, D, 0);
2827 Domain_Free(D);
2828 D = DomainDifference(H, E, 0);
2829 Domain_Free(H);
2830 Domain_Free(E);
2831 EVALUE_SET_DOMAIN(p->arr[2*i], D);
2835 /* Use smallest representative for coefficients in affine form in
2836 * argument of fractional.
2837 * Since any change will make the argument non-standard,
2838 * the containing evalue will have to be reduced again afterward.
2840 static void fractional_minimal_coefficients(enode *p)
2842 evalue *pp;
2843 Value twice;
2844 value_init(twice);
2846 assert(p->type == fractional);
2847 pp = &p->arr[0];
2848 while (value_zero_p(pp->d)) {
2849 assert(pp->x.p->type == polynomial);
2850 assert(pp->x.p->size == 2);
2851 assert(value_notzero_p(pp->x.p->arr[1].d));
2852 mpz_mul_ui(twice, pp->x.p->arr[1].x.n, 2);
2853 if (value_gt(twice, pp->x.p->arr[1].d))
2854 value_subtract(pp->x.p->arr[1].x.n,
2855 pp->x.p->arr[1].x.n, pp->x.p->arr[1].d);
2856 pp = &pp->x.p->arr[0];
2859 value_clear(twice);
2862 static Polyhedron *polynomial_projection(enode *p, Polyhedron *D, Value *d,
2863 Matrix **R)
2865 Polyhedron *I, *H;
2866 evalue *pp;
2867 unsigned dim = D->Dimension;
2868 Matrix *T = Matrix_Alloc(2, dim+1);
2869 assert(T);
2871 assert(p->type == fractional || p->type == flooring);
2872 value_set_si(T->p[1][dim], 1);
2873 evalue_extract_affine(&p->arr[0], T->p[0], &T->p[0][dim], d);
2874 I = DomainImage(D, T, 0);
2875 H = DomainConvex(I, 0);
2876 Domain_Free(I);
2877 if (R)
2878 *R = T;
2879 else
2880 Matrix_Free(T);
2882 return H;
2885 static void replace_by_affine(evalue *e, Value offset)
2887 enode *p;
2888 evalue inc;
2890 p = e->x.p;
2891 value_init(inc.d);
2892 value_init(inc.x.n);
2893 value_set_si(inc.d, 1);
2894 value_oppose(inc.x.n, offset);
2895 eadd(&inc, &p->arr[0]);
2896 reorder_terms_about(p, &p->arr[0]); /* frees arr[0] */
2897 value_clear(e->d);
2898 *e = p->arr[1];
2899 free(p);
2900 free_evalue_refs(&inc);
2903 int evalue_range_reduction_in_domain(evalue *e, Polyhedron *D)
2905 int i;
2906 enode *p;
2907 Value d, min, max;
2908 int r = 0;
2909 Polyhedron *I;
2910 int bounded;
2912 if (value_notzero_p(e->d))
2913 return r;
2915 p = e->x.p;
2917 if (p->type == relation) {
2918 Matrix *T;
2919 int equal;
2920 value_init(d);
2921 value_init(min);
2922 value_init(max);
2924 fractional_minimal_coefficients(p->arr[0].x.p);
2925 I = polynomial_projection(p->arr[0].x.p, D, &d, &T);
2926 bounded = line_minmax(I, &min, &max); /* frees I */
2927 equal = value_eq(min, max);
2928 mpz_cdiv_q(min, min, d);
2929 mpz_fdiv_q(max, max, d);
2931 if (bounded && value_gt(min, max)) {
2932 /* Never zero */
2933 if (p->size == 3) {
2934 value_clear(e->d);
2935 *e = p->arr[2];
2936 } else {
2937 evalue_set_si(e, 0, 1);
2938 r = 1;
2940 free_evalue_refs(&(p->arr[1]));
2941 free_evalue_refs(&(p->arr[0]));
2942 free(p);
2943 value_clear(d);
2944 value_clear(min);
2945 value_clear(max);
2946 Matrix_Free(T);
2947 return r ? r : evalue_range_reduction_in_domain(e, D);
2948 } else if (bounded && equal) {
2949 /* Always zero */
2950 if (p->size == 3)
2951 free_evalue_refs(&(p->arr[2]));
2952 value_clear(e->d);
2953 *e = p->arr[1];
2954 free_evalue_refs(&(p->arr[0]));
2955 free(p);
2956 value_clear(d);
2957 value_clear(min);
2958 value_clear(max);
2959 Matrix_Free(T);
2960 return evalue_range_reduction_in_domain(e, D);
2961 } else if (bounded && value_eq(min, max)) {
2962 /* zero for a single value */
2963 Polyhedron *E;
2964 Matrix *M = Matrix_Alloc(1, D->Dimension+2);
2965 Vector_Copy(T->p[0], M->p[0]+1, D->Dimension+1);
2966 value_multiply(min, min, d);
2967 value_subtract(M->p[0][D->Dimension+1],
2968 M->p[0][D->Dimension+1], min);
2969 E = DomainAddConstraints(D, M, 0);
2970 value_clear(d);
2971 value_clear(min);
2972 value_clear(max);
2973 Matrix_Free(T);
2974 Matrix_Free(M);
2975 r = evalue_range_reduction_in_domain(&p->arr[1], E);
2976 if (p->size == 3)
2977 r |= evalue_range_reduction_in_domain(&p->arr[2], D);
2978 Domain_Free(E);
2979 _reduce_evalue(&p->arr[0].x.p->arr[0], 0, 1);
2980 return r;
2983 value_clear(d);
2984 value_clear(min);
2985 value_clear(max);
2986 Matrix_Free(T);
2987 _reduce_evalue(&p->arr[0].x.p->arr[0], 0, 1);
2990 i = p->type == relation ? 1 :
2991 p->type == fractional ? 1 : 0;
2992 for (; i<p->size; i++)
2993 r |= evalue_range_reduction_in_domain(&p->arr[i], D);
2995 if (p->type != fractional) {
2996 if (r && p->type == polynomial) {
2997 evalue f;
2998 value_init(f.d);
2999 value_set_si(f.d, 0);
3000 f.x.p = new_enode(polynomial, 2, p->pos);
3001 evalue_set_si(&f.x.p->arr[0], 0, 1);
3002 evalue_set_si(&f.x.p->arr[1], 1, 1);
3003 reorder_terms_about(p, &f);
3004 value_clear(e->d);
3005 *e = p->arr[0];
3006 free(p);
3008 return r;
3011 value_init(d);
3012 value_init(min);
3013 value_init(max);
3014 fractional_minimal_coefficients(p);
3015 I = polynomial_projection(p, D, &d, NULL);
3016 bounded = line_minmax(I, &min, &max); /* frees I */
3017 mpz_fdiv_q(min, min, d);
3018 mpz_fdiv_q(max, max, d);
3019 value_subtract(d, max, min);
3021 if (bounded && value_eq(min, max)) {
3022 replace_by_affine(e, min);
3023 r = 1;
3024 } else if (bounded && value_one_p(d) && p->size > 3) {
3025 /* replace {g}^2 by -(g-min)^2 + (2{g}+1)*(g-min) - {g}
3026 * See pages 199-200 of PhD thesis.
3028 evalue rem;
3029 evalue inc;
3030 evalue t;
3031 evalue f;
3032 evalue factor;
3033 value_init(rem.d);
3034 value_set_si(rem.d, 0);
3035 rem.x.p = new_enode(fractional, 3, -1);
3036 evalue_copy(&rem.x.p->arr[0], &p->arr[0]);
3037 value_clear(rem.x.p->arr[1].d);
3038 value_clear(rem.x.p->arr[2].d);
3039 rem.x.p->arr[1] = p->arr[1];
3040 rem.x.p->arr[2] = p->arr[2];
3041 for (i = 3; i < p->size; ++i)
3042 p->arr[i-2] = p->arr[i];
3043 p->size -= 2;
3045 value_init(inc.d);
3046 value_init(inc.x.n);
3047 value_set_si(inc.d, 1);
3048 value_oppose(inc.x.n, min);
3050 value_init(t.d);
3051 evalue_copy(&t, &p->arr[0]);
3052 eadd(&inc, &t);
3054 value_init(f.d);
3055 value_set_si(f.d, 0);
3056 f.x.p = new_enode(fractional, 3, -1);
3057 evalue_copy(&f.x.p->arr[0], &p->arr[0]);
3058 evalue_set_si(&f.x.p->arr[1], 1, 1);
3059 evalue_set_si(&f.x.p->arr[2], 2, 1);
3061 value_init(factor.d);
3062 evalue_set_si(&factor, -1, 1);
3063 emul(&t, &factor);
3065 eadd(&f, &factor);
3066 emul(&t, &factor);
3068 value_clear(f.x.p->arr[1].x.n);
3069 value_clear(f.x.p->arr[2].x.n);
3070 evalue_set_si(&f.x.p->arr[1], 0, 1);
3071 evalue_set_si(&f.x.p->arr[2], -1, 1);
3072 eadd(&f, &factor);
3074 if (r) {
3075 evalue_reorder_terms(&rem);
3076 evalue_reorder_terms(e);
3079 emul(&factor, e);
3080 eadd(&rem, e);
3082 free_evalue_refs(&inc);
3083 free_evalue_refs(&t);
3084 free_evalue_refs(&f);
3085 free_evalue_refs(&factor);
3086 free_evalue_refs(&rem);
3088 evalue_range_reduction_in_domain(e, D);
3090 r = 1;
3091 } else {
3092 _reduce_evalue(&p->arr[0], 0, 1);
3093 if (r)
3094 evalue_reorder_terms(e);
3097 value_clear(d);
3098 value_clear(min);
3099 value_clear(max);
3101 return r;
3104 void evalue_range_reduction(evalue *e)
3106 int i;
3107 if (value_notzero_p(e->d) || e->x.p->type != partition)
3108 return;
3110 for (i = 0; i < e->x.p->size/2; ++i)
3111 if (evalue_range_reduction_in_domain(&e->x.p->arr[2*i+1],
3112 EVALUE_DOMAIN(e->x.p->arr[2*i]))) {
3113 reduce_evalue(&e->x.p->arr[2*i+1]);
3115 if (EVALUE_IS_ZERO(e->x.p->arr[2*i+1])) {
3116 free_evalue_refs(&e->x.p->arr[2*i+1]);
3117 Domain_Free(EVALUE_DOMAIN(e->x.p->arr[2*i]));
3118 value_clear(e->x.p->arr[2*i].d);
3119 e->x.p->size -= 2;
3120 e->x.p->arr[2*i] = e->x.p->arr[e->x.p->size];
3121 e->x.p->arr[2*i+1] = e->x.p->arr[e->x.p->size+1];
3122 --i;
3127 /* Frees EP
3129 Enumeration* partition2enumeration(evalue *EP)
3131 int i;
3132 Enumeration *en, *res = NULL;
3134 if (EVALUE_IS_ZERO(*EP)) {
3135 evalue_free(EP);
3136 return res;
3139 assert(value_zero_p(EP->d));
3140 assert(EP->x.p->type == partition);
3141 assert(EP->x.p->size >= 2);
3143 for (i = 0; i < EP->x.p->size/2; ++i) {
3144 assert(EP->x.p->pos == EVALUE_DOMAIN(EP->x.p->arr[2*i])->Dimension);
3145 en = (Enumeration *)malloc(sizeof(Enumeration));
3146 en->next = res;
3147 res = en;
3148 res->ValidityDomain = EVALUE_DOMAIN(EP->x.p->arr[2*i]);
3149 value_clear(EP->x.p->arr[2*i].d);
3150 res->EP = EP->x.p->arr[2*i+1];
3152 free(EP->x.p);
3153 value_clear(EP->d);
3154 free(EP);
3155 return res;
3158 int evalue_frac2floor_in_domain3(evalue *e, Polyhedron *D, int shift)
3160 enode *p;
3161 int r = 0;
3162 int i;
3163 Polyhedron *I;
3164 Value d, min;
3165 evalue fl;
3167 if (value_notzero_p(e->d))
3168 return r;
3170 p = e->x.p;
3172 i = p->type == relation ? 1 :
3173 p->type == fractional ? 1 : 0;
3174 for (; i<p->size; i++)
3175 r |= evalue_frac2floor_in_domain3(&p->arr[i], D, shift);
3177 if (p->type != fractional) {
3178 if (r && p->type == polynomial) {
3179 evalue f;
3180 value_init(f.d);
3181 value_set_si(f.d, 0);
3182 f.x.p = new_enode(polynomial, 2, p->pos);
3183 evalue_set_si(&f.x.p->arr[0], 0, 1);
3184 evalue_set_si(&f.x.p->arr[1], 1, 1);
3185 reorder_terms_about(p, &f);
3186 value_clear(e->d);
3187 *e = p->arr[0];
3188 free(p);
3190 return r;
3193 if (shift) {
3194 value_init(d);
3195 I = polynomial_projection(p, D, &d, NULL);
3198 Polyhedron_Print(stderr, P_VALUE_FMT, I);
3201 assert(I->NbEq == 0); /* Should have been reduced */
3203 /* Find minimum */
3204 for (i = 0; i < I->NbConstraints; ++i)
3205 if (value_pos_p(I->Constraint[i][1]))
3206 break;
3208 if (i < I->NbConstraints) {
3209 value_init(min);
3210 value_oppose(I->Constraint[i][2], I->Constraint[i][2]);
3211 mpz_cdiv_q(min, I->Constraint[i][2], I->Constraint[i][1]);
3212 if (value_neg_p(min)) {
3213 evalue offset;
3214 mpz_fdiv_q(min, min, d);
3215 value_init(offset.d);
3216 value_set_si(offset.d, 1);
3217 value_init(offset.x.n);
3218 value_oppose(offset.x.n, min);
3219 eadd(&offset, &p->arr[0]);
3220 free_evalue_refs(&offset);
3222 value_clear(min);
3225 Polyhedron_Free(I);
3226 value_clear(d);
3229 value_init(fl.d);
3230 value_set_si(fl.d, 0);
3231 fl.x.p = new_enode(flooring, 3, -1);
3232 evalue_set_si(&fl.x.p->arr[1], 0, 1);
3233 evalue_set_si(&fl.x.p->arr[2], -1, 1);
3234 evalue_copy(&fl.x.p->arr[0], &p->arr[0]);
3236 eadd(&fl, &p->arr[0]);
3237 reorder_terms_about(p, &p->arr[0]);
3238 value_clear(e->d);
3239 *e = p->arr[1];
3240 free(p);
3241 free_evalue_refs(&fl);
3243 return 1;
3246 int evalue_frac2floor_in_domain(evalue *e, Polyhedron *D)
3248 return evalue_frac2floor_in_domain3(e, D, 1);
3251 void evalue_frac2floor2(evalue *e, int shift)
3253 int i;
3254 if (value_notzero_p(e->d) || e->x.p->type != partition) {
3255 if (!shift) {
3256 if (evalue_frac2floor_in_domain3(e, NULL, 0))
3257 reduce_evalue(e);
3259 return;
3262 for (i = 0; i < e->x.p->size/2; ++i)
3263 if (evalue_frac2floor_in_domain3(&e->x.p->arr[2*i+1],
3264 EVALUE_DOMAIN(e->x.p->arr[2*i]), shift))
3265 reduce_evalue(&e->x.p->arr[2*i+1]);
3268 void evalue_frac2floor(evalue *e)
3270 evalue_frac2floor2(e, 1);
3273 /* Add a new variable with lower bound 1 and upper bound specified
3274 * by row. If negative is true, then the new variable has upper
3275 * bound -1 and lower bound specified by row.
3277 static Matrix *esum_add_constraint(int nvar, Polyhedron *D, Matrix *C,
3278 Vector *row, int negative)
3280 int nr, nc;
3281 int i;
3282 int nparam = D->Dimension - nvar;
3284 if (C == 0) {
3285 nr = D->NbConstraints + 2;
3286 nc = D->Dimension + 2 + 1;
3287 C = Matrix_Alloc(nr, nc);
3288 for (i = 0; i < D->NbConstraints; ++i) {
3289 Vector_Copy(D->Constraint[i], C->p[i], 1 + nvar);
3290 Vector_Copy(D->Constraint[i] + 1 + nvar, C->p[i] + 1 + nvar + 1,
3291 D->Dimension + 1 - nvar);
3293 } else {
3294 Matrix *oldC = C;
3295 nr = C->NbRows + 2;
3296 nc = C->NbColumns + 1;
3297 C = Matrix_Alloc(nr, nc);
3298 for (i = 0; i < oldC->NbRows; ++i) {
3299 Vector_Copy(oldC->p[i], C->p[i], 1 + nvar);
3300 Vector_Copy(oldC->p[i] + 1 + nvar, C->p[i] + 1 + nvar + 1,
3301 oldC->NbColumns - 1 - nvar);
3304 value_set_si(C->p[nr-2][0], 1);
3305 if (negative)
3306 value_set_si(C->p[nr-2][1 + nvar], -1);
3307 else
3308 value_set_si(C->p[nr-2][1 + nvar], 1);
3309 value_set_si(C->p[nr-2][nc - 1], -1);
3311 Vector_Copy(row->p, C->p[nr-1], 1 + nvar + 1);
3312 Vector_Copy(row->p + 1 + nvar + 1, C->p[nr-1] + C->NbColumns - 1 - nparam,
3313 1 + nparam);
3315 return C;
3318 static void floor2frac_r(evalue *e, int nvar)
3320 enode *p;
3321 int i;
3322 evalue f;
3323 evalue *pp;
3325 if (value_notzero_p(e->d))
3326 return;
3328 p = e->x.p;
3330 for (i = type_offset(p); i < p->size; i++)
3331 floor2frac_r(&p->arr[i], nvar);
3333 if (p->type != flooring)
3334 return;
3336 for (pp = &p->arr[0]; value_zero_p(pp->d); pp = &pp->x.p->arr[0]) {
3337 assert(pp->x.p->type == polynomial);
3338 pp->x.p->pos -= nvar;
3341 value_init(f.d);
3342 value_set_si(f.d, 0);
3343 f.x.p = new_enode(fractional, 3, -1);
3344 evalue_set_si(&f.x.p->arr[1], 0, 1);
3345 evalue_set_si(&f.x.p->arr[2], -1, 1);
3346 evalue_copy(&f.x.p->arr[0], &p->arr[0]);
3348 eadd(&f, &p->arr[0]);
3349 reorder_terms_about(p, &p->arr[0]);
3350 value_clear(e->d);
3351 *e = p->arr[1];
3352 free(p);
3353 free_evalue_refs(&f);
3356 /* Convert flooring back to fractional and shift position
3357 * of the parameters by nvar
3359 static void floor2frac(evalue *e, int nvar)
3361 floor2frac_r(e, nvar);
3362 reduce_evalue(e);
3365 int evalue_floor2frac(evalue *e)
3367 int i;
3368 int r = 0;
3370 if (value_notzero_p(e->d))
3371 return 0;
3373 if (e->x.p->type == partition) {
3374 for (i = 0; i < e->x.p->size/2; ++i)
3375 if (evalue_floor2frac(&e->x.p->arr[2*i+1]))
3376 reduce_evalue(&e->x.p->arr[2*i+1]);
3377 return 0;
3380 for (i = type_offset(e->x.p); i < e->x.p->size; ++i)
3381 r |= evalue_floor2frac(&e->x.p->arr[i]);
3383 if (e->x.p->type == flooring) {
3384 floor2frac(e, 0);
3385 return 1;
3388 if (r)
3389 evalue_reorder_terms(e);
3391 return r;
3394 evalue *esum_over_domain_cst(int nvar, Polyhedron *D, Matrix *C)
3396 evalue *t;
3397 int nparam = D->Dimension - nvar;
3399 if (C != 0) {
3400 C = Matrix_Copy(C);
3401 D = Constraints2Polyhedron(C, 0);
3402 Matrix_Free(C);
3405 t = barvinok_enumerate_e(D, 0, nparam, 0);
3407 /* Double check that D was not unbounded. */
3408 assert(!(value_pos_p(t->d) && value_neg_p(t->x.n)));
3410 if (C != 0)
3411 Polyhedron_Free(D);
3413 return t;
3416 static void domain_signs(Polyhedron *D, int *signs)
3418 int j, k;
3420 POL_ENSURE_VERTICES(D);
3421 for (j = 0; j < D->Dimension; ++j) {
3422 signs[j] = 0;
3423 for (k = 0; k < D->NbRays; ++k) {
3424 signs[j] = value_sign(D->Ray[k][1+j]);
3425 if (signs[j])
3426 break;
3431 static evalue *esum_over_domain(evalue *e, int nvar, Polyhedron *D,
3432 int *signs, Matrix *C, unsigned MaxRays)
3434 Vector *row = NULL;
3435 int i, offset;
3436 evalue *res;
3437 Matrix *origC;
3438 evalue *factor = NULL;
3439 evalue cum;
3440 int negative = 0;
3441 int allocated = 0;
3443 if (EVALUE_IS_ZERO(*e))
3444 return 0;
3446 if (D->next) {
3447 Polyhedron *DD = Disjoint_Domain(D, 0, MaxRays);
3448 Polyhedron *Q;
3450 Q = DD;
3451 DD = Q->next;
3452 Q->next = 0;
3454 res = esum_over_domain(e, nvar, Q, signs, C, MaxRays);
3455 Polyhedron_Free(Q);
3457 for (Q = DD; Q; Q = DD) {
3458 evalue *t;
3460 DD = Q->next;
3461 Q->next = 0;
3463 t = esum_over_domain(e, nvar, Q, signs, C, MaxRays);
3464 Polyhedron_Free(Q);
3466 if (!res)
3467 res = t;
3468 else if (t) {
3469 eadd(t, res);
3470 evalue_free(t);
3473 return res;
3476 if (value_notzero_p(e->d)) {
3477 evalue *t;
3479 t = esum_over_domain_cst(nvar, D, C);
3481 if (!EVALUE_IS_ONE(*e))
3482 emul(e, t);
3484 return t;
3487 if (!signs) {
3488 allocated = 1;
3489 signs = ALLOCN(int, D->Dimension);
3490 domain_signs(D, signs);
3493 switch (e->x.p->type) {
3494 case flooring: {
3495 evalue *pp = &e->x.p->arr[0];
3497 if (pp->x.p->pos > nvar) {
3498 /* remainder is independent of the summated vars */
3499 evalue f;
3500 evalue *t;
3502 value_init(f.d);
3503 evalue_copy(&f, e);
3504 floor2frac(&f, nvar);
3506 t = esum_over_domain_cst(nvar, D, C);
3508 emul(&f, t);
3510 free_evalue_refs(&f);
3512 if (allocated)
3513 free(signs);
3515 return t;
3518 row = Vector_Alloc(1 + D->Dimension + 1 + 1);
3519 poly_denom(pp, &row->p[1 + nvar]);
3520 value_set_si(row->p[0], 1);
3521 for (pp = &e->x.p->arr[0]; value_zero_p(pp->d);
3522 pp = &pp->x.p->arr[0]) {
3523 int pos;
3524 assert(pp->x.p->type == polynomial);
3525 pos = pp->x.p->pos;
3526 if (pos >= 1 + nvar)
3527 ++pos;
3528 value_assign(row->p[pos], row->p[1+nvar]);
3529 value_division(row->p[pos], row->p[pos], pp->x.p->arr[1].d);
3530 value_multiply(row->p[pos], row->p[pos], pp->x.p->arr[1].x.n);
3532 value_assign(row->p[1 + D->Dimension + 1], row->p[1+nvar]);
3533 value_division(row->p[1 + D->Dimension + 1],
3534 row->p[1 + D->Dimension + 1],
3535 pp->d);
3536 value_multiply(row->p[1 + D->Dimension + 1],
3537 row->p[1 + D->Dimension + 1],
3538 pp->x.n);
3539 value_oppose(row->p[1 + nvar], row->p[1 + nvar]);
3540 break;
3542 case polynomial: {
3543 int pos = e->x.p->pos;
3545 if (pos > nvar) {
3546 factor = ALLOC(evalue);
3547 value_init(factor->d);
3548 value_set_si(factor->d, 0);
3549 factor->x.p = new_enode(polynomial, 2, pos - nvar);
3550 evalue_set_si(&factor->x.p->arr[0], 0, 1);
3551 evalue_set_si(&factor->x.p->arr[1], 1, 1);
3552 break;
3555 row = Vector_Alloc(1 + D->Dimension + 1 + 1);
3556 negative = signs[pos-1] < 0;
3557 value_set_si(row->p[0], 1);
3558 if (negative) {
3559 value_set_si(row->p[pos], -1);
3560 value_set_si(row->p[1 + nvar], 1);
3561 } else {
3562 value_set_si(row->p[pos], 1);
3563 value_set_si(row->p[1 + nvar], -1);
3565 break;
3567 default:
3568 assert(0);
3571 offset = type_offset(e->x.p);
3573 res = esum_over_domain(&e->x.p->arr[offset], nvar, D, signs, C, MaxRays);
3575 if (factor) {
3576 value_init(cum.d);
3577 evalue_copy(&cum, factor);
3580 origC = C;
3581 for (i = 1; offset+i < e->x.p->size; ++i) {
3582 evalue *t;
3583 if (row) {
3584 Matrix *prevC = C;
3585 C = esum_add_constraint(nvar, D, C, row, negative);
3586 if (prevC != origC)
3587 Matrix_Free(prevC);
3590 if (row)
3591 Vector_Print(stderr, P_VALUE_FMT, row);
3592 if (C)
3593 Matrix_Print(stderr, P_VALUE_FMT, C);
3595 t = esum_over_domain(&e->x.p->arr[offset+i], nvar, D, signs, C, MaxRays);
3597 if (t) {
3598 if (factor)
3599 emul(&cum, t);
3600 if (negative && (i % 2))
3601 evalue_negate(t);
3604 if (!res)
3605 res = t;
3606 else if (t) {
3607 eadd(t, res);
3608 evalue_free(t);
3610 if (factor && offset+i+1 < e->x.p->size)
3611 emul(factor, &cum);
3613 if (C != origC)
3614 Matrix_Free(C);
3616 if (factor) {
3617 free_evalue_refs(&cum);
3618 evalue_free(factor);
3621 if (row)
3622 Vector_Free(row);
3624 reduce_evalue(res);
3626 if (allocated)
3627 free(signs);
3629 return res;
3632 static void Polyhedron_Insert(Polyhedron ***next, Polyhedron *Q)
3634 if (emptyQ(Q))
3635 Polyhedron_Free(Q);
3636 else {
3637 **next = Q;
3638 *next = &(Q->next);
3642 static Polyhedron *Polyhedron_Split_Into_Orthants(Polyhedron *P,
3643 unsigned MaxRays)
3645 int i = 0;
3646 Polyhedron *D = P;
3647 Vector *c = Vector_Alloc(1 + P->Dimension + 1);
3648 value_set_si(c->p[0], 1);
3650 if (P->Dimension == 0)
3651 return Polyhedron_Copy(P);
3653 for (i = 0; i < P->Dimension; ++i) {
3654 Polyhedron *L = NULL;
3655 Polyhedron **next = &L;
3656 Polyhedron *I;
3658 for (I = D; I; I = I->next) {
3659 Polyhedron *Q;
3660 value_set_si(c->p[1+i], 1);
3661 value_set_si(c->p[1+P->Dimension], 0);
3662 Q = AddConstraints(c->p, 1, I, MaxRays);
3663 Polyhedron_Insert(&next, Q);
3664 value_set_si(c->p[1+i], -1);
3665 value_set_si(c->p[1+P->Dimension], -1);
3666 Q = AddConstraints(c->p, 1, I, MaxRays);
3667 Polyhedron_Insert(&next, Q);
3668 value_set_si(c->p[1+i], 0);
3670 if (D != P)
3671 Domain_Free(D);
3672 D = L;
3674 Vector_Free(c);
3675 return D;
3678 /* Make arguments of all floors non-negative */
3679 static void shift_floor_in_domain(evalue *e, Polyhedron *D)
3681 Value d, m;
3682 Polyhedron *I;
3683 int i;
3684 enode *p;
3686 if (value_notzero_p(e->d))
3687 return;
3689 p = e->x.p;
3691 for (i = type_offset(p); i < p->size; ++i)
3692 shift_floor_in_domain(&p->arr[i], D);
3694 if (p->type != flooring)
3695 return;
3697 value_init(d);
3698 value_init(m);
3700 I = polynomial_projection(p, D, &d, NULL);
3701 assert(I->NbEq == 0); /* Should have been reduced */
3703 for (i = 0; i < I->NbConstraints; ++i)
3704 if (value_pos_p(I->Constraint[i][1]))
3705 break;
3706 assert(i < I->NbConstraints);
3707 if (i < I->NbConstraints) {
3708 value_oppose(I->Constraint[i][2], I->Constraint[i][2]);
3709 mpz_fdiv_q(m, I->Constraint[i][2], I->Constraint[i][1]);
3710 if (value_neg_p(m)) {
3711 /* replace [e] by [e-m]+m such that e-m >= 0 */
3712 evalue f;
3714 value_init(f.d);
3715 value_init(f.x.n);
3716 value_set_si(f.d, 1);
3717 value_oppose(f.x.n, m);
3718 eadd(&f, &p->arr[0]);
3719 value_clear(f.x.n);
3721 value_set_si(f.d, 0);
3722 f.x.p = new_enode(flooring, 3, -1);
3723 value_clear(f.x.p->arr[0].d);
3724 f.x.p->arr[0] = p->arr[0];
3725 evalue_set_si(&f.x.p->arr[2], 1, 1);
3726 value_set_si(f.x.p->arr[1].d, 1);
3727 value_init(f.x.p->arr[1].x.n);
3728 value_assign(f.x.p->arr[1].x.n, m);
3729 reorder_terms_about(p, &f);
3730 value_clear(e->d);
3731 *e = p->arr[1];
3732 free(p);
3735 Polyhedron_Free(I);
3736 value_clear(d);
3737 value_clear(m);
3740 evalue *box_summate(Polyhedron *P, evalue *E, unsigned nvar, unsigned MaxRays)
3742 evalue *sum = evalue_zero();
3743 Polyhedron *D = Polyhedron_Split_Into_Orthants(P, MaxRays);
3744 for (P = D; P; P = P->next) {
3745 evalue *t;
3746 evalue *fe = evalue_dup(E);
3747 Polyhedron *next = P->next;
3748 P->next = NULL;
3749 reduce_evalue_in_domain(fe, P);
3750 evalue_frac2floor2(fe, 0);
3751 shift_floor_in_domain(fe, P);
3752 t = esum_over_domain(fe, nvar, P, NULL, NULL, MaxRays);
3753 if (t) {
3754 eadd(t, sum);
3755 evalue_free(t);
3757 evalue_free(fe);
3758 P->next = next;
3760 Domain_Free(D);
3761 return sum;
3764 /* Initial silly implementation */
3765 void eor(evalue *e1, evalue *res)
3767 evalue E;
3768 evalue mone;
3769 value_init(E.d);
3770 value_init(mone.d);
3771 evalue_set_si(&mone, -1, 1);
3773 evalue_copy(&E, res);
3774 eadd(e1, &E);
3775 emul(e1, res);
3776 emul(&mone, res);
3777 eadd(&E, res);
3779 free_evalue_refs(&E);
3780 free_evalue_refs(&mone);
3783 /* computes denominator of polynomial evalue
3784 * d should point to a value initialized to 1
3786 void evalue_denom(const evalue *e, Value *d)
3788 int i, offset;
3790 if (value_notzero_p(e->d)) {
3791 value_lcm(*d, *d, e->d);
3792 return;
3794 assert(e->x.p->type == polynomial ||
3795 e->x.p->type == fractional ||
3796 e->x.p->type == flooring);
3797 offset = type_offset(e->x.p);
3798 for (i = e->x.p->size-1; i >= offset; --i)
3799 evalue_denom(&e->x.p->arr[i], d);
3802 /* Divides the evalue e by the integer n */
3803 void evalue_div(evalue *e, Value n)
3805 int i, offset;
3807 if (value_one_p(n) || EVALUE_IS_ZERO(*e))
3808 return;
3810 if (value_notzero_p(e->d)) {
3811 Value gc;
3812 value_init(gc);
3813 value_multiply(e->d, e->d, n);
3814 value_gcd(gc, e->x.n, e->d);
3815 if (value_notone_p(gc)) {
3816 value_division(e->d, e->d, gc);
3817 value_division(e->x.n, e->x.n, gc);
3819 value_clear(gc);
3820 return;
3822 if (e->x.p->type == partition) {
3823 for (i = 0; i < e->x.p->size/2; ++i)
3824 evalue_div(&e->x.p->arr[2*i+1], n);
3825 return;
3827 offset = type_offset(e->x.p);
3828 for (i = e->x.p->size-1; i >= offset; --i)
3829 evalue_div(&e->x.p->arr[i], n);
3832 /* Multiplies the evalue e by the integer n */
3833 void evalue_mul(evalue *e, Value n)
3835 int i, offset;
3837 if (value_one_p(n) || EVALUE_IS_ZERO(*e))
3838 return;
3840 if (value_notzero_p(e->d)) {
3841 Value gc;
3842 value_init(gc);
3843 value_multiply(e->x.n, e->x.n, n);
3844 value_gcd(gc, e->x.n, e->d);
3845 if (value_notone_p(gc)) {
3846 value_division(e->d, e->d, gc);
3847 value_division(e->x.n, e->x.n, gc);
3849 value_clear(gc);
3850 return;
3852 if (e->x.p->type == partition) {
3853 for (i = 0; i < e->x.p->size/2; ++i)
3854 evalue_mul(&e->x.p->arr[2*i+1], n);
3855 return;
3857 offset = type_offset(e->x.p);
3858 for (i = e->x.p->size-1; i >= offset; --i)
3859 evalue_mul(&e->x.p->arr[i], n);
3862 /* Multiplies the evalue e by the n/d */
3863 void evalue_mul_div(evalue *e, Value n, Value d)
3865 int i, offset;
3867 if ((value_one_p(n) && value_one_p(d)) || EVALUE_IS_ZERO(*e))
3868 return;
3870 if (value_notzero_p(e->d)) {
3871 Value gc;
3872 value_init(gc);
3873 value_multiply(e->x.n, e->x.n, n);
3874 value_multiply(e->d, e->d, d);
3875 value_gcd(gc, e->x.n, e->d);
3876 if (value_notone_p(gc)) {
3877 value_division(e->d, e->d, gc);
3878 value_division(e->x.n, e->x.n, gc);
3880 value_clear(gc);
3881 return;
3883 if (e->x.p->type == partition) {
3884 for (i = 0; i < e->x.p->size/2; ++i)
3885 evalue_mul_div(&e->x.p->arr[2*i+1], n, d);
3886 return;
3888 offset = type_offset(e->x.p);
3889 for (i = e->x.p->size-1; i >= offset; --i)
3890 evalue_mul_div(&e->x.p->arr[i], n, d);
3893 void evalue_negate(evalue *e)
3895 int i, offset;
3897 if (value_notzero_p(e->d)) {
3898 value_oppose(e->x.n, e->x.n);
3899 return;
3901 if (e->x.p->type == partition) {
3902 for (i = 0; i < e->x.p->size/2; ++i)
3903 evalue_negate(&e->x.p->arr[2*i+1]);
3904 return;
3906 offset = type_offset(e->x.p);
3907 for (i = e->x.p->size-1; i >= offset; --i)
3908 evalue_negate(&e->x.p->arr[i]);
3911 void evalue_add_constant(evalue *e, const Value cst)
3913 int i;
3915 if (value_zero_p(e->d)) {
3916 if (e->x.p->type == partition) {
3917 for (i = 0; i < e->x.p->size/2; ++i)
3918 evalue_add_constant(&e->x.p->arr[2*i+1], cst);
3919 return;
3921 if (e->x.p->type == relation) {
3922 for (i = 1; i < e->x.p->size; ++i)
3923 evalue_add_constant(&e->x.p->arr[i], cst);
3924 return;
3926 do {
3927 e = &e->x.p->arr[type_offset(e->x.p)];
3928 } while (value_zero_p(e->d));
3930 value_addmul(e->x.n, cst, e->d);
3933 static void evalue_frac2polynomial_r(evalue *e, int *signs, int sign, int in_frac)
3935 int i, offset;
3936 Value d;
3937 enode *p;
3938 int sign_odd = sign;
3940 if (value_notzero_p(e->d)) {
3941 if (in_frac && sign * value_sign(e->x.n) < 0) {
3942 value_set_si(e->x.n, 0);
3943 value_set_si(e->d, 1);
3945 return;
3948 if (e->x.p->type == relation) {
3949 for (i = e->x.p->size-1; i >= 1; --i)
3950 evalue_frac2polynomial_r(&e->x.p->arr[i], signs, sign, in_frac);
3951 return;
3954 if (e->x.p->type == polynomial)
3955 sign_odd *= signs[e->x.p->pos-1];
3956 offset = type_offset(e->x.p);
3957 evalue_frac2polynomial_r(&e->x.p->arr[offset], signs, sign, in_frac);
3958 in_frac |= e->x.p->type == fractional;
3959 for (i = e->x.p->size-1; i > offset; --i)
3960 evalue_frac2polynomial_r(&e->x.p->arr[i], signs,
3961 (i - offset) % 2 ? sign_odd : sign, in_frac);
3963 if (e->x.p->type != fractional)
3964 return;
3966 /* replace { a/m } by (m-1)/m if sign != 0
3967 * and by (m-1)/(2m) if sign == 0
3969 value_init(d);
3970 value_set_si(d, 1);
3971 evalue_denom(&e->x.p->arr[0], &d);
3972 free_evalue_refs(&e->x.p->arr[0]);
3973 value_init(e->x.p->arr[0].d);
3974 value_init(e->x.p->arr[0].x.n);
3975 if (sign == 0)
3976 value_addto(e->x.p->arr[0].d, d, d);
3977 else
3978 value_assign(e->x.p->arr[0].d, d);
3979 value_decrement(e->x.p->arr[0].x.n, d);
3980 value_clear(d);
3982 p = e->x.p;
3983 reorder_terms_about(p, &p->arr[0]);
3984 value_clear(e->d);
3985 *e = p->arr[1];
3986 free(p);
3989 /* Approximate the evalue in fractional representation by a polynomial.
3990 * If sign > 0, the result is an upper bound;
3991 * if sign < 0, the result is a lower bound;
3992 * if sign = 0, the result is an intermediate approximation.
3994 void evalue_frac2polynomial(evalue *e, int sign, unsigned MaxRays)
3996 int i, dim;
3997 int *signs;
3999 if (value_notzero_p(e->d))
4000 return;
4001 assert(e->x.p->type == partition);
4002 /* make sure all variables in the domains have a fixed sign */
4003 if (sign) {
4004 evalue_split_domains_into_orthants(e, MaxRays);
4005 if (EVALUE_IS_ZERO(*e))
4006 return;
4009 assert(e->x.p->size >= 2);
4010 dim = EVALUE_DOMAIN(e->x.p->arr[0])->Dimension;
4012 signs = ALLOCN(int, dim);
4014 if (!sign)
4015 for (i = 0; i < dim; ++i)
4016 signs[i] = 0;
4017 for (i = 0; i < e->x.p->size/2; ++i) {
4018 if (sign)
4019 domain_signs(EVALUE_DOMAIN(e->x.p->arr[2*i]), signs);
4020 evalue_frac2polynomial_r(&e->x.p->arr[2*i+1], signs, sign, 0);
4023 free(signs);
4026 /* Split the domains of e (which is assumed to be a partition)
4027 * such that each resulting domain lies entirely in one orthant.
4029 void evalue_split_domains_into_orthants(evalue *e, unsigned MaxRays)
4031 int i, dim;
4032 assert(value_zero_p(e->d));
4033 assert(e->x.p->type == partition);
4034 assert(e->x.p->size >= 2);
4035 dim = EVALUE_DOMAIN(e->x.p->arr[0])->Dimension;
4037 for (i = 0; i < dim; ++i) {
4038 evalue split;
4039 Matrix *C, *C2;
4040 C = Matrix_Alloc(1, 1 + dim + 1);
4041 value_set_si(C->p[0][0], 1);
4042 value_init(split.d);
4043 value_set_si(split.d, 0);
4044 split.x.p = new_enode(partition, 4, dim);
4045 value_set_si(C->p[0][1+i], 1);
4046 C2 = Matrix_Copy(C);
4047 EVALUE_SET_DOMAIN(split.x.p->arr[0], Constraints2Polyhedron(C2, MaxRays));
4048 Matrix_Free(C2);
4049 evalue_set_si(&split.x.p->arr[1], 1, 1);
4050 value_set_si(C->p[0][1+i], -1);
4051 value_set_si(C->p[0][1+dim], -1);
4052 EVALUE_SET_DOMAIN(split.x.p->arr[2], Constraints2Polyhedron(C, MaxRays));
4053 evalue_set_si(&split.x.p->arr[3], 1, 1);
4054 emul(&split, e);
4055 free_evalue_refs(&split);
4056 Matrix_Free(C);
4060 void evalue_extract_affine(const evalue *e, Value *coeff, Value *cst, Value *d)
4062 value_set_si(*d, 1);
4063 evalue_denom(e, d);
4064 for ( ; value_zero_p(e->d); e = &e->x.p->arr[0]) {
4065 evalue *c;
4066 assert(e->x.p->type == polynomial);
4067 assert(e->x.p->size == 2);
4068 c = &e->x.p->arr[1];
4069 value_multiply(coeff[e->x.p->pos-1], *d, c->x.n);
4070 value_division(coeff[e->x.p->pos-1], coeff[e->x.p->pos-1], c->d);
4072 value_multiply(*cst, *d, e->x.n);
4073 value_division(*cst, *cst, e->d);
4076 /* returns an evalue that corresponds to
4078 * c/den x_param
4080 static evalue *term(int param, Value c, Value den)
4082 evalue *EP = ALLOC(evalue);
4083 value_init(EP->d);
4084 value_set_si(EP->d,0);
4085 EP->x.p = new_enode(polynomial, 2, param + 1);
4086 evalue_set_si(&EP->x.p->arr[0], 0, 1);
4087 evalue_set_reduce(&EP->x.p->arr[1], c, den);
4088 return EP;
4091 evalue *affine2evalue(Value *coeff, Value denom, int nvar)
4093 int i;
4094 evalue *E = ALLOC(evalue);
4095 value_init(E->d);
4096 evalue_set_reduce(E, coeff[nvar], denom);
4097 for (i = 0; i < nvar; ++i) {
4098 evalue *t;
4099 if (value_zero_p(coeff[i]))
4100 continue;
4101 t = term(i, coeff[i], denom);
4102 eadd(t, E);
4103 evalue_free(t);
4105 return E;
4108 void evalue_substitute(evalue *e, evalue **subs)
4110 int i, offset;
4111 evalue *v;
4112 enode *p;
4114 if (value_notzero_p(e->d))
4115 return;
4117 p = e->x.p;
4118 assert(p->type != partition);
4120 for (i = 0; i < p->size; ++i)
4121 evalue_substitute(&p->arr[i], subs);
4123 if (p->type == relation) {
4124 /* For relation a ? b : c, compute (a' ? 1) * b' + (a' ? 0 : 1) * c' */
4125 if (p->size == 3) {
4126 v = ALLOC(evalue);
4127 value_init(v->d);
4128 value_set_si(v->d, 0);
4129 v->x.p = new_enode(relation, 3, 0);
4130 evalue_copy(&v->x.p->arr[0], &p->arr[0]);
4131 evalue_set_si(&v->x.p->arr[1], 0, 1);
4132 evalue_set_si(&v->x.p->arr[2], 1, 1);
4133 emul(v, &p->arr[2]);
4134 evalue_free(v);
4136 v = ALLOC(evalue);
4137 value_init(v->d);
4138 value_set_si(v->d, 0);
4139 v->x.p = new_enode(relation, 2, 0);
4140 value_clear(v->x.p->arr[0].d);
4141 v->x.p->arr[0] = p->arr[0];
4142 evalue_set_si(&v->x.p->arr[1], 1, 1);
4143 emul(v, &p->arr[1]);
4144 evalue_free(v);
4145 if (p->size == 3) {
4146 eadd(&p->arr[2], &p->arr[1]);
4147 free_evalue_refs(&p->arr[2]);
4149 value_clear(e->d);
4150 *e = p->arr[1];
4151 free(p);
4152 return;
4155 if (p->type == polynomial)
4156 v = subs[p->pos-1];
4157 else {
4158 v = ALLOC(evalue);
4159 value_init(v->d);
4160 value_set_si(v->d, 0);
4161 v->x.p = new_enode(p->type, 3, -1);
4162 value_clear(v->x.p->arr[0].d);
4163 v->x.p->arr[0] = p->arr[0];
4164 evalue_set_si(&v->x.p->arr[1], 0, 1);
4165 evalue_set_si(&v->x.p->arr[2], 1, 1);
4168 offset = type_offset(p);
4170 for (i = p->size-1; i >= offset+1; i--) {
4171 emul(v, &p->arr[i]);
4172 eadd(&p->arr[i], &p->arr[i-1]);
4173 free_evalue_refs(&(p->arr[i]));
4176 if (p->type != polynomial)
4177 evalue_free(v);
4179 value_clear(e->d);
4180 *e = p->arr[offset];
4181 free(p);
4184 /* evalue e is given in terms of "new" parameter; CP maps the new
4185 * parameters back to the old parameters.
4186 * Transforms e such that it refers back to the old parameters and
4187 * adds appropriate constraints to the domain.
4188 * In particular, if CP maps the new parameters onto an affine
4189 * subspace of the old parameters, then the corresponding equalities
4190 * are added to the domain.
4191 * Also, if any of the new parameters was a rational combination
4192 * of the old parameters $p' = (<a, p> + c)/m$, then modulo
4193 * constraints ${<a, p> + c)/m} = 0$ are added to ensure
4194 * the new evalue remains non-zero only for integer parameters
4195 * of the new parameters (which have been removed by the substitution).
4197 void evalue_backsubstitute(evalue *e, Matrix *CP, unsigned MaxRays)
4199 Matrix *eq;
4200 Matrix *inv;
4201 evalue **subs;
4202 enode *p;
4203 int i, j;
4204 unsigned nparam = CP->NbColumns-1;
4205 Polyhedron *CEq;
4206 Value gcd;
4208 if (EVALUE_IS_ZERO(*e))
4209 return;
4211 assert(value_zero_p(e->d));
4212 p = e->x.p;
4213 assert(p->type == partition);
4215 inv = left_inverse(CP, &eq);
4216 subs = ALLOCN(evalue *, nparam);
4217 for (i = 0; i < nparam; ++i)
4218 subs[i] = affine2evalue(inv->p[i], inv->p[nparam][inv->NbColumns-1],
4219 inv->NbColumns-1);
4221 CEq = Constraints2Polyhedron(eq, MaxRays);
4222 addeliminatedparams_partition(p, inv, CEq, inv->NbColumns-1, MaxRays);
4223 Polyhedron_Free(CEq);
4225 for (i = 0; i < p->size/2; ++i)
4226 evalue_substitute(&p->arr[2*i+1], subs);
4228 for (i = 0; i < nparam; ++i)
4229 evalue_free(subs[i]);
4230 free(subs);
4232 value_init(gcd);
4233 for (i = 0; i < inv->NbRows-1; ++i) {
4234 Vector_Gcd(inv->p[i], inv->NbColumns, &gcd);
4235 value_gcd(gcd, gcd, inv->p[inv->NbRows-1][inv->NbColumns-1]);
4236 if (value_eq(gcd, inv->p[inv->NbRows-1][inv->NbColumns-1]))
4237 continue;
4238 Vector_AntiScale(inv->p[i], inv->p[i], gcd, inv->NbColumns);
4239 value_divexact(gcd, inv->p[inv->NbRows-1][inv->NbColumns-1], gcd);
4241 for (j = 0; j < p->size/2; ++j) {
4242 evalue *arg = affine2evalue(inv->p[i], gcd, inv->NbColumns-1);
4243 evalue *ev;
4244 evalue rel;
4246 value_init(rel.d);
4247 value_set_si(rel.d, 0);
4248 rel.x.p = new_enode(relation, 2, 0);
4249 value_clear(rel.x.p->arr[1].d);
4250 rel.x.p->arr[1] = p->arr[2*j+1];
4251 ev = &rel.x.p->arr[0];
4252 value_set_si(ev->d, 0);
4253 ev->x.p = new_enode(fractional, 3, -1);
4254 evalue_set_si(&ev->x.p->arr[1], 0, 1);
4255 evalue_set_si(&ev->x.p->arr[2], 1, 1);
4256 value_clear(ev->x.p->arr[0].d);
4257 ev->x.p->arr[0] = *arg;
4258 free(arg);
4260 p->arr[2*j+1] = rel;
4263 value_clear(gcd);
4265 Matrix_Free(eq);
4266 Matrix_Free(inv);
4269 /* Computes
4271 * \sum_{i=0}^n c_i/d X^i
4273 * where d is the last element in the vector c.
4275 evalue *evalue_polynomial(Vector *c, const evalue* X)
4277 unsigned dim = c->Size-2;
4278 evalue EC;
4279 evalue *EP = ALLOC(evalue);
4280 int i;
4282 value_init(EP->d);
4284 if (EVALUE_IS_ZERO(*X) || dim == 0) {
4285 evalue_set(EP, c->p[0], c->p[dim+1]);
4286 reduce_constant(EP);
4287 return EP;
4290 evalue_set(EP, c->p[dim], c->p[dim+1]);
4292 value_init(EC.d);
4293 evalue_set(&EC, c->p[dim], c->p[dim+1]);
4295 for (i = dim-1; i >= 0; --i) {
4296 emul(X, EP);
4297 value_assign(EC.x.n, c->p[i]);
4298 eadd(&EC, EP);
4300 free_evalue_refs(&EC);
4301 return EP;
4304 /* Create an evalue from an array of pairs of domains and evalues. */
4305 evalue *evalue_from_section_array(struct evalue_section *s, int n)
4307 int i;
4308 evalue *res;
4310 res = ALLOC(evalue);
4311 value_init(res->d);
4313 if (n == 0)
4314 evalue_set_si(res, 0, 1);
4315 else {
4316 value_set_si(res->d, 0);
4317 res->x.p = new_enode(partition, 2*n, s[0].D->Dimension);
4318 for (i = 0; i < n; ++i) {
4319 EVALUE_SET_DOMAIN(res->x.p->arr[2*i], s[i].D);
4320 value_clear(res->x.p->arr[2*i+1].d);
4321 res->x.p->arr[2*i+1] = *s[i].E;
4322 free(s[i].E);
4325 return res;
4328 /* shift variables (>= first, 0-based) in polynomial n up (may be negative) */
4329 void evalue_shift_variables(evalue *e, int first, int n)
4331 int i;
4332 if (value_notzero_p(e->d))
4333 return;
4334 assert(e->x.p->type == polynomial ||
4335 e->x.p->type == flooring ||
4336 e->x.p->type == fractional);
4337 if (e->x.p->type == polynomial && e->x.p->pos >= first+1) {
4338 assert(e->x.p->pos + n >= 1);
4339 e->x.p->pos += n;
4341 for (i = 0; i < e->x.p->size; ++i)
4342 evalue_shift_variables(&e->x.p->arr[i], first, n);
4345 static const evalue *outer_floor(evalue *e, const evalue *outer)
4347 int i;
4349 if (value_notzero_p(e->d))
4350 return outer;
4351 switch (e->x.p->type) {
4352 case flooring:
4353 if (!outer || evalue_level_cmp(outer, &e->x.p->arr[0]) > 0)
4354 return &e->x.p->arr[0];
4355 else
4356 return outer;
4357 case polynomial:
4358 case fractional:
4359 case relation:
4360 for (i = type_offset(e->x.p); i < e->x.p->size; ++i)
4361 outer = outer_floor(&e->x.p->arr[i], outer);
4362 return outer;
4363 case partition:
4364 for (i = 0; i < e->x.p->size/2; ++i)
4365 outer = outer_floor(&e->x.p->arr[2*i+1], outer);
4366 return outer;
4367 default:
4368 assert(0);
4372 /* Find and return outermost floor argument or NULL if e has no floors */
4373 evalue *evalue_outer_floor(evalue *e)
4375 const evalue *floor = outer_floor(e, NULL);
4376 return floor ? evalue_dup(floor): NULL;
4379 static void evalue_set_to_zero(evalue *e)
4381 if (EVALUE_IS_ZERO(*e))
4382 return;
4383 if (value_zero_p(e->d)) {
4384 free_evalue_refs(e);
4385 value_init(e->d);
4386 value_init(e->x.n);
4388 value_set_si(e->d, 1);
4389 value_set_si(e->x.n, 0);
4392 /* Replace (outer) floor with argument "floor" by variable "var" (0-based)
4393 * and drop terms not containing the floor.
4394 * Returns true if e contains the floor.
4396 int evalue_replace_floor(evalue *e, const evalue *floor, int var)
4398 int i;
4399 int contains = 0;
4400 int reorder = 0;
4402 if (value_notzero_p(e->d))
4403 return 0;
4404 switch (e->x.p->type) {
4405 case flooring:
4406 if (!eequal(floor, &e->x.p->arr[0]))
4407 return 0;
4408 e->x.p->type = polynomial;
4409 e->x.p->pos = 1 + var;
4410 e->x.p->size--;
4411 free_evalue_refs(&e->x.p->arr[0]);
4412 for (i = 0; i < e->x.p->size; ++i)
4413 e->x.p->arr[i] = e->x.p->arr[i+1];
4414 evalue_set_to_zero(&e->x.p->arr[0]);
4415 return 1;
4416 case polynomial:
4417 case fractional:
4418 case relation:
4419 for (i = type_offset(e->x.p); i < e->x.p->size; ++i) {
4420 int c = evalue_replace_floor(&e->x.p->arr[i], floor, var);
4421 contains |= c;
4422 if (!c)
4423 evalue_set_to_zero(&e->x.p->arr[i]);
4424 if (c && !reorder && evalue_level_cmp(&e->x.p->arr[i], e) < 0)
4425 reorder = 1;
4427 evalue_reduce_size(e);
4428 if (reorder)
4429 evalue_reorder_terms(e);
4430 return contains;
4431 case partition:
4432 default:
4433 assert(0);
4437 /* Replace (outer) floor with argument "floor" by variable zero */
4438 void evalue_drop_floor(evalue *e, const evalue *floor)
4440 int i;
4441 enode *p;
4443 if (value_notzero_p(e->d))
4444 return;
4445 switch (e->x.p->type) {
4446 case flooring:
4447 if (!eequal(floor, &e->x.p->arr[0]))
4448 return;
4449 p = e->x.p;
4450 free_evalue_refs(&p->arr[0]);
4451 for (i = 2; i < p->size; ++i)
4452 free_evalue_refs(&p->arr[i]);
4453 value_clear(e->d);
4454 *e = p->arr[1];
4455 free(p);
4456 break;
4457 case polynomial:
4458 case fractional:
4459 case relation:
4460 for (i = type_offset(e->x.p); i < e->x.p->size; ++i)
4461 evalue_drop_floor(&e->x.p->arr[i], floor);
4462 evalue_reduce_size(e);
4463 break;
4464 case partition:
4465 default:
4466 assert(0);
4470 /**
4472 PROCEDURES TO COMPUTE ENUMERATION. recursive procedure, recurse for
4473 each imbriquation
4475 @param pos index position of current loop index (1..hdim-1)
4476 @param P loop domain
4477 @param context context values for fixed indices
4478 @param exist number of existential variables
4479 @return the number of integer points in this
4480 polyhedron
4483 void count_points_e (int pos, Polyhedron *P, int exist, int nparam,
4484 Value *context, Value *res)
4486 Value LB, UB, k, c;
4488 if (emptyQ(P)) {
4489 value_set_si(*res, 0);
4490 return;
4493 if (!exist) {
4494 count_points(pos, P, context, res);
4495 return;
4498 value_init(LB); value_init(UB); value_init(k);
4499 value_set_si(LB,0);
4500 value_set_si(UB,0);
4502 if (lower_upper_bounds(pos,P,context,&LB,&UB) !=0) {
4503 /* Problem if UB or LB is INFINITY */
4504 value_clear(LB); value_clear(UB); value_clear(k);
4505 if (pos > P->Dimension - nparam - exist)
4506 value_set_si(*res, 1);
4507 else
4508 value_set_si(*res, -1);
4509 return;
4512 #ifdef EDEBUG1
4513 if (!P->next) {
4514 int i;
4515 for (value_assign(k,LB); value_le(k,UB); value_increment(k,k)) {
4516 fprintf(stderr, "(");
4517 for (i=1; i<pos; i++) {
4518 value_print(stderr,P_VALUE_FMT,context[i]);
4519 fprintf(stderr,",");
4521 value_print(stderr,P_VALUE_FMT,k);
4522 fprintf(stderr,")\n");
4525 #endif
4527 value_set_si(context[pos],0);
4528 if (value_lt(UB,LB)) {
4529 value_clear(LB); value_clear(UB); value_clear(k);
4530 value_set_si(*res, 0);
4531 return;
4533 if (!P->next) {
4534 if (exist)
4535 value_set_si(*res, 1);
4536 else {
4537 value_subtract(k,UB,LB);
4538 value_add_int(k,k,1);
4539 value_assign(*res, k);
4541 value_clear(LB); value_clear(UB); value_clear(k);
4542 return;
4545 /*-----------------------------------------------------------------*/
4546 /* Optimization idea */
4547 /* If inner loops are not a function of k (the current index) */
4548 /* i.e. if P->Constraint[i][pos]==0 for all P following this and */
4549 /* for all i, */
4550 /* Then CNT = (UB-LB+1)*count_points(pos+1, P->next, context) */
4551 /* (skip the for loop) */
4552 /*-----------------------------------------------------------------*/
4554 value_init(c);
4555 value_set_si(*res, 0);
4556 for (value_assign(k,LB);value_le(k,UB);value_increment(k,k)) {
4557 /* Insert k in context */
4558 value_assign(context[pos],k);
4559 count_points_e(pos+1, P->next, exist, nparam, context, &c);
4560 if(value_notmone_p(c))
4561 value_addto(*res, *res, c);
4562 else {
4563 value_set_si(*res, -1);
4564 break;
4566 if (pos > P->Dimension - nparam - exist &&
4567 value_pos_p(*res))
4568 break;
4570 value_clear(c);
4572 #ifdef EDEBUG11
4573 fprintf(stderr,"%d\n",CNT);
4574 #endif
4576 /* Reset context */
4577 value_set_si(context[pos],0);
4578 value_clear(LB); value_clear(UB); value_clear(k);
4579 return;
4580 } /* count_points_e */