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 /***********************************************************************/
18 #include <barvinok/evalue.h>
19 #include <barvinok/barvinok.h>
20 #include <barvinok/options.h>
21 #include <barvinok/util.h>
24 #ifndef value_pmodulus
25 #define value_pmodulus(ref,val1,val2) (mpz_fdiv_r((ref),(val1),(val2)))
28 #define ALLOC(type) (type*)malloc(sizeof(type))
29 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
32 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
34 #define NALLOC(p,n) p = (void *)malloc((n) * sizeof(*p))
37 void evalue_set_si(evalue
*ev
, int n
, int d
) {
38 value_set_si(ev
->d
, d
);
40 value_set_si(ev
->x
.n
, n
);
43 void evalue_set(evalue
*ev
, Value n
, Value d
) {
44 value_assign(ev
->d
, d
);
46 value_assign(ev
->x
.n
, n
);
49 void evalue_set_reduce(evalue
*ev
, Value n
, Value d
) {
51 value_gcd(ev
->x
.n
, n
, d
);
52 value_divexact(ev
->d
, d
, ev
->x
.n
);
53 value_divexact(ev
->x
.n
, n
, ev
->x
.n
);
58 evalue
*EP
= ALLOC(evalue
);
60 evalue_set_si(EP
, 0, 1);
66 evalue
*EP
= ALLOC(evalue
);
68 value_set_si(EP
->d
, -2);
73 /* returns an evalue that corresponds to
77 evalue
*evalue_var(int var
)
79 evalue
*EP
= ALLOC(evalue
);
81 value_set_si(EP
->d
,0);
82 EP
->x
.p
= new_enode(polynomial
, 2, var
+ 1);
83 evalue_set_si(&EP
->x
.p
->arr
[0], 0, 1);
84 evalue_set_si(&EP
->x
.p
->arr
[1], 1, 1);
88 void aep_evalue(evalue
*e
, int *ref
) {
93 if (value_notzero_p(e
->d
))
94 return; /* a rational number, its already reduced */
96 return; /* hum... an overflow probably occured */
98 /* First check the components of p */
99 for (i
=0;i
<p
->size
;i
++)
100 aep_evalue(&p
->arr
[i
],ref
);
107 p
->pos
= ref
[p
->pos
-1]+1;
113 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
119 if (value_notzero_p(e
->d
))
120 return; /* a rational number, its already reduced */
122 return; /* hum... an overflow probably occured */
125 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
126 for(i
=0;i
<CT
->NbRows
-1;i
++)
127 for(j
=0;j
<CT
->NbColumns
;j
++)
128 if(value_notzero_p(CT
->p
[i
][j
])) {
133 /* Transform the references in e, using ref */
137 } /* addeliminatedparams_evalue */
139 static void addeliminatedparams_partition(enode
*p
, Matrix
*CT
, Polyhedron
*CEq
,
140 unsigned nparam
, unsigned MaxRays
)
143 assert(p
->type
== partition
);
146 for (i
= 0; i
< p
->size
/2; i
++) {
147 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
148 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
152 T
= DomainIntersection(D
, CEq
, MaxRays
);
155 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
159 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
160 unsigned MaxRays
, unsigned nparam
)
165 if (CT
->NbRows
== CT
->NbColumns
)
168 if (EVALUE_IS_ZERO(*e
))
171 if (value_notzero_p(e
->d
)) {
174 value_set_si(res
.d
, 0);
175 res
.x
.p
= new_enode(partition
, 2, nparam
);
176 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
177 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
178 value_clear(res
.x
.p
->arr
[1].d
);
179 res
.x
.p
->arr
[1] = *e
;
187 addeliminatedparams_partition(p
, CT
, CEq
, nparam
, MaxRays
);
188 for (i
= 0; i
< p
->size
/2; i
++)
189 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
192 static int mod_rational_cmp(evalue
*e1
, evalue
*e2
)
200 assert(value_notzero_p(e1
->d
));
201 assert(value_notzero_p(e2
->d
));
202 value_multiply(m
, e1
->x
.n
, e2
->d
);
203 value_multiply(m2
, e2
->x
.n
, e1
->d
);
206 else if (value_gt(m
, m2
))
216 static int mod_term_cmp_r(evalue
*e1
, evalue
*e2
)
218 if (value_notzero_p(e1
->d
)) {
220 if (value_zero_p(e2
->d
))
222 return mod_rational_cmp(e1
, e2
);
224 if (value_notzero_p(e2
->d
))
226 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
228 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
231 int r
= mod_rational_cmp(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
233 ? mod_term_cmp_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
238 static int mod_term_cmp(const evalue
*e1
, const evalue
*e2
)
240 assert(value_zero_p(e1
->d
));
241 assert(value_zero_p(e2
->d
));
242 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
243 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
244 return mod_term_cmp_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
247 static void check_order(const evalue
*e
)
252 if (value_notzero_p(e
->d
))
255 switch (e
->x
.p
->type
) {
257 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
258 check_order(&e
->x
.p
->arr
[2*i
+1]);
261 for (i
= 1; i
< e
->x
.p
->size
; ++i
) {
263 if (value_notzero_p(a
->d
))
265 switch (a
->x
.p
->type
) {
267 assert(mod_term_cmp(&e
->x
.p
->arr
[0], &a
->x
.p
->arr
[0]) < 0);
276 for (i
= 0; i
< e
->x
.p
->size
; ++i
) {
278 if (value_notzero_p(a
->d
))
280 switch (a
->x
.p
->type
) {
282 assert(e
->x
.p
->pos
< a
->x
.p
->pos
);
293 for (i
= 1; i
< e
->x
.p
->size
; ++i
) {
295 if (value_notzero_p(a
->d
))
297 switch (a
->x
.p
->type
) {
308 /* Negative pos means inequality */
309 /* s is negative of substitution if m is not zero */
318 struct fixed_param
*fixed
;
323 static int relations_depth(evalue
*e
)
328 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
329 e
= &e
->x
.p
->arr
[1], ++d
);
333 static void poly_denom_not_constant(evalue
**pp
, Value
*d
)
338 while (value_zero_p(p
->d
)) {
339 assert(p
->x
.p
->type
== polynomial
);
340 assert(p
->x
.p
->size
== 2);
341 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
342 value_lcm(*d
, *d
, p
->x
.p
->arr
[1].d
);
348 static void poly_denom(evalue
*p
, Value
*d
)
350 poly_denom_not_constant(&p
, d
);
351 value_lcm(*d
, *d
, p
->d
);
354 static void realloc_substitution(struct subst
*s
, int d
)
356 struct fixed_param
*n
;
359 for (i
= 0; i
< s
->n
; ++i
)
366 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
372 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
375 /* May have been reduced already */
376 if (value_notzero_p(m
->d
))
379 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
380 assert(m
->x
.p
->size
== 3);
382 /* fractional was inverted during reduction
383 * invert it back and move constant in
385 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
386 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
387 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
388 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
389 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
390 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
391 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
392 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
393 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
394 value_set_si(m
->x
.p
->arr
[1].d
, 1);
397 /* Oops. Nested identical relations. */
398 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
401 if (s
->n
>= s
->max
) {
402 int d
= relations_depth(r
);
403 realloc_substitution(s
, d
);
407 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
408 assert(p
->x
.p
->size
== 2);
411 assert(value_pos_p(f
->x
.n
));
413 value_init(s
->fixed
[s
->n
].m
);
414 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
415 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
416 value_init(s
->fixed
[s
->n
].d
);
417 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
418 value_init(s
->fixed
[s
->n
].s
.d
);
419 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
425 static int type_offset(enode
*p
)
427 return p
->type
== fractional
? 1 :
428 p
->type
== flooring
? 1 :
429 p
->type
== relation
? 1 : 0;
432 static void reorder_terms_about(enode
*p
, evalue
*v
)
435 int offset
= type_offset(p
);
437 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
439 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
440 free_evalue_refs(&(p
->arr
[i
]));
446 void evalue_reorder_terms(evalue
*e
)
452 assert(value_zero_p(e
->d
));
454 assert(p
->type
== fractional
||
455 p
->type
== flooring
||
456 p
->type
== polynomial
); /* for now */
458 offset
= type_offset(p
);
460 value_set_si(f
.d
, 0);
461 f
.x
.p
= new_enode(p
->type
, offset
+2, p
->pos
);
463 value_clear(f
.x
.p
->arr
[0].d
);
464 f
.x
.p
->arr
[0] = p
->arr
[0];
466 evalue_set_si(&f
.x
.p
->arr
[offset
], 0, 1);
467 evalue_set_si(&f
.x
.p
->arr
[offset
+1], 1, 1);
468 reorder_terms_about(p
, &f
);
474 static void evalue_reduce_size(evalue
*e
)
478 assert(value_zero_p(e
->d
));
481 offset
= type_offset(p
);
483 /* Try to reduce the degree */
484 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
485 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
487 free_evalue_refs(&p
->arr
[i
]);
492 /* Try to reduce its strength */
493 if (p
->type
== relation
) {
495 free_evalue_refs(&p
->arr
[0]);
496 evalue_set_si(e
, 0, 1);
499 } else if (p
->size
== offset
+1) {
501 memcpy(e
, &p
->arr
[offset
], sizeof(evalue
));
503 free_evalue_refs(&p
->arr
[0]);
508 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
510 /* This function is called after the argument of the fractional part
511 * in a polynomial expression in this fractional part has been reduced.
512 * If the polynomial expression is of degree at least two, then
513 * check if the argument happens to have been reduced to an affine
514 * expression with denominator two. If so, then emul_fractionals
515 * assumes that the polynomial expression in this fractional part
516 * is affine so we reduce the higher degree polynomial to an affine
519 * In particular, since the denominator of the fractional part is two,
520 * then the fractional part can only take on two values, 0 and 1/2.
521 * This means that { f(x)/2 }^2 = 1/2 { f(x)/2 } so that we can repeatedly
524 * a_n { f(x)/2 }^n with n >= 2
528 * a_n/2 { f(x)/2 }^{n-1}
530 static void reduce_fractional(evalue
*e
)
535 if (e
->x
.p
->size
<= 3)
539 poly_denom(&e
->x
.p
->arr
[0], &d
.d
);
540 if (value_two_p(d
.d
)) {
542 value_set_si(d
.x
.n
, 1);
543 for (i
= e
->x
.p
->size
- 1; i
>= 3; --i
) {
544 emul(&d
, &e
->x
.p
->arr
[i
]);
545 eadd(&e
->x
.p
->arr
[i
], &e
->x
.p
->arr
[i
- 1]);
546 free_evalue_refs(&e
->x
.p
->arr
[i
]);
554 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
560 if (value_notzero_p(e
->d
)) {
562 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
563 return; /* a rational number, its already reduced */
567 return; /* hum... an overflow probably occured */
569 /* First reduce the components of p */
570 add
= p
->type
== relation
;
571 for (i
=0; i
<p
->size
; i
++) {
573 add
= add_modulo_substitution(s
, e
);
575 if (i
== 0 && p
->type
==fractional
) {
576 _reduce_evalue(&p
->arr
[i
], s
, 1);
577 reduce_fractional(e
);
579 _reduce_evalue(&p
->arr
[i
], s
, fract
);
581 if (add
&& i
== p
->size
-1) {
583 value_clear(s
->fixed
[s
->n
].m
);
584 value_clear(s
->fixed
[s
->n
].d
);
585 free_evalue_refs(&s
->fixed
[s
->n
].s
);
586 } else if (add
&& i
== 1)
587 s
->fixed
[s
->n
-1].pos
*= -1;
590 if (p
->type
==periodic
) {
592 /* Try to reduce the period */
593 for (i
=1; i
<=(p
->size
)/2; i
++) {
594 if ((p
->size
% i
)==0) {
596 /* Can we reduce the size to i ? */
598 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
599 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
602 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
606 you_lose
: /* OK, lets not do it */
611 /* Try to reduce its strength */
614 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
618 else if (p
->type
==polynomial
) {
619 for (k
= 0; s
&& k
< s
->n
; ++k
) {
620 if (s
->fixed
[k
].pos
== p
->pos
) {
621 int divide
= value_notone_p(s
->fixed
[k
].d
);
624 if (value_notzero_p(s
->fixed
[k
].m
)) {
627 assert(p
->size
== 2);
628 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
630 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
637 value_assign(d
.d
, s
->fixed
[k
].d
);
639 if (value_notzero_p(s
->fixed
[k
].m
))
640 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
642 value_set_si(d
.x
.n
, 1);
645 for (i
=p
->size
-1;i
>=1;i
--) {
646 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
648 emul(&d
, &p
->arr
[i
]);
649 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
650 free_evalue_refs(&(p
->arr
[i
]));
653 _reduce_evalue(&p
->arr
[0], s
, fract
);
656 free_evalue_refs(&d
);
662 evalue_reduce_size(e
);
664 else if (p
->type
==fractional
) {
668 if (value_notzero_p(p
->arr
[0].d
)) {
670 value_assign(v
.d
, p
->arr
[0].d
);
672 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
677 evalue
*pp
= &p
->arr
[0];
678 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
679 assert(pp
->x
.p
->size
== 2);
681 /* search for exact duplicate among the modulo inequalities */
683 f
= &pp
->x
.p
->arr
[1];
684 for (k
= 0; s
&& k
< s
->n
; ++k
) {
685 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
686 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
687 value_eq(s
->fixed
[k
].m
, f
->d
) &&
688 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
695 /* replace { E/m } by { (E-1)/m } + 1/m */
700 evalue_set_si(&extra
, 1, 1);
701 value_assign(extra
.d
, g
);
702 eadd(&extra
, &v
.x
.p
->arr
[1]);
703 free_evalue_refs(&extra
);
705 /* We've been going in circles; stop now */
706 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
707 free_evalue_refs(&v
);
709 evalue_set_si(&v
, 0, 1);
714 value_set_si(v
.d
, 0);
715 v
.x
.p
= new_enode(fractional
, 3, -1);
716 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
717 value_assign(v
.x
.p
->arr
[1].d
, g
);
718 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
719 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
722 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
725 value_division(f
->d
, g
, f
->d
);
726 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
727 value_assign(f
->d
, g
);
728 value_decrement(f
->x
.n
, f
->x
.n
);
729 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
731 value_gcd(g
, f
->d
, f
->x
.n
);
732 value_division(f
->d
, f
->d
, g
);
733 value_division(f
->x
.n
, f
->x
.n
, g
);
742 /* reduction may have made this fractional arg smaller */
743 i
= reorder
? p
->size
: 1;
744 for ( ; i
< p
->size
; ++i
)
745 if (value_zero_p(p
->arr
[i
].d
) &&
746 p
->arr
[i
].x
.p
->type
== fractional
&&
747 mod_term_cmp(e
, &p
->arr
[i
]) >= 0)
751 value_set_si(v
.d
, 0);
752 v
.x
.p
= new_enode(fractional
, 3, -1);
753 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
754 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
755 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
763 evalue
*pp
= &p
->arr
[0];
766 poly_denom_not_constant(&pp
, &m
);
767 mpz_fdiv_r(r
, m
, pp
->d
);
768 if (value_notzero_p(r
)) {
770 value_set_si(v
.d
, 0);
771 v
.x
.p
= new_enode(fractional
, 3, -1);
773 value_multiply(r
, m
, pp
->x
.n
);
774 value_multiply(v
.x
.p
->arr
[1].d
, m
, pp
->d
);
775 value_init(v
.x
.p
->arr
[1].x
.n
);
776 mpz_fdiv_r(v
.x
.p
->arr
[1].x
.n
, r
, pp
->d
);
777 mpz_fdiv_q(r
, r
, pp
->d
);
779 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
780 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
782 while (value_zero_p(pp
->d
))
783 pp
= &pp
->x
.p
->arr
[0];
785 value_assign(pp
->d
, m
);
786 value_assign(pp
->x
.n
, r
);
788 value_gcd(r
, pp
->d
, pp
->x
.n
);
789 value_division(pp
->d
, pp
->d
, r
);
790 value_division(pp
->x
.n
, pp
->x
.n
, r
);
803 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
804 pp
= &pp
->x
.p
->arr
[0]) {
805 f
= &pp
->x
.p
->arr
[1];
806 assert(value_pos_p(f
->d
));
807 mpz_mul_ui(twice
, f
->x
.n
, 2);
808 if (value_lt(twice
, f
->d
))
810 if (value_eq(twice
, f
->d
))
818 value_set_si(v
.d
, 0);
819 v
.x
.p
= new_enode(fractional
, 3, -1);
820 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
821 poly_denom(&p
->arr
[0], &twice
);
822 value_assign(v
.x
.p
->arr
[1].d
, twice
);
823 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
824 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
825 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
827 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
828 pp
= &pp
->x
.p
->arr
[0]) {
829 f
= &pp
->x
.p
->arr
[1];
830 value_oppose(f
->x
.n
, f
->x
.n
);
831 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
833 value_division(pp
->d
, twice
, pp
->d
);
834 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
835 value_assign(pp
->d
, twice
);
836 value_oppose(pp
->x
.n
, pp
->x
.n
);
837 value_decrement(pp
->x
.n
, pp
->x
.n
);
838 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
840 /* Maybe we should do this during reduction of
843 value_gcd(twice
, pp
->d
, pp
->x
.n
);
844 value_division(pp
->d
, pp
->d
, twice
);
845 value_division(pp
->x
.n
, pp
->x
.n
, twice
);
855 reorder_terms_about(p
, &v
);
856 _reduce_evalue(&p
->arr
[1], s
, fract
);
859 evalue_reduce_size(e
);
861 else if (p
->type
== flooring
) {
862 /* Replace floor(constant) by its value */
863 if (value_notzero_p(p
->arr
[0].d
)) {
866 value_set_si(v
.d
, 1);
868 mpz_fdiv_q(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
869 reorder_terms_about(p
, &v
);
870 _reduce_evalue(&p
->arr
[1], s
, fract
);
872 evalue_reduce_size(e
);
874 else if (p
->type
== relation
) {
875 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
876 free_evalue_refs(&(p
->arr
[2]));
877 free_evalue_refs(&(p
->arr
[0]));
884 evalue_reduce_size(e
);
885 if (value_notzero_p(e
->d
) || p
!= e
->x
.p
)
892 /* Relation was reduced by means of an identical
893 * inequality => remove
895 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
898 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
899 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
901 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
903 free_evalue_refs(&(p
->arr
[2]));
907 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
909 evalue_set_si(e
, 0, 1);
910 free_evalue_refs(&(p
->arr
[1]));
912 free_evalue_refs(&(p
->arr
[0]));
918 } /* reduce_evalue */
920 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
925 for (k
= 0; k
< dim
; ++k
)
926 if (value_notzero_p(row
[k
+1]))
929 Vector_Normalize_Positive(row
+1, dim
+1, k
);
930 assert(s
->n
< s
->max
);
931 value_init(s
->fixed
[s
->n
].d
);
932 value_init(s
->fixed
[s
->n
].m
);
933 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
934 s
->fixed
[s
->n
].pos
= k
+1;
935 value_set_si(s
->fixed
[s
->n
].m
, 0);
936 r
= &s
->fixed
[s
->n
].s
;
938 for (l
= k
+1; l
< dim
; ++l
)
939 if (value_notzero_p(row
[l
+1])) {
940 value_set_si(r
->d
, 0);
941 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
942 value_init(r
->x
.p
->arr
[1].x
.n
);
943 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
944 value_set_si(r
->x
.p
->arr
[1].d
, 1);
948 value_oppose(r
->x
.n
, row
[dim
+1]);
949 value_set_si(r
->d
, 1);
953 static void _reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
, struct subst
*s
)
956 Polyhedron
*orig
= D
;
961 D
= DomainConvex(D
, 0);
962 /* We don't perform any substitutions if the domain is a union.
963 * We may therefore miss out on some possible simplifications,
964 * e.g., if a variable is always even in the whole union,
965 * while there is a relation in the evalue that evaluates
966 * to zero for even values of the variable.
968 if (!D
->next
&& D
->NbEq
) {
972 realloc_substitution(s
, dim
);
974 int d
= relations_depth(e
);
976 NALLOC(s
->fixed
, s
->max
);
979 for (j
= 0; j
< D
->NbEq
; ++j
)
980 add_substitution(s
, D
->Constraint
[j
], dim
);
984 _reduce_evalue(e
, s
, 0);
987 for (j
= 0; j
< s
->n
; ++j
) {
988 value_clear(s
->fixed
[j
].d
);
989 value_clear(s
->fixed
[j
].m
);
990 free_evalue_refs(&s
->fixed
[j
].s
);
995 void reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
)
997 struct subst s
= { NULL
, 0, 0 };
998 POL_ENSURE_VERTICES(D
);
1000 if (EVALUE_IS_ZERO(*e
))
1002 free_evalue_refs(e
);
1004 evalue_set_si(e
, 0, 1);
1007 _reduce_evalue_in_domain(e
, D
, &s
);
1012 void reduce_evalue (evalue
*e
) {
1013 struct subst s
= { NULL
, 0, 0 };
1015 if (value_notzero_p(e
->d
))
1016 return; /* a rational number, its already reduced */
1018 if (e
->x
.p
->type
== partition
) {
1020 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
1021 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
1023 /* This shouldn't really happen;
1024 * Empty domains should not be added.
1026 POL_ENSURE_VERTICES(D
);
1028 _reduce_evalue_in_domain(&e
->x
.p
->arr
[2*i
+1], D
, &s
);
1030 if (emptyQ(D
) || EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
1031 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
1032 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
1033 value_clear(e
->x
.p
->arr
[2*i
].d
);
1035 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
1036 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
1040 if (e
->x
.p
->size
== 0) {
1042 evalue_set_si(e
, 0, 1);
1045 _reduce_evalue(e
, &s
, 0);
1050 static void print_evalue_r(FILE *DST
, const evalue
*e
, const char **pname
)
1052 if (EVALUE_IS_NAN(*e
)) {
1053 fprintf(DST
, "NaN");
1057 if(value_notzero_p(e
->d
)) {
1058 if(value_notone_p(e
->d
)) {
1059 value_print(DST
,VALUE_FMT
,e
->x
.n
);
1061 value_print(DST
,VALUE_FMT
,e
->d
);
1064 value_print(DST
,VALUE_FMT
,e
->x
.n
);
1068 print_enode(DST
,e
->x
.p
,pname
);
1070 } /* print_evalue */
1072 void print_evalue(FILE *DST
, const evalue
*e
, const char **pname
)
1074 print_evalue_r(DST
, e
, pname
);
1075 if (value_notzero_p(e
->d
))
1079 void print_enode(FILE *DST
, enode
*p
, const char **pname
)
1084 fprintf(DST
, "NULL");
1090 for (i
=0; i
<p
->size
; i
++) {
1091 print_evalue_r(DST
, &p
->arr
[i
], pname
);
1095 fprintf(DST
, " }\n");
1099 for (i
=p
->size
-1; i
>=0; i
--) {
1100 print_evalue_r(DST
, &p
->arr
[i
], pname
);
1101 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
1103 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
1105 fprintf(DST
, " )\n");
1109 for (i
=0; i
<p
->size
; i
++) {
1110 print_evalue_r(DST
, &p
->arr
[i
], pname
);
1111 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
1113 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
1118 for (i
=p
->size
-1; i
>=1; i
--) {
1119 print_evalue_r(DST
, &p
->arr
[i
], pname
);
1121 fprintf(DST
, " * ");
1122 fprintf(DST
, p
->type
== flooring
? "[" : "{");
1123 print_evalue_r(DST
, &p
->arr
[0], pname
);
1124 fprintf(DST
, p
->type
== flooring
? "]" : "}");
1126 fprintf(DST
, "^%d + ", i
-1);
1128 fprintf(DST
, " + ");
1131 fprintf(DST
, " )\n");
1135 print_evalue_r(DST
, &p
->arr
[0], pname
);
1136 fprintf(DST
, "= 0 ] * \n");
1137 print_evalue_r(DST
, &p
->arr
[1], pname
);
1139 fprintf(DST
, " +\n [ ");
1140 print_evalue_r(DST
, &p
->arr
[0], pname
);
1141 fprintf(DST
, "!= 0 ] * \n");
1142 print_evalue_r(DST
, &p
->arr
[2], pname
);
1146 char **new_names
= NULL
;
1147 const char **names
= pname
;
1148 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
1149 if (!pname
|| p
->pos
< maxdim
) {
1150 new_names
= ALLOCN(char *, maxdim
);
1151 for (i
= 0; i
< p
->pos
; ++i
) {
1153 new_names
[i
] = (char *)pname
[i
];
1155 new_names
[i
] = ALLOCN(char, 10);
1156 snprintf(new_names
[i
], 10, "%c", 'P'+i
);
1159 for ( ; i
< maxdim
; ++i
) {
1160 new_names
[i
] = ALLOCN(char, 10);
1161 snprintf(new_names
[i
], 10, "_p%d", i
);
1163 names
= (const char**)new_names
;
1166 for (i
=0; i
<p
->size
/2; i
++) {
1167 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
1168 print_evalue_r(DST
, &p
->arr
[2*i
+1], names
);
1169 if (value_notzero_p(p
->arr
[2*i
+1].d
))
1173 if (!pname
|| p
->pos
< maxdim
) {
1174 for (i
= pname
? p
->pos
: 0; i
< maxdim
; ++i
)
1188 * 0 if toplevels of e1 and e2 are at the same level
1189 * <0 if toplevel of e1 should be outside of toplevel of e2
1190 * >0 if toplevel of e2 should be outside of toplevel of e1
1192 static int evalue_level_cmp(const evalue
*e1
, const evalue
*e2
)
1194 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
))
1196 if (value_notzero_p(e1
->d
))
1198 if (value_notzero_p(e2
->d
))
1200 if (e1
->x
.p
->type
== partition
&& e2
->x
.p
->type
== partition
)
1202 if (e1
->x
.p
->type
== partition
)
1204 if (e2
->x
.p
->type
== partition
)
1206 if (e1
->x
.p
->type
== relation
&& e2
->x
.p
->type
== relation
) {
1207 if (eequal(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]))
1209 return mod_term_cmp(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
1211 if (e1
->x
.p
->type
== relation
)
1213 if (e2
->x
.p
->type
== relation
)
1215 if (e1
->x
.p
->type
== polynomial
&& e2
->x
.p
->type
== polynomial
)
1216 return e1
->x
.p
->pos
- e2
->x
.p
->pos
;
1217 if (e1
->x
.p
->type
== polynomial
)
1219 if (e2
->x
.p
->type
== polynomial
)
1221 if (e1
->x
.p
->type
== periodic
&& e2
->x
.p
->type
== periodic
)
1222 return e1
->x
.p
->pos
- e2
->x
.p
->pos
;
1223 assert(e1
->x
.p
->type
!= periodic
);
1224 assert(e2
->x
.p
->type
!= periodic
);
1225 assert(e1
->x
.p
->type
== e2
->x
.p
->type
);
1226 if (eequal(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]))
1228 return mod_term_cmp(e1
, e2
);
1231 static void eadd_rev(const evalue
*e1
, evalue
*res
)
1235 evalue_copy(&ev
, e1
);
1237 free_evalue_refs(res
);
1241 static void eadd_rev_cst(const evalue
*e1
, evalue
*res
)
1245 evalue_copy(&ev
, e1
);
1246 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
1247 free_evalue_refs(res
);
1251 struct section
{ Polyhedron
* D
; evalue E
; };
1253 void eadd_partitions(const evalue
*e1
, evalue
*res
)
1258 s
= (struct section
*)
1259 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
1260 sizeof(struct section
));
1262 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1263 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1264 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1267 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1268 assert(res
->x
.p
->size
>= 2);
1269 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1270 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
1272 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
1274 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1279 fd
= DomainConstraintSimplify(fd
, 0);
1284 value_init(s
[n
].E
.d
);
1285 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
1289 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1290 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
1291 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1293 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1294 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1295 d
= DomainConstraintSimplify(d
, 0);
1301 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1302 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1304 value_init(s
[n
].E
.d
);
1305 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1306 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1311 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1315 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1318 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1319 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1320 value_clear(res
->x
.p
->arr
[2*i
].d
);
1325 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1326 for (j
= 0; j
< n
; ++j
) {
1327 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1328 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1329 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1335 static void explicit_complement(evalue
*res
)
1337 enode
*rel
= new_enode(relation
, 3, 0);
1339 value_clear(rel
->arr
[0].d
);
1340 rel
->arr
[0] = res
->x
.p
->arr
[0];
1341 value_clear(rel
->arr
[1].d
);
1342 rel
->arr
[1] = res
->x
.p
->arr
[1];
1343 value_set_si(rel
->arr
[2].d
, 1);
1344 value_init(rel
->arr
[2].x
.n
);
1345 value_set_si(rel
->arr
[2].x
.n
, 0);
1350 static void reduce_constant(evalue
*e
)
1355 value_gcd(g
, e
->x
.n
, e
->d
);
1356 if (value_notone_p(g
)) {
1357 value_division(e
->d
, e
->d
,g
);
1358 value_division(e
->x
.n
, e
->x
.n
,g
);
1363 /* Add two rational numbers */
1364 static void eadd_rationals(const evalue
*e1
, evalue
*res
)
1366 if (value_eq(e1
->d
, res
->d
))
1367 value_addto(res
->x
.n
, res
->x
.n
, e1
->x
.n
);
1369 value_multiply(res
->x
.n
, res
->x
.n
, e1
->d
);
1370 value_addmul(res
->x
.n
, e1
->x
.n
, res
->d
);
1371 value_multiply(res
->d
,e1
->d
,res
->d
);
1373 reduce_constant(res
);
1376 static void eadd_relations(const evalue
*e1
, evalue
*res
)
1380 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1381 explicit_complement(res
);
1382 for (i
= 1; i
< e1
->x
.p
->size
; ++i
)
1383 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1386 static void eadd_arrays(const evalue
*e1
, evalue
*res
, int n
)
1390 // add any element in e1 to the corresponding element in res
1391 i
= type_offset(res
->x
.p
);
1393 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1395 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1398 static void eadd_poly(const evalue
*e1
, evalue
*res
)
1400 if (e1
->x
.p
->size
> res
->x
.p
->size
)
1403 eadd_arrays(e1
, res
, e1
->x
.p
->size
);
1407 * Product or sum of two periodics of the same parameter
1408 * and different periods
1410 static void combine_periodics(const evalue
*e1
, evalue
*res
,
1411 void (*op
)(const evalue
*, evalue
*))
1419 value_set_si(es
, e1
->x
.p
->size
);
1420 value_set_si(rs
, res
->x
.p
->size
);
1421 value_lcm(rs
, es
, rs
);
1422 size
= (int)mpz_get_si(rs
);
1425 p
= new_enode(periodic
, size
, e1
->x
.p
->pos
);
1426 for (i
= 0; i
< res
->x
.p
->size
; i
++) {
1427 value_clear(p
->arr
[i
].d
);
1428 p
->arr
[i
] = res
->x
.p
->arr
[i
];
1430 for (i
= res
->x
.p
->size
; i
< size
; i
++)
1431 evalue_copy(&p
->arr
[i
], &res
->x
.p
->arr
[i
% res
->x
.p
->size
]);
1432 for (i
= 0; i
< size
; i
++)
1433 op(&e1
->x
.p
->arr
[i
% e1
->x
.p
->size
], &p
->arr
[i
]);
1438 static void eadd_periodics(const evalue
*e1
, evalue
*res
)
1444 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1445 eadd_arrays(e1
, res
, e1
->x
.p
->size
);
1449 combine_periodics(e1
, res
, eadd
);
1452 void evalue_assign(evalue
*dst
, const evalue
*src
)
1454 if (value_pos_p(dst
->d
) && value_pos_p(src
->d
)) {
1455 value_assign(dst
->d
, src
->d
);
1456 value_assign(dst
->x
.n
, src
->x
.n
);
1459 free_evalue_refs(dst
);
1461 evalue_copy(dst
, src
);
1464 void eadd(const evalue
*e1
, evalue
*res
)
1468 if (EVALUE_IS_ZERO(*e1
))
1471 if (EVALUE_IS_NAN(*res
))
1474 if (EVALUE_IS_NAN(*e1
)) {
1475 evalue_assign(res
, e1
);
1479 if (EVALUE_IS_ZERO(*res
)) {
1480 evalue_assign(res
, e1
);
1484 cmp
= evalue_level_cmp(res
, e1
);
1486 switch (e1
->x
.p
->type
) {
1490 eadd_rev_cst(e1
, res
);
1495 } else if (cmp
== 0) {
1496 if (value_notzero_p(e1
->d
)) {
1497 eadd_rationals(e1
, res
);
1499 switch (e1
->x
.p
->type
) {
1501 eadd_partitions(e1
, res
);
1504 eadd_relations(e1
, res
);
1507 assert(e1
->x
.p
->size
== res
->x
.p
->size
);
1514 eadd_periodics(e1
, res
);
1522 switch (res
->x
.p
->type
) {
1526 /* Add to the constant term of a polynomial */
1527 eadd(e1
, &res
->x
.p
->arr
[type_offset(res
->x
.p
)]);
1530 /* Add to all elements of a periodic number */
1531 for (i
= 0; i
< res
->x
.p
->size
; i
++)
1532 eadd(e1
, &res
->x
.p
->arr
[i
]);
1535 fprintf(stderr
, "eadd: cannot add const with vector\n");
1540 /* Create (zero) complement if needed */
1541 if (res
->x
.p
->size
< 3)
1542 explicit_complement(res
);
1543 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1544 eadd(e1
, &res
->x
.p
->arr
[i
]);
1552 static void emul_rev(const evalue
*e1
, evalue
*res
)
1556 evalue_copy(&ev
, e1
);
1558 free_evalue_refs(res
);
1562 static void emul_poly(const evalue
*e1
, evalue
*res
)
1564 int i
, j
, offset
= type_offset(res
->x
.p
);
1567 int size
= (e1
->x
.p
->size
+ res
->x
.p
->size
- offset
- 1);
1569 p
= new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1571 for (i
= offset
; i
< e1
->x
.p
->size
-1; ++i
)
1572 if (!EVALUE_IS_ZERO(e1
->x
.p
->arr
[i
]))
1575 /* special case pure power */
1576 if (i
== e1
->x
.p
->size
-1) {
1578 value_clear(p
->arr
[0].d
);
1579 p
->arr
[0] = res
->x
.p
->arr
[0];
1581 for (i
= offset
; i
< e1
->x
.p
->size
-1; ++i
)
1582 evalue_set_si(&p
->arr
[i
], 0, 1);
1583 for (i
= offset
; i
< res
->x
.p
->size
; ++i
) {
1584 value_clear(p
->arr
[i
+e1
->x
.p
->size
-offset
-1].d
);
1585 p
->arr
[i
+e1
->x
.p
->size
-offset
-1] = res
->x
.p
->arr
[i
];
1586 emul(&e1
->x
.p
->arr
[e1
->x
.p
->size
-1],
1587 &p
->arr
[i
+e1
->x
.p
->size
-offset
-1]);
1595 value_set_si(tmp
.d
,0);
1598 evalue_copy(&p
->arr
[0], &e1
->x
.p
->arr
[0]);
1599 for (i
= offset
; i
< e1
->x
.p
->size
; i
++) {
1600 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1601 emul(&res
->x
.p
->arr
[offset
], &tmp
.x
.p
->arr
[i
]);
1604 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1605 for (i
= offset
+1; i
<res
->x
.p
->size
; i
++)
1606 for (j
= offset
; j
<e1
->x
.p
->size
; j
++) {
1609 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1610 emul(&res
->x
.p
->arr
[i
], &ev
);
1611 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-offset
]);
1612 free_evalue_refs(&ev
);
1614 free_evalue_refs(res
);
1618 void emul_partitions(const evalue
*e1
, evalue
*res
)
1623 s
= (struct section
*)
1624 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1625 sizeof(struct section
));
1627 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1628 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1629 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1632 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1633 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1634 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1635 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1636 d
= DomainConstraintSimplify(d
, 0);
1642 /* This code is only needed because the partitions
1643 are not true partitions.
1645 for (k
= 0; k
< n
; ++k
) {
1646 if (DomainIncludes(s
[k
].D
, d
))
1648 if (DomainIncludes(d
, s
[k
].D
)) {
1649 Domain_Free(s
[k
].D
);
1650 free_evalue_refs(&s
[k
].E
);
1661 value_init(s
[n
].E
.d
);
1662 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1663 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1667 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1668 value_clear(res
->x
.p
->arr
[2*i
].d
);
1669 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1674 evalue_set_si(res
, 0, 1);
1676 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1677 for (j
= 0; j
< n
; ++j
) {
1678 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1679 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1680 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1687 /* Product of two rational numbers */
1688 static void emul_rationals(const evalue
*e1
, evalue
*res
)
1690 value_multiply(res
->d
, e1
->d
, res
->d
);
1691 value_multiply(res
->x
.n
, e1
->x
.n
, res
->x
.n
);
1692 reduce_constant(res
);
1695 static void emul_relations(const evalue
*e1
, evalue
*res
)
1699 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3) {
1700 free_evalue_refs(&res
->x
.p
->arr
[2]);
1703 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1704 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1707 static void emul_periodics(const evalue
*e1
, evalue
*res
)
1714 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1715 /* Product of two periodics of the same parameter and period */
1716 for (i
= 0; i
< res
->x
.p
->size
; i
++)
1717 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1721 combine_periodics(e1
, res
, emul
);
1724 /* Multiply two polynomial expressions in the same fractional part.
1726 * If the denominator of the fractional part is two, then the fractional
1727 * part can only take on two values, 0 and 1/2.
1728 * This means that { f(x)/2 }^2 = 1/2 { f(x)/2 } so that
1730 * (a0 + a1 { f(x)/2 }) * (b0 + b1 { f(x)/2 })
1731 * = a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { f(x)/2 }
1733 * Since we can always reduce higher degree polynomials this way
1734 * we assume that the inputs are degree-1 polynomials.
1735 * Note in particular that we always start out with degree-1 polynomials
1736 * and that if we obtain an argument with a denominator of two
1737 * as a result of a substitution, then the polynomial expression
1738 * is reduced in reduce_fractional.
1740 static void emul_fractionals(const evalue
*e1
, evalue
*res
)
1744 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1745 if (!value_two_p(d
.d
))
1750 value_set_si(d
.x
.n
, 1);
1751 /* { x }^2 == { x }/2 */
1752 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1753 assert(e1
->x
.p
->size
== 3);
1754 assert(res
->x
.p
->size
== 3);
1756 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1758 eadd(&res
->x
.p
->arr
[1], &tmp
);
1759 emul(&e1
->x
.p
->arr
[2], &tmp
);
1760 emul(&e1
->x
.p
->arr
[1], &res
->x
.p
->arr
[1]);
1761 emul(&e1
->x
.p
->arr
[1], &res
->x
.p
->arr
[2]);
1762 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1763 free_evalue_refs(&tmp
);
1769 /* Computes the product of two evalues "e1" and "res" and puts
1770 * the result in "res". You need to make a copy of "res"
1771 * before calling this function if you still need it afterward.
1772 * The vector type of evalues is not treated here
1774 void emul(const evalue
*e1
, evalue
*res
)
1778 assert(!(value_zero_p(e1
->d
) && e1
->x
.p
->type
== evector
));
1779 assert(!(value_zero_p(res
->d
) && res
->x
.p
->type
== evector
));
1781 if (EVALUE_IS_ZERO(*res
))
1784 if (EVALUE_IS_ONE(*e1
))
1787 if (EVALUE_IS_ZERO(*e1
)) {
1788 evalue_assign(res
, e1
);
1792 if (EVALUE_IS_NAN(*res
))
1795 if (EVALUE_IS_NAN(*e1
)) {
1796 evalue_assign(res
, e1
);
1800 cmp
= evalue_level_cmp(res
, e1
);
1803 } else if (cmp
== 0) {
1804 if (value_notzero_p(e1
->d
)) {
1805 emul_rationals(e1
, res
);
1807 switch (e1
->x
.p
->type
) {
1809 emul_partitions(e1
, res
);
1812 emul_relations(e1
, res
);
1819 emul_periodics(e1
, res
);
1822 emul_fractionals(e1
, res
);
1828 switch (res
->x
.p
->type
) {
1830 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1831 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1838 for (i
= type_offset(res
->x
.p
); i
< res
->x
.p
->size
; ++i
)
1839 emul(e1
, &res
->x
.p
->arr
[i
]);
1845 /* Frees mask content ! */
1846 void emask(evalue
*mask
, evalue
*res
) {
1853 if (EVALUE_IS_ZERO(*res
)) {
1854 free_evalue_refs(mask
);
1858 assert(value_zero_p(mask
->d
));
1859 assert(mask
->x
.p
->type
== partition
);
1860 assert(value_zero_p(res
->d
));
1861 assert(res
->x
.p
->type
== partition
);
1862 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1863 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1864 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1865 pos
= res
->x
.p
->pos
;
1867 s
= (struct section
*)
1868 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1869 sizeof(struct section
));
1873 evalue_set_si(&mone
, -1, 1);
1876 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1877 assert(mask
->x
.p
->size
>= 2);
1878 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1879 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1881 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1883 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1892 value_init(s
[n
].E
.d
);
1893 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1897 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1898 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1901 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1902 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1903 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1904 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1906 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1907 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1913 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1914 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1916 value_init(s
[n
].E
.d
);
1917 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1918 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1924 /* Just ignore; this may have been previously masked off */
1926 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1930 free_evalue_refs(&mone
);
1931 free_evalue_refs(mask
);
1932 free_evalue_refs(res
);
1935 evalue_set_si(res
, 0, 1);
1937 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1938 for (j
= 0; j
< n
; ++j
) {
1939 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1940 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1941 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1948 void evalue_copy(evalue
*dst
, const evalue
*src
)
1950 value_assign(dst
->d
, src
->d
);
1951 if (EVALUE_IS_NAN(*dst
)) {
1955 if (value_pos_p(src
->d
)) {
1956 value_init(dst
->x
.n
);
1957 value_assign(dst
->x
.n
, src
->x
.n
);
1959 dst
->x
.p
= ecopy(src
->x
.p
);
1962 evalue
*evalue_dup(const evalue
*e
)
1964 evalue
*res
= ALLOC(evalue
);
1966 evalue_copy(res
, e
);
1970 enode
*new_enode(enode_type type
,int size
,int pos
) {
1976 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1979 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1983 for(i
=0; i
<size
; i
++) {
1984 value_init(res
->arr
[i
].d
);
1985 value_set_si(res
->arr
[i
].d
,0);
1986 res
->arr
[i
].x
.p
= 0;
1991 enode
*ecopy(enode
*e
) {
1996 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1997 for(i
=0;i
<e
->size
;++i
) {
1998 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1999 if(value_zero_p(res
->arr
[i
].d
))
2000 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
2001 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
2002 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
2004 value_init(res
->arr
[i
].x
.n
);
2005 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
2011 int ecmp(const evalue
*e1
, const evalue
*e2
)
2017 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
2021 value_multiply(m
, e1
->x
.n
, e2
->d
);
2022 value_multiply(m2
, e2
->x
.n
, e1
->d
);
2024 if (value_lt(m
, m2
))
2026 else if (value_gt(m
, m2
))
2036 if (value_notzero_p(e1
->d
))
2038 if (value_notzero_p(e2
->d
))
2044 if (p1
->type
!= p2
->type
)
2045 return p1
->type
- p2
->type
;
2046 if (p1
->pos
!= p2
->pos
)
2047 return p1
->pos
- p2
->pos
;
2048 if (p1
->size
!= p2
->size
)
2049 return p1
->size
- p2
->size
;
2051 for (i
= p1
->size
-1; i
>= 0; --i
)
2052 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
2058 int eequal(const evalue
*e1
, const evalue
*e2
)
2063 if (value_ne(e1
->d
,e2
->d
))
2066 if (EVALUE_IS_DOMAIN(*e1
))
2067 return PolyhedronIncludes(EVALUE_DOMAIN(*e2
), EVALUE_DOMAIN(*e1
)) &&
2068 PolyhedronIncludes(EVALUE_DOMAIN(*e1
), EVALUE_DOMAIN(*e2
));
2070 if (EVALUE_IS_NAN(*e1
))
2073 assert(value_posz_p(e1
->d
));
2075 /* e1->d == e2->d */
2076 if (value_notzero_p(e1
->d
)) {
2077 if (value_ne(e1
->x
.n
,e2
->x
.n
))
2080 /* e1->d == e2->d != 0 AND e1->n == e2->n */
2084 /* e1->d == e2->d == 0 */
2087 if (p1
->type
!= p2
->type
) return 0;
2088 if (p1
->size
!= p2
->size
) return 0;
2089 if (p1
->pos
!= p2
->pos
) return 0;
2090 for (i
=0; i
<p1
->size
; i
++)
2091 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
2096 void free_evalue_refs(evalue
*e
) {
2101 if (EVALUE_IS_NAN(*e
)) {
2106 if (EVALUE_IS_DOMAIN(*e
)) {
2107 Domain_Free(EVALUE_DOMAIN(*e
));
2110 } else if (value_pos_p(e
->d
)) {
2112 /* 'e' stores a constant */
2114 value_clear(e
->x
.n
);
2117 assert(value_zero_p(e
->d
));
2120 if (!p
) return; /* null pointer */
2121 for (i
=0; i
<p
->size
; i
++) {
2122 free_evalue_refs(&(p
->arr
[i
]));
2126 } /* free_evalue_refs */
2128 void evalue_free(evalue
*e
)
2130 free_evalue_refs(e
);
2134 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
2135 Vector
* val
, evalue
*res
)
2137 unsigned nparam
= periods
->Size
;
2140 double d
= compute_evalue(e
, val
->p
);
2141 d
*= VALUE_TO_DOUBLE(m
);
2146 value_assign(res
->d
, m
);
2147 value_init(res
->x
.n
);
2148 value_set_double(res
->x
.n
, d
);
2149 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
2152 if (value_one_p(periods
->p
[p
]))
2153 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
2158 value_assign(tmp
, periods
->p
[p
]);
2159 value_set_si(res
->d
, 0);
2160 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
2162 value_decrement(tmp
, tmp
);
2163 value_assign(val
->p
[p
], tmp
);
2164 mod2table_r(e
, periods
, m
, p
+1, val
,
2165 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
2166 } while (value_pos_p(tmp
));
2172 static void rel2table(evalue
*e
, int zero
)
2174 if (value_pos_p(e
->d
)) {
2175 if (value_zero_p(e
->x
.n
) == zero
)
2176 value_set_si(e
->x
.n
, 1);
2178 value_set_si(e
->x
.n
, 0);
2179 value_set_si(e
->d
, 1);
2182 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
2183 rel2table(&e
->x
.p
->arr
[i
], zero
);
2187 void evalue_mod2table(evalue
*e
, int nparam
)
2192 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2195 for (i
=0; i
<p
->size
; i
++) {
2196 evalue_mod2table(&(p
->arr
[i
]), nparam
);
2198 if (p
->type
== relation
) {
2203 evalue_copy(©
, &p
->arr
[0]);
2205 rel2table(&p
->arr
[0], 1);
2206 emul(&p
->arr
[0], &p
->arr
[1]);
2208 rel2table(©
, 0);
2209 emul(©
, &p
->arr
[2]);
2210 eadd(&p
->arr
[2], &p
->arr
[1]);
2211 free_evalue_refs(&p
->arr
[2]);
2212 free_evalue_refs(©
);
2214 free_evalue_refs(&p
->arr
[0]);
2218 } else if (p
->type
== fractional
) {
2219 Vector
*periods
= Vector_Alloc(nparam
);
2220 Vector
*val
= Vector_Alloc(nparam
);
2226 value_set_si(tmp
, 1);
2227 Vector_Set(periods
->p
, 1, nparam
);
2228 Vector_Set(val
->p
, 0, nparam
);
2229 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2232 assert(p
->type
== polynomial
);
2233 assert(p
->size
== 2);
2234 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2235 value_lcm(tmp
, tmp
, p
->arr
[1].d
);
2237 value_lcm(tmp
, tmp
, ev
->d
);
2239 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2242 evalue_set_si(&res
, 0, 1);
2243 /* Compute the polynomial using Horner's rule */
2244 for (i
=p
->size
-1;i
>1;i
--) {
2245 eadd(&p
->arr
[i
], &res
);
2248 eadd(&p
->arr
[1], &res
);
2250 free_evalue_refs(e
);
2251 free_evalue_refs(&EP
);
2256 Vector_Free(periods
);
2258 } /* evalue_mod2table */
2260 /********************************************************/
2261 /* function in domain */
2262 /* check if the parameters in list_args */
2263 /* verifies the constraints of Domain P */
2264 /********************************************************/
2265 int in_domain(Polyhedron
*P
, Value
*list_args
)
2268 Value v
; /* value of the constraint of a row when
2269 parameters are instantiated*/
2271 if (P
->Dimension
== 0)
2276 for (row
= 0; row
< P
->NbConstraints
; row
++) {
2277 Inner_Product(P
->Constraint
[row
]+1, list_args
, P
->Dimension
, &v
);
2278 value_addto(v
, v
, P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2279 if (value_neg_p(v
) ||
2280 (value_zero_p(P
->Constraint
[row
][0]) && value_notzero_p(v
))) {
2287 return in
|| (P
->next
&& in_domain(P
->next
, list_args
));
2290 /****************************************************/
2291 /* function compute enode */
2292 /* compute the value of enode p with parameters */
2293 /* list "list_args */
2294 /* compute the polynomial or the periodic */
2295 /****************************************************/
2297 static double compute_enode(enode
*p
, Value
*list_args
) {
2309 if (p
->type
== polynomial
) {
2311 value_assign(param
,list_args
[p
->pos
-1]);
2313 /* Compute the polynomial using Horner's rule */
2314 for (i
=p
->size
-1;i
>0;i
--) {
2315 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2316 res
*=VALUE_TO_DOUBLE(param
);
2318 res
+=compute_evalue(&p
->arr
[0],list_args
);
2320 else if (p
->type
== fractional
) {
2321 double d
= compute_evalue(&p
->arr
[0], list_args
);
2322 d
-= floor(d
+1e-10);
2324 /* Compute the polynomial using Horner's rule */
2325 for (i
=p
->size
-1;i
>1;i
--) {
2326 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2329 res
+=compute_evalue(&p
->arr
[1],list_args
);
2331 else if (p
->type
== flooring
) {
2332 double d
= compute_evalue(&p
->arr
[0], list_args
);
2335 /* Compute the polynomial using Horner's rule */
2336 for (i
=p
->size
-1;i
>1;i
--) {
2337 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2340 res
+=compute_evalue(&p
->arr
[1],list_args
);
2342 else if (p
->type
== periodic
) {
2343 value_assign(m
,list_args
[p
->pos
-1]);
2345 /* Choose the right element of the periodic */
2346 value_set_si(param
,p
->size
);
2347 value_pmodulus(m
,m
,param
);
2348 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2350 else if (p
->type
== relation
) {
2351 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2352 res
= compute_evalue(&p
->arr
[1], list_args
);
2353 else if (p
->size
> 2)
2354 res
= compute_evalue(&p
->arr
[2], list_args
);
2356 else if (p
->type
== partition
) {
2357 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2358 Value
*vals
= list_args
;
2361 for (i
= 0; i
< dim
; ++i
) {
2362 value_init(vals
[i
]);
2364 value_assign(vals
[i
], list_args
[i
]);
2367 for (i
= 0; i
< p
->size
/2; ++i
)
2368 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2369 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2373 for (i
= 0; i
< dim
; ++i
)
2374 value_clear(vals
[i
]);
2383 } /* compute_enode */
2385 /*************************************************/
2386 /* return the value of Ehrhart Polynomial */
2387 /* It returns a double, because since it is */
2388 /* a recursive function, some intermediate value */
2389 /* might not be integral */
2390 /*************************************************/
2392 double compute_evalue(const evalue
*e
, Value
*list_args
)
2396 if (value_notzero_p(e
->d
)) {
2397 if (value_notone_p(e
->d
))
2398 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2400 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2403 res
= compute_enode(e
->x
.p
,list_args
);
2405 } /* compute_evalue */
2408 /****************************************************/
2409 /* function compute_poly : */
2410 /* Check for the good validity domain */
2411 /* return the number of point in the Polyhedron */
2412 /* in allocated memory */
2413 /* Using the Ehrhart pseudo-polynomial */
2414 /****************************************************/
2415 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2418 /* double d; int i; */
2420 tmp
= (Value
*) malloc (sizeof(Value
));
2421 assert(tmp
!= NULL
);
2423 value_set_si(*tmp
,0);
2426 return(tmp
); /* no ehrhart polynomial */
2427 if(en
->ValidityDomain
) {
2428 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2429 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2434 return(tmp
); /* no Validity Domain */
2436 if(in_domain(en
->ValidityDomain
,list_args
)) {
2438 #ifdef EVAL_EHRHART_DEBUG
2439 Print_Domain(stdout
,en
->ValidityDomain
);
2440 print_evalue(stdout
,&en
->EP
);
2443 /* d = compute_evalue(&en->EP,list_args);
2445 printf("(double)%lf = %d\n", d, i ); */
2446 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2452 value_set_si(*tmp
,0);
2453 return(tmp
); /* no compatible domain with the arguments */
2454 } /* compute_poly */
2456 static evalue
*eval_polynomial(const enode
*p
, int offset
,
2457 evalue
*base
, Value
*values
)
2462 res
= evalue_zero();
2463 for (i
= p
->size
-1; i
> offset
; --i
) {
2464 c
= evalue_eval(&p
->arr
[i
], values
);
2469 c
= evalue_eval(&p
->arr
[offset
], values
);
2476 evalue
*evalue_eval(const evalue
*e
, Value
*values
)
2483 if (value_notzero_p(e
->d
)) {
2484 res
= ALLOC(evalue
);
2486 evalue_copy(res
, e
);
2489 switch (e
->x
.p
->type
) {
2491 value_init(param
.x
.n
);
2492 value_assign(param
.x
.n
, values
[e
->x
.p
->pos
-1]);
2493 value_init(param
.d
);
2494 value_set_si(param
.d
, 1);
2496 res
= eval_polynomial(e
->x
.p
, 0, ¶m
, values
);
2497 free_evalue_refs(¶m
);
2500 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2501 mpz_fdiv_r(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2503 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2504 evalue_free(param2
);
2507 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2508 mpz_fdiv_q(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2509 value_set_si(param2
->d
, 1);
2511 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2512 evalue_free(param2
);
2515 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2516 if (value_zero_p(param2
->x
.n
))
2517 res
= evalue_eval(&e
->x
.p
->arr
[1], values
);
2518 else if (e
->x
.p
->size
> 2)
2519 res
= evalue_eval(&e
->x
.p
->arr
[2], values
);
2521 res
= evalue_zero();
2522 evalue_free(param2
);
2525 assert(e
->x
.p
->pos
== EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
);
2526 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2527 if (in_domain(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), values
)) {
2528 res
= evalue_eval(&e
->x
.p
->arr
[2*i
+1], values
);
2532 res
= evalue_zero();
2540 size_t value_size(Value v
) {
2541 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2542 * sizeof(v
[0]._mp_d
[0]);
2545 size_t domain_size(Polyhedron
*D
)
2548 size_t s
= sizeof(*D
);
2550 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2551 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2552 s
+= value_size(D
->Constraint
[i
][j
]);
2555 for (i = 0; i < D->NbRays; ++i)
2556 for (j = 0; j < D->Dimension+2; ++j)
2557 s += value_size(D->Ray[i][j]);
2560 return D
->next
? s
+domain_size(D
->next
) : s
;
2563 size_t enode_size(enode
*p
) {
2564 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2567 if (p
->type
== partition
)
2568 for (i
= 0; i
< p
->size
/2; ++i
) {
2569 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2570 s
+= evalue_size(&p
->arr
[2*i
+1]);
2573 for (i
= 0; i
< p
->size
; ++i
) {
2574 s
+= evalue_size(&p
->arr
[i
]);
2579 size_t evalue_size(evalue
*e
)
2581 size_t s
= sizeof(*e
);
2582 s
+= value_size(e
->d
);
2583 if (value_notzero_p(e
->d
))
2584 s
+= value_size(e
->x
.n
);
2586 s
+= enode_size(e
->x
.p
);
2590 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2592 evalue
*found
= NULL
;
2597 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2600 value_init(offset
.d
);
2601 value_init(offset
.x
.n
);
2602 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2603 value_lcm(offset
.d
, m
, offset
.d
);
2604 value_set_si(offset
.x
.n
, 1);
2607 evalue_copy(©
, cst
);
2610 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2612 if (eequal(base
, &e
->x
.p
->arr
[0]))
2613 found
= &e
->x
.p
->arr
[0];
2615 value_set_si(offset
.x
.n
, -2);
2618 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2620 if (eequal(base
, &e
->x
.p
->arr
[0]))
2623 free_evalue_refs(cst
);
2624 free_evalue_refs(&offset
);
2627 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2628 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2633 static evalue
*find_relation_pair(evalue
*e
)
2636 evalue
*found
= NULL
;
2638 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2641 if (e
->x
.p
->type
== fractional
) {
2646 poly_denom(&e
->x
.p
->arr
[0], &m
);
2648 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2649 cst
= &cst
->x
.p
->arr
[0])
2652 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2653 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2658 i
= e
->x
.p
->type
== relation
;
2659 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2660 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2665 void evalue_mod2relation(evalue
*e
) {
2668 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2671 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2672 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2673 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2674 value_clear(e
->x
.p
->arr
[2*i
].d
);
2675 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2677 if (2*i
< e
->x
.p
->size
) {
2678 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2679 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2684 if (e
->x
.p
->size
== 0) {
2686 evalue_set_si(e
, 0, 1);
2692 while ((d
= find_relation_pair(e
)) != NULL
) {
2696 value_init(split
.d
);
2697 value_set_si(split
.d
, 0);
2698 split
.x
.p
= new_enode(relation
, 3, 0);
2699 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2700 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2702 ev
= &split
.x
.p
->arr
[0];
2703 value_set_si(ev
->d
, 0);
2704 ev
->x
.p
= new_enode(fractional
, 3, -1);
2705 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2706 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2707 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2713 free_evalue_refs(&split
);
2717 static int evalue_comp(const void * a
, const void * b
)
2719 const evalue
*e1
= *(const evalue
**)a
;
2720 const evalue
*e2
= *(const evalue
**)b
;
2721 return ecmp(e1
, e2
);
2724 void evalue_combine(evalue
*e
)
2731 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2734 NALLOC(evs
, e
->x
.p
->size
/2);
2735 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2736 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2737 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2738 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2739 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2740 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2741 value_clear(p
->arr
[2*k
].d
);
2742 value_clear(p
->arr
[2*k
+1].d
);
2743 p
->arr
[2*k
] = *(evs
[i
]-1);
2744 p
->arr
[2*k
+1] = *(evs
[i
]);
2747 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2750 value_clear((evs
[i
]-1)->d
);
2754 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2755 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2756 free_evalue_refs(evs
[i
]);
2760 for (i
= 2*k
; i
< p
->size
; ++i
)
2761 value_clear(p
->arr
[i
].d
);
2768 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2770 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2772 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2775 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2776 Polyhedron
*D
, *N
, **P
;
2779 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2786 if (D
->NbEq
<= H
->NbEq
) {
2792 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2793 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2794 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2795 reduce_evalue(&tmp
);
2796 if (value_notzero_p(tmp
.d
) ||
2797 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2800 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2801 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2804 free_evalue_refs(&tmp
);
2810 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2812 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2814 value_clear(e
->x
.p
->arr
[2*i
].d
);
2815 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2817 if (2*i
< e
->x
.p
->size
) {
2818 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2819 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2826 H
= DomainConvex(D
, 0);
2827 E
= DomainDifference(H
, D
, 0);
2829 D
= DomainDifference(H
, E
, 0);
2832 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2836 /* Use smallest representative for coefficients in affine form in
2837 * argument of fractional.
2838 * Since any change will make the argument non-standard,
2839 * the containing evalue will have to be reduced again afterward.
2841 static void fractional_minimal_coefficients(enode
*p
)
2847 assert(p
->type
== fractional
);
2849 while (value_zero_p(pp
->d
)) {
2850 assert(pp
->x
.p
->type
== polynomial
);
2851 assert(pp
->x
.p
->size
== 2);
2852 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2853 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2854 if (value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2855 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2856 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2857 pp
= &pp
->x
.p
->arr
[0];
2863 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2868 unsigned dim
= D
->Dimension
;
2869 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2872 assert(p
->type
== fractional
|| p
->type
== flooring
);
2873 value_set_si(T
->p
[1][dim
], 1);
2874 evalue_extract_affine(&p
->arr
[0], T
->p
[0], &T
->p
[0][dim
], d
);
2875 I
= DomainImage(D
, T
, 0);
2876 H
= DomainConvex(I
, 0);
2886 static void replace_by_affine(evalue
*e
, Value offset
)
2893 value_init(inc
.x
.n
);
2894 value_set_si(inc
.d
, 1);
2895 value_oppose(inc
.x
.n
, offset
);
2896 eadd(&inc
, &p
->arr
[0]);
2897 reorder_terms_about(p
, &p
->arr
[0]); /* frees arr[0] */
2901 free_evalue_refs(&inc
);
2904 int evalue_range_reduction_in_domain(evalue
*e
, Polyhedron
*D
)
2913 if (value_notzero_p(e
->d
))
2918 if (p
->type
== relation
) {
2925 fractional_minimal_coefficients(p
->arr
[0].x
.p
);
2926 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
);
2927 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2928 equal
= value_eq(min
, max
);
2929 mpz_cdiv_q(min
, min
, d
);
2930 mpz_fdiv_q(max
, max
, d
);
2932 if (bounded
&& value_gt(min
, max
)) {
2938 evalue_set_si(e
, 0, 1);
2941 free_evalue_refs(&(p
->arr
[1]));
2942 free_evalue_refs(&(p
->arr
[0]));
2948 return r
? r
: evalue_range_reduction_in_domain(e
, D
);
2949 } else if (bounded
&& equal
) {
2952 free_evalue_refs(&(p
->arr
[2]));
2955 free_evalue_refs(&(p
->arr
[0]));
2961 return evalue_range_reduction_in_domain(e
, D
);
2962 } else if (bounded
&& value_eq(min
, max
)) {
2963 /* zero for a single value */
2965 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2966 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2967 value_multiply(min
, min
, d
);
2968 value_subtract(M
->p
[0][D
->Dimension
+1],
2969 M
->p
[0][D
->Dimension
+1], min
);
2970 E
= DomainAddConstraints(D
, M
, 0);
2976 r
= evalue_range_reduction_in_domain(&p
->arr
[1], E
);
2978 r
|= evalue_range_reduction_in_domain(&p
->arr
[2], D
);
2980 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2988 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2991 i
= p
->type
== relation
? 1 :
2992 p
->type
== fractional
? 1 : 0;
2993 for (; i
<p
->size
; i
++)
2994 r
|= evalue_range_reduction_in_domain(&p
->arr
[i
], D
);
2996 if (p
->type
!= fractional
) {
2997 if (r
&& p
->type
== polynomial
) {
3000 value_set_si(f
.d
, 0);
3001 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
3002 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
3003 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3004 reorder_terms_about(p
, &f
);
3015 fractional_minimal_coefficients(p
);
3016 I
= polynomial_projection(p
, D
, &d
, NULL
);
3017 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
3018 mpz_fdiv_q(min
, min
, d
);
3019 mpz_fdiv_q(max
, max
, d
);
3020 value_subtract(d
, max
, min
);
3022 if (bounded
&& value_eq(min
, max
)) {
3023 replace_by_affine(e
, min
);
3025 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
3026 /* replace {g}^2 by -(g-min)^2 + (2{g}+1)*(g-min) - {g}
3027 * See pages 199-200 of PhD thesis.
3035 value_set_si(rem
.d
, 0);
3036 rem
.x
.p
= new_enode(fractional
, 3, -1);
3037 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
3038 value_clear(rem
.x
.p
->arr
[1].d
);
3039 value_clear(rem
.x
.p
->arr
[2].d
);
3040 rem
.x
.p
->arr
[1] = p
->arr
[1];
3041 rem
.x
.p
->arr
[2] = p
->arr
[2];
3042 for (i
= 3; i
< p
->size
; ++i
)
3043 p
->arr
[i
-2] = p
->arr
[i
];
3047 value_init(inc
.x
.n
);
3048 value_set_si(inc
.d
, 1);
3049 value_oppose(inc
.x
.n
, min
);
3052 evalue_copy(&t
, &p
->arr
[0]);
3056 value_set_si(f
.d
, 0);
3057 f
.x
.p
= new_enode(fractional
, 3, -1);
3058 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3059 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3060 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
3062 value_init(factor
.d
);
3063 evalue_set_si(&factor
, -1, 1);
3069 value_clear(f
.x
.p
->arr
[1].x
.n
);
3070 value_clear(f
.x
.p
->arr
[2].x
.n
);
3071 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3072 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3076 evalue_reorder_terms(&rem
);
3077 evalue_reorder_terms(e
);
3083 free_evalue_refs(&inc
);
3084 free_evalue_refs(&t
);
3085 free_evalue_refs(&f
);
3086 free_evalue_refs(&factor
);
3087 free_evalue_refs(&rem
);
3089 evalue_range_reduction_in_domain(e
, D
);
3093 _reduce_evalue(&p
->arr
[0], 0, 1);
3095 evalue_reorder_terms(e
);
3105 void evalue_range_reduction(evalue
*e
)
3108 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
3111 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3112 if (evalue_range_reduction_in_domain(&e
->x
.p
->arr
[2*i
+1],
3113 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
3114 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3116 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
3117 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
3118 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3119 value_clear(e
->x
.p
->arr
[2*i
].d
);
3121 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
3122 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
3130 Enumeration
* partition2enumeration(evalue
*EP
)
3133 Enumeration
*en
, *res
= NULL
;
3135 if (EVALUE_IS_ZERO(*EP
)) {
3140 assert(value_zero_p(EP
->d
));
3141 assert(EP
->x
.p
->type
== partition
);
3142 assert(EP
->x
.p
->size
>= 2);
3144 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
3145 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
3146 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
3149 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
3150 value_clear(EP
->x
.p
->arr
[2*i
].d
);
3151 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
3159 int evalue_frac2floor_in_domain3(evalue
*e
, Polyhedron
*D
, int shift
)
3168 if (value_notzero_p(e
->d
))
3173 i
= p
->type
== relation
? 1 :
3174 p
->type
== fractional
? 1 : 0;
3175 for (; i
<p
->size
; i
++)
3176 r
|= evalue_frac2floor_in_domain3(&p
->arr
[i
], D
, shift
);
3178 if (p
->type
!= fractional
) {
3179 if (r
&& p
->type
== polynomial
) {
3182 value_set_si(f
.d
, 0);
3183 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
3184 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
3185 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3186 reorder_terms_about(p
, &f
);
3196 I
= polynomial_projection(p
, D
, &d
, NULL
);
3199 Polyhedron_Print(stderr, P_VALUE_FMT, I);
3202 assert(I
->NbEq
== 0); /* Should have been reduced */
3205 for (i
= 0; i
< I
->NbConstraints
; ++i
)
3206 if (value_pos_p(I
->Constraint
[i
][1]))
3209 if (i
< I
->NbConstraints
) {
3211 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
3212 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
3213 if (value_neg_p(min
)) {
3215 mpz_fdiv_q(min
, min
, d
);
3216 value_init(offset
.d
);
3217 value_set_si(offset
.d
, 1);
3218 value_init(offset
.x
.n
);
3219 value_oppose(offset
.x
.n
, min
);
3220 eadd(&offset
, &p
->arr
[0]);
3221 free_evalue_refs(&offset
);
3231 value_set_si(fl
.d
, 0);
3232 fl
.x
.p
= new_enode(flooring
, 3, -1);
3233 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
3234 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
3235 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
3237 eadd(&fl
, &p
->arr
[0]);
3238 reorder_terms_about(p
, &p
->arr
[0]);
3242 free_evalue_refs(&fl
);
3247 int evalue_frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
3249 return evalue_frac2floor_in_domain3(e
, D
, 1);
3252 void evalue_frac2floor2(evalue
*e
, int shift
)
3255 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
3257 if (evalue_frac2floor_in_domain3(e
, NULL
, 0))
3263 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3264 if (evalue_frac2floor_in_domain3(&e
->x
.p
->arr
[2*i
+1],
3265 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), shift
))
3266 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3269 void evalue_frac2floor(evalue
*e
)
3271 evalue_frac2floor2(e
, 1);
3274 /* Add a new variable with lower bound 1 and upper bound specified
3275 * by row. If negative is true, then the new variable has upper
3276 * bound -1 and lower bound specified by row.
3278 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
3279 Vector
*row
, int negative
)
3283 int nparam
= D
->Dimension
- nvar
;
3286 nr
= D
->NbConstraints
+ 2;
3287 nc
= D
->Dimension
+ 2 + 1;
3288 C
= Matrix_Alloc(nr
, nc
);
3289 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
3290 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
3291 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3292 D
->Dimension
+ 1 - nvar
);
3297 nc
= C
->NbColumns
+ 1;
3298 C
= Matrix_Alloc(nr
, nc
);
3299 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
3300 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
3301 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3302 oldC
->NbColumns
- 1 - nvar
);
3305 value_set_si(C
->p
[nr
-2][0], 1);
3307 value_set_si(C
->p
[nr
-2][1 + nvar
], -1);
3309 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
3310 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
3312 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
3313 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
3319 static void floor2frac_r(evalue
*e
, int nvar
)
3326 if (value_notzero_p(e
->d
))
3331 for (i
= type_offset(p
); i
< p
->size
; i
++)
3332 floor2frac_r(&p
->arr
[i
], nvar
);
3334 if (p
->type
!= flooring
)
3337 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3338 assert(pp
->x
.p
->type
== polynomial
);
3339 pp
->x
.p
->pos
-= nvar
;
3343 value_set_si(f
.d
, 0);
3344 f
.x
.p
= new_enode(fractional
, 3, -1);
3345 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3346 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3347 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3349 eadd(&f
, &p
->arr
[0]);
3350 reorder_terms_about(p
, &p
->arr
[0]);
3354 free_evalue_refs(&f
);
3357 /* Convert flooring back to fractional and shift position
3358 * of the parameters by nvar
3360 static void floor2frac(evalue
*e
, int nvar
)
3362 floor2frac_r(e
, nvar
);
3366 int evalue_floor2frac(evalue
*e
)
3371 if (value_notzero_p(e
->d
))
3374 if (e
->x
.p
->type
== partition
) {
3375 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3376 if (evalue_floor2frac(&e
->x
.p
->arr
[2*i
+1]))
3377 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3381 for (i
= type_offset(e
->x
.p
); i
< e
->x
.p
->size
; ++i
)
3382 r
|= evalue_floor2frac(&e
->x
.p
->arr
[i
]);
3384 if (e
->x
.p
->type
== flooring
) {
3390 evalue_reorder_terms(e
);
3395 static evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
,
3396 struct barvinok_options
*options
)
3399 int nparam
= D
->Dimension
- nvar
;
3403 D
= Constraints2Polyhedron(C
, options
->MaxRays
);
3407 t
= barvinok_enumerate_e_with_options(D
, 0, nparam
, options
);
3409 /* Double check that D was not unbounded. */
3410 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3418 static void domain_signs(Polyhedron
*D
, int *signs
)
3422 POL_ENSURE_VERTICES(D
);
3423 for (j
= 0; j
< D
->Dimension
; ++j
) {
3425 for (k
= 0; k
< D
->NbRays
; ++k
) {
3426 signs
[j
] = value_sign(D
->Ray
[k
][1+j
]);
3433 static evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3434 int *signs
, Matrix
*C
, struct barvinok_options
*options
)
3440 evalue
*factor
= NULL
;
3445 if (EVALUE_IS_ZERO(*e
))
3449 Polyhedron
*DD
= Disjoint_Domain(D
, 0, options
->MaxRays
);
3456 res
= esum_over_domain(e
, nvar
, Q
, signs
, C
, options
);
3459 for (Q
= DD
; Q
; Q
= DD
) {
3465 t
= esum_over_domain(e
, nvar
, Q
, signs
, C
, options
);
3478 if (value_notzero_p(e
->d
)) {
3481 t
= esum_over_domain_cst(nvar
, D
, C
, options
);
3483 if (!EVALUE_IS_ONE(*e
))
3491 signs
= ALLOCN(int, D
->Dimension
);
3492 domain_signs(D
, signs
);
3495 switch (e
->x
.p
->type
) {
3497 evalue
*pp
= &e
->x
.p
->arr
[0];
3499 if (pp
->x
.p
->pos
> nvar
) {
3500 /* remainder is independent of the summated vars */
3506 floor2frac(&f
, nvar
);
3508 t
= esum_over_domain_cst(nvar
, D
, C
, options
);
3512 free_evalue_refs(&f
);
3520 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3521 poly_denom(pp
, &row
->p
[1 + nvar
]);
3522 value_set_si(row
->p
[0], 1);
3523 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3524 pp
= &pp
->x
.p
->arr
[0]) {
3526 assert(pp
->x
.p
->type
== polynomial
);
3528 if (pos
>= 1 + nvar
)
3530 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3531 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3532 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3534 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3535 value_division(row
->p
[1 + D
->Dimension
+ 1],
3536 row
->p
[1 + D
->Dimension
+ 1],
3538 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3539 row
->p
[1 + D
->Dimension
+ 1],
3541 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3545 int pos
= e
->x
.p
->pos
;
3548 factor
= ALLOC(evalue
);
3549 value_init(factor
->d
);
3550 value_set_si(factor
->d
, 0);
3551 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3552 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3553 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3557 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3558 negative
= signs
[pos
-1] < 0;
3559 value_set_si(row
->p
[0], 1);
3561 value_set_si(row
->p
[pos
], -1);
3562 value_set_si(row
->p
[1 + nvar
], 1);
3564 value_set_si(row
->p
[pos
], 1);
3565 value_set_si(row
->p
[1 + nvar
], -1);
3573 offset
= type_offset(e
->x
.p
);
3575 res
= esum_over_domain(&e
->x
.p
->arr
[offset
], nvar
, D
, signs
, C
, options
);
3579 evalue_copy(&cum
, factor
);
3583 for (i
= 1; offset
+i
< e
->x
.p
->size
; ++i
) {
3587 C
= esum_add_constraint(nvar
, D
, C
, row
, negative
);
3593 Vector_Print(stderr, P_VALUE_FMT, row);
3595 Matrix_Print(stderr, P_VALUE_FMT, C);
3597 t
= esum_over_domain(&e
->x
.p
->arr
[offset
+i
], nvar
, D
, signs
, C
, options
);
3602 if (negative
&& (i
% 2))
3612 if (factor
&& offset
+i
+1 < e
->x
.p
->size
)
3619 free_evalue_refs(&cum
);
3620 evalue_free(factor
);
3634 static void Polyhedron_Insert(Polyhedron
***next
, Polyhedron
*Q
)
3644 static Polyhedron
*Polyhedron_Split_Into_Orthants(Polyhedron
*P
,
3649 Vector
*c
= Vector_Alloc(1 + P
->Dimension
+ 1);
3650 value_set_si(c
->p
[0], 1);
3652 if (P
->Dimension
== 0)
3653 return Polyhedron_Copy(P
);
3655 for (i
= 0; i
< P
->Dimension
; ++i
) {
3656 Polyhedron
*L
= NULL
;
3657 Polyhedron
**next
= &L
;
3660 for (I
= D
; I
; I
= I
->next
) {
3662 value_set_si(c
->p
[1+i
], 1);
3663 value_set_si(c
->p
[1+P
->Dimension
], 0);
3664 Q
= AddConstraints(c
->p
, 1, I
, MaxRays
);
3665 Polyhedron_Insert(&next
, Q
);
3666 value_set_si(c
->p
[1+i
], -1);
3667 value_set_si(c
->p
[1+P
->Dimension
], -1);
3668 Q
= AddConstraints(c
->p
, 1, I
, MaxRays
);
3669 Polyhedron_Insert(&next
, Q
);
3670 value_set_si(c
->p
[1+i
], 0);
3680 /* Make arguments of all floors non-negative */
3681 static void shift_floor_in_domain(evalue
*e
, Polyhedron
*D
)
3688 if (value_notzero_p(e
->d
))
3693 for (i
= type_offset(p
); i
< p
->size
; ++i
)
3694 shift_floor_in_domain(&p
->arr
[i
], D
);
3696 if (p
->type
!= flooring
)
3702 I
= polynomial_projection(p
, D
, &d
, NULL
);
3703 assert(I
->NbEq
== 0); /* Should have been reduced */
3705 for (i
= 0; i
< I
->NbConstraints
; ++i
)
3706 if (value_pos_p(I
->Constraint
[i
][1]))
3708 assert(i
< I
->NbConstraints
);
3709 if (i
< I
->NbConstraints
) {
3710 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
3711 mpz_fdiv_q(m
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
3712 if (value_neg_p(m
)) {
3713 /* replace [e] by [e-m]+m such that e-m >= 0 */
3718 value_set_si(f
.d
, 1);
3719 value_oppose(f
.x
.n
, m
);
3720 eadd(&f
, &p
->arr
[0]);
3723 value_set_si(f
.d
, 0);
3724 f
.x
.p
= new_enode(flooring
, 3, -1);
3725 value_clear(f
.x
.p
->arr
[0].d
);
3726 f
.x
.p
->arr
[0] = p
->arr
[0];
3727 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
3728 value_set_si(f
.x
.p
->arr
[1].d
, 1);
3729 value_init(f
.x
.p
->arr
[1].x
.n
);
3730 value_assign(f
.x
.p
->arr
[1].x
.n
, m
);
3731 reorder_terms_about(p
, &f
);
3742 evalue
*box_summate(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
3743 struct barvinok_options
*options
)
3745 evalue
*sum
= evalue_zero();
3746 Polyhedron
*D
= Polyhedron_Split_Into_Orthants(P
, options
->MaxRays
);
3747 for (P
= D
; P
; P
= P
->next
) {
3749 evalue
*fe
= evalue_dup(E
);
3750 Polyhedron
*next
= P
->next
;
3752 reduce_evalue_in_domain(fe
, P
);
3753 evalue_frac2floor2(fe
, 0);
3754 shift_floor_in_domain(fe
, P
);
3755 t
= esum_over_domain(fe
, nvar
, P
, NULL
, NULL
, options
);
3767 /* Initial silly implementation */
3768 void eor(evalue
*e1
, evalue
*res
)
3774 evalue_set_si(&mone
, -1, 1);
3776 evalue_copy(&E
, res
);
3782 free_evalue_refs(&E
);
3783 free_evalue_refs(&mone
);
3786 /* computes denominator of polynomial evalue
3787 * d should point to a value initialized to 1
3789 void evalue_denom(const evalue
*e
, Value
*d
)
3793 if (value_notzero_p(e
->d
)) {
3794 value_lcm(*d
, *d
, e
->d
);
3797 assert(e
->x
.p
->type
== polynomial
||
3798 e
->x
.p
->type
== fractional
||
3799 e
->x
.p
->type
== flooring
);
3800 offset
= type_offset(e
->x
.p
);
3801 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3802 evalue_denom(&e
->x
.p
->arr
[i
], d
);
3805 /* Divides the evalue e by the integer n */
3806 void evalue_div(evalue
*e
, Value n
)
3810 if (value_one_p(n
) || EVALUE_IS_ZERO(*e
))
3813 if (value_notzero_p(e
->d
)) {
3816 value_multiply(e
->d
, e
->d
, n
);
3817 value_gcd(gc
, e
->x
.n
, e
->d
);
3818 if (value_notone_p(gc
)) {
3819 value_division(e
->d
, e
->d
, gc
);
3820 value_division(e
->x
.n
, e
->x
.n
, gc
);
3825 if (e
->x
.p
->type
== partition
) {
3826 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3827 evalue_div(&e
->x
.p
->arr
[2*i
+1], n
);
3830 offset
= type_offset(e
->x
.p
);
3831 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3832 evalue_div(&e
->x
.p
->arr
[i
], n
);
3835 /* Multiplies the evalue e by the integer n */
3836 void evalue_mul(evalue
*e
, Value n
)
3840 if (value_one_p(n
) || EVALUE_IS_ZERO(*e
))
3843 if (value_notzero_p(e
->d
)) {
3846 value_multiply(e
->x
.n
, e
->x
.n
, n
);
3847 value_gcd(gc
, e
->x
.n
, e
->d
);
3848 if (value_notone_p(gc
)) {
3849 value_division(e
->d
, e
->d
, gc
);
3850 value_division(e
->x
.n
, e
->x
.n
, gc
);
3855 if (e
->x
.p
->type
== partition
) {
3856 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3857 evalue_mul(&e
->x
.p
->arr
[2*i
+1], n
);
3860 offset
= type_offset(e
->x
.p
);
3861 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3862 evalue_mul(&e
->x
.p
->arr
[i
], n
);
3865 /* Multiplies the evalue e by the n/d */
3866 void evalue_mul_div(evalue
*e
, Value n
, Value d
)
3870 if ((value_one_p(n
) && value_one_p(d
)) || EVALUE_IS_ZERO(*e
))
3873 if (value_notzero_p(e
->d
)) {
3876 value_multiply(e
->x
.n
, e
->x
.n
, n
);
3877 value_multiply(e
->d
, e
->d
, d
);
3878 value_gcd(gc
, e
->x
.n
, e
->d
);
3879 if (value_notone_p(gc
)) {
3880 value_division(e
->d
, e
->d
, gc
);
3881 value_division(e
->x
.n
, e
->x
.n
, gc
);
3886 if (e
->x
.p
->type
== partition
) {
3887 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3888 evalue_mul_div(&e
->x
.p
->arr
[2*i
+1], n
, d
);
3891 offset
= type_offset(e
->x
.p
);
3892 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3893 evalue_mul_div(&e
->x
.p
->arr
[i
], n
, d
);
3896 void evalue_negate(evalue
*e
)
3900 if (value_notzero_p(e
->d
)) {
3901 value_oppose(e
->x
.n
, e
->x
.n
);
3904 if (e
->x
.p
->type
== partition
) {
3905 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3906 evalue_negate(&e
->x
.p
->arr
[2*i
+1]);
3909 offset
= type_offset(e
->x
.p
);
3910 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3911 evalue_negate(&e
->x
.p
->arr
[i
]);
3914 void evalue_add_constant(evalue
*e
, const Value cst
)
3918 if (value_zero_p(e
->d
)) {
3919 if (e
->x
.p
->type
== partition
) {
3920 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3921 evalue_add_constant(&e
->x
.p
->arr
[2*i
+1], cst
);
3924 if (e
->x
.p
->type
== relation
) {
3925 for (i
= 1; i
< e
->x
.p
->size
; ++i
)
3926 evalue_add_constant(&e
->x
.p
->arr
[i
], cst
);
3930 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)];
3931 } while (value_zero_p(e
->d
));
3933 value_addmul(e
->x
.n
, cst
, e
->d
);
3936 static void evalue_frac2polynomial_r(evalue
*e
, int *signs
, int sign
, int in_frac
)
3941 int sign_odd
= sign
;
3943 if (value_notzero_p(e
->d
)) {
3944 if (in_frac
&& sign
* value_sign(e
->x
.n
) < 0) {
3945 value_set_si(e
->x
.n
, 0);
3946 value_set_si(e
->d
, 1);
3951 if (e
->x
.p
->type
== relation
) {
3952 for (i
= e
->x
.p
->size
-1; i
>= 1; --i
)
3953 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
, sign
, in_frac
);
3957 if (e
->x
.p
->type
== polynomial
)
3958 sign_odd
*= signs
[e
->x
.p
->pos
-1];
3959 offset
= type_offset(e
->x
.p
);
3960 evalue_frac2polynomial_r(&e
->x
.p
->arr
[offset
], signs
, sign
, in_frac
);
3961 in_frac
|= e
->x
.p
->type
== fractional
;
3962 for (i
= e
->x
.p
->size
-1; i
> offset
; --i
)
3963 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
,
3964 (i
- offset
) % 2 ? sign_odd
: sign
, in_frac
);
3966 if (e
->x
.p
->type
!= fractional
)
3969 /* replace { a/m } by (m-1)/m if sign != 0
3970 * and by (m-1)/(2m) if sign == 0
3974 evalue_denom(&e
->x
.p
->arr
[0], &d
);
3975 free_evalue_refs(&e
->x
.p
->arr
[0]);
3976 value_init(e
->x
.p
->arr
[0].d
);
3977 value_init(e
->x
.p
->arr
[0].x
.n
);
3979 value_addto(e
->x
.p
->arr
[0].d
, d
, d
);
3981 value_assign(e
->x
.p
->arr
[0].d
, d
);
3982 value_decrement(e
->x
.p
->arr
[0].x
.n
, d
);
3986 reorder_terms_about(p
, &p
->arr
[0]);
3992 /* Approximate the evalue in fractional representation by a polynomial.
3993 * If sign > 0, the result is an upper bound;
3994 * if sign < 0, the result is a lower bound;
3995 * if sign = 0, the result is an intermediate approximation.
3997 void evalue_frac2polynomial(evalue
*e
, int sign
, unsigned MaxRays
)
4002 if (value_notzero_p(e
->d
))
4004 assert(e
->x
.p
->type
== partition
);
4005 /* make sure all variables in the domains have a fixed sign */
4007 evalue_split_domains_into_orthants(e
, MaxRays
);
4008 if (EVALUE_IS_ZERO(*e
))
4012 assert(e
->x
.p
->size
>= 2);
4013 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
4015 signs
= ALLOCN(int, dim
);
4018 for (i
= 0; i
< dim
; ++i
)
4020 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
4022 domain_signs(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), signs
);
4023 evalue_frac2polynomial_r(&e
->x
.p
->arr
[2*i
+1], signs
, sign
, 0);
4029 /* Split the domains of e (which is assumed to be a partition)
4030 * such that each resulting domain lies entirely in one orthant.
4032 void evalue_split_domains_into_orthants(evalue
*e
, unsigned MaxRays
)
4035 assert(value_zero_p(e
->d
));
4036 assert(e
->x
.p
->type
== partition
);
4037 assert(e
->x
.p
->size
>= 2);
4038 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
4040 for (i
= 0; i
< dim
; ++i
) {
4043 C
= Matrix_Alloc(1, 1 + dim
+ 1);
4044 value_set_si(C
->p
[0][0], 1);
4045 value_init(split
.d
);
4046 value_set_si(split
.d
, 0);
4047 split
.x
.p
= new_enode(partition
, 4, dim
);
4048 value_set_si(C
->p
[0][1+i
], 1);
4049 C2
= Matrix_Copy(C
);
4050 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[0], Constraints2Polyhedron(C2
, MaxRays
));
4052 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
4053 value_set_si(C
->p
[0][1+i
], -1);
4054 value_set_si(C
->p
[0][1+dim
], -1);
4055 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[2], Constraints2Polyhedron(C
, MaxRays
));
4056 evalue_set_si(&split
.x
.p
->arr
[3], 1, 1);
4058 free_evalue_refs(&split
);
4063 void evalue_extract_affine(const evalue
*e
, Value
*coeff
, Value
*cst
, Value
*d
)
4065 value_set_si(*d
, 1);
4067 for ( ; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[0]) {
4069 assert(e
->x
.p
->type
== polynomial
);
4070 assert(e
->x
.p
->size
== 2);
4071 c
= &e
->x
.p
->arr
[1];
4072 value_multiply(coeff
[e
->x
.p
->pos
-1], *d
, c
->x
.n
);
4073 value_division(coeff
[e
->x
.p
->pos
-1], coeff
[e
->x
.p
->pos
-1], c
->d
);
4075 value_multiply(*cst
, *d
, e
->x
.n
);
4076 value_division(*cst
, *cst
, e
->d
);
4079 /* returns an evalue that corresponds to
4083 static evalue
*term(int param
, Value c
, Value den
)
4085 evalue
*EP
= ALLOC(evalue
);
4087 value_set_si(EP
->d
,0);
4088 EP
->x
.p
= new_enode(polynomial
, 2, param
+ 1);
4089 evalue_set_si(&EP
->x
.p
->arr
[0], 0, 1);
4090 evalue_set_reduce(&EP
->x
.p
->arr
[1], c
, den
);
4094 evalue
*affine2evalue(Value
*coeff
, Value denom
, int nvar
)
4097 evalue
*E
= ALLOC(evalue
);
4099 evalue_set_reduce(E
, coeff
[nvar
], denom
);
4100 for (i
= 0; i
< nvar
; ++i
) {
4102 if (value_zero_p(coeff
[i
]))
4104 t
= term(i
, coeff
[i
], denom
);
4111 void evalue_substitute(evalue
*e
, evalue
**subs
)
4117 if (value_notzero_p(e
->d
))
4121 assert(p
->type
!= partition
);
4123 for (i
= 0; i
< p
->size
; ++i
)
4124 evalue_substitute(&p
->arr
[i
], subs
);
4126 if (p
->type
== relation
) {
4127 /* For relation a ? b : c, compute (a' ? 1) * b' + (a' ? 0 : 1) * c' */
4131 value_set_si(v
->d
, 0);
4132 v
->x
.p
= new_enode(relation
, 3, 0);
4133 evalue_copy(&v
->x
.p
->arr
[0], &p
->arr
[0]);
4134 evalue_set_si(&v
->x
.p
->arr
[1], 0, 1);
4135 evalue_set_si(&v
->x
.p
->arr
[2], 1, 1);
4136 emul(v
, &p
->arr
[2]);
4141 value_set_si(v
->d
, 0);
4142 v
->x
.p
= new_enode(relation
, 2, 0);
4143 value_clear(v
->x
.p
->arr
[0].d
);
4144 v
->x
.p
->arr
[0] = p
->arr
[0];
4145 evalue_set_si(&v
->x
.p
->arr
[1], 1, 1);
4146 emul(v
, &p
->arr
[1]);
4149 eadd(&p
->arr
[2], &p
->arr
[1]);
4150 free_evalue_refs(&p
->arr
[2]);
4158 if (p
->type
== polynomial
)
4163 value_set_si(v
->d
, 0);
4164 v
->x
.p
= new_enode(p
->type
, 3, -1);
4165 value_clear(v
->x
.p
->arr
[0].d
);
4166 v
->x
.p
->arr
[0] = p
->arr
[0];
4167 evalue_set_si(&v
->x
.p
->arr
[1], 0, 1);
4168 evalue_set_si(&v
->x
.p
->arr
[2], 1, 1);
4171 offset
= type_offset(p
);
4173 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
4174 emul(v
, &p
->arr
[i
]);
4175 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
4176 free_evalue_refs(&(p
->arr
[i
]));
4179 if (p
->type
!= polynomial
)
4183 *e
= p
->arr
[offset
];
4187 /* evalue e is given in terms of "new" parameter; CP maps the new
4188 * parameters back to the old parameters.
4189 * Transforms e such that it refers back to the old parameters and
4190 * adds appropriate constraints to the domain.
4191 * In particular, if CP maps the new parameters onto an affine
4192 * subspace of the old parameters, then the corresponding equalities
4193 * are added to the domain.
4194 * Also, if any of the new parameters was a rational combination
4195 * of the old parameters $p' = (<a, p> + c)/m$, then modulo
4196 * constraints ${<a, p> + c)/m} = 0$ are added to ensure
4197 * the new evalue remains non-zero only for integer parameters
4198 * of the new parameters (which have been removed by the substitution).
4200 void evalue_backsubstitute(evalue
*e
, Matrix
*CP
, unsigned MaxRays
)
4207 unsigned nparam
= CP
->NbColumns
-1;
4211 if (EVALUE_IS_ZERO(*e
))
4214 assert(value_zero_p(e
->d
));
4216 assert(p
->type
== partition
);
4218 inv
= left_inverse(CP
, &eq
);
4219 subs
= ALLOCN(evalue
*, nparam
);
4220 for (i
= 0; i
< nparam
; ++i
)
4221 subs
[i
] = affine2evalue(inv
->p
[i
], inv
->p
[nparam
][inv
->NbColumns
-1],
4224 CEq
= Constraints2Polyhedron(eq
, MaxRays
);
4225 addeliminatedparams_partition(p
, inv
, CEq
, inv
->NbColumns
-1, MaxRays
);
4226 Polyhedron_Free(CEq
);
4228 for (i
= 0; i
< p
->size
/2; ++i
)
4229 evalue_substitute(&p
->arr
[2*i
+1], subs
);
4231 for (i
= 0; i
< nparam
; ++i
)
4232 evalue_free(subs
[i
]);
4236 for (i
= 0; i
< inv
->NbRows
-1; ++i
) {
4237 Vector_Gcd(inv
->p
[i
], inv
->NbColumns
, &gcd
);
4238 value_gcd(gcd
, gcd
, inv
->p
[inv
->NbRows
-1][inv
->NbColumns
-1]);
4239 if (value_eq(gcd
, inv
->p
[inv
->NbRows
-1][inv
->NbColumns
-1]))
4241 Vector_AntiScale(inv
->p
[i
], inv
->p
[i
], gcd
, inv
->NbColumns
);
4242 value_divexact(gcd
, inv
->p
[inv
->NbRows
-1][inv
->NbColumns
-1], gcd
);
4244 for (j
= 0; j
< p
->size
/2; ++j
) {
4245 evalue
*arg
= affine2evalue(inv
->p
[i
], gcd
, inv
->NbColumns
-1);
4250 value_set_si(rel
.d
, 0);
4251 rel
.x
.p
= new_enode(relation
, 2, 0);
4252 value_clear(rel
.x
.p
->arr
[1].d
);
4253 rel
.x
.p
->arr
[1] = p
->arr
[2*j
+1];
4254 ev
= &rel
.x
.p
->arr
[0];
4255 value_set_si(ev
->d
, 0);
4256 ev
->x
.p
= new_enode(fractional
, 3, -1);
4257 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
4258 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
4259 value_clear(ev
->x
.p
->arr
[0].d
);
4260 ev
->x
.p
->arr
[0] = *arg
;
4263 p
->arr
[2*j
+1] = rel
;
4274 * \sum_{i=0}^n c_i/d X^i
4276 * where d is the last element in the vector c.
4278 evalue
*evalue_polynomial(Vector
*c
, const evalue
* X
)
4280 unsigned dim
= c
->Size
-2;
4282 evalue
*EP
= ALLOC(evalue
);
4287 if (EVALUE_IS_ZERO(*X
) || dim
== 0) {
4288 evalue_set(EP
, c
->p
[0], c
->p
[dim
+1]);
4289 reduce_constant(EP
);
4293 evalue_set(EP
, c
->p
[dim
], c
->p
[dim
+1]);
4296 evalue_set(&EC
, c
->p
[dim
], c
->p
[dim
+1]);
4298 for (i
= dim
-1; i
>= 0; --i
) {
4300 value_assign(EC
.x
.n
, c
->p
[i
]);
4303 free_evalue_refs(&EC
);
4307 /* Create an evalue from an array of pairs of domains and evalues. */
4308 evalue
*evalue_from_section_array(struct evalue_section
*s
, int n
)
4313 res
= ALLOC(evalue
);
4317 evalue_set_si(res
, 0, 1);
4319 value_set_si(res
->d
, 0);
4320 res
->x
.p
= new_enode(partition
, 2*n
, s
[0].D
->Dimension
);
4321 for (i
= 0; i
< n
; ++i
) {
4322 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
], s
[i
].D
);
4323 value_clear(res
->x
.p
->arr
[2*i
+1].d
);
4324 res
->x
.p
->arr
[2*i
+1] = *s
[i
].E
;
4331 /* shift variables (>= first, 0-based) in polynomial n up (may be negative) */
4332 void evalue_shift_variables(evalue
*e
, int first
, int n
)
4335 if (value_notzero_p(e
->d
))
4337 assert(e
->x
.p
->type
== polynomial
||
4338 e
->x
.p
->type
== flooring
||
4339 e
->x
.p
->type
== fractional
);
4340 if (e
->x
.p
->type
== polynomial
&& e
->x
.p
->pos
>= first
+1) {
4341 assert(e
->x
.p
->pos
+ n
>= 1);
4344 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
4345 evalue_shift_variables(&e
->x
.p
->arr
[i
], first
, n
);
4348 static const evalue
*outer_floor(evalue
*e
, const evalue
*outer
)
4352 if (value_notzero_p(e
->d
))
4354 switch (e
->x
.p
->type
) {
4356 if (!outer
|| evalue_level_cmp(outer
, &e
->x
.p
->arr
[0]) > 0)
4357 return &e
->x
.p
->arr
[0];
4363 for (i
= type_offset(e
->x
.p
); i
< e
->x
.p
->size
; ++i
)
4364 outer
= outer_floor(&e
->x
.p
->arr
[i
], outer
);
4367 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
4368 outer
= outer_floor(&e
->x
.p
->arr
[2*i
+1], outer
);
4375 /* Find and return outermost floor argument or NULL if e has no floors */
4376 evalue
*evalue_outer_floor(evalue
*e
)
4378 const evalue
*floor
= outer_floor(e
, NULL
);
4379 return floor
? evalue_dup(floor
): NULL
;
4382 static void evalue_set_to_zero(evalue
*e
)
4384 if (EVALUE_IS_ZERO(*e
))
4386 if (value_zero_p(e
->d
)) {
4387 free_evalue_refs(e
);
4391 value_set_si(e
->d
, 1);
4392 value_set_si(e
->x
.n
, 0);
4395 /* Replace (outer) floor with argument "floor" by variable "var" (0-based)
4396 * and drop terms not containing the floor.
4397 * Returns true if e contains the floor.
4399 int evalue_replace_floor(evalue
*e
, const evalue
*floor
, int var
)
4405 if (value_notzero_p(e
->d
))
4407 switch (e
->x
.p
->type
) {
4409 if (!eequal(floor
, &e
->x
.p
->arr
[0]))
4411 e
->x
.p
->type
= polynomial
;
4412 e
->x
.p
->pos
= 1 + var
;
4414 free_evalue_refs(&e
->x
.p
->arr
[0]);
4415 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
4416 e
->x
.p
->arr
[i
] = e
->x
.p
->arr
[i
+1];
4417 evalue_set_to_zero(&e
->x
.p
->arr
[0]);
4422 for (i
= type_offset(e
->x
.p
); i
< e
->x
.p
->size
; ++i
) {
4423 int c
= evalue_replace_floor(&e
->x
.p
->arr
[i
], floor
, var
);
4426 evalue_set_to_zero(&e
->x
.p
->arr
[i
]);
4427 if (c
&& !reorder
&& evalue_level_cmp(&e
->x
.p
->arr
[i
], e
) < 0)
4430 evalue_reduce_size(e
);
4432 evalue_reorder_terms(e
);
4440 /* Replace (outer) floor with argument "floor" by variable zero */
4441 void evalue_drop_floor(evalue
*e
, const evalue
*floor
)
4446 if (value_notzero_p(e
->d
))
4448 switch (e
->x
.p
->type
) {
4450 if (!eequal(floor
, &e
->x
.p
->arr
[0]))
4453 free_evalue_refs(&p
->arr
[0]);
4454 for (i
= 2; i
< p
->size
; ++i
)
4455 free_evalue_refs(&p
->arr
[i
]);
4463 for (i
= type_offset(e
->x
.p
); i
< e
->x
.p
->size
; ++i
)
4464 evalue_drop_floor(&e
->x
.p
->arr
[i
], floor
);
4465 evalue_reduce_size(e
);
4475 PROCEDURES TO COMPUTE ENUMERATION. recursive procedure, recurse for
4478 @param pos index position of current loop index (1..hdim-1)
4479 @param P loop domain
4480 @param context context values for fixed indices
4481 @param exist number of existential variables
4482 @return the number of integer points in this
4486 void count_points_e (int pos
, Polyhedron
*P
, int exist
, int nparam
,
4487 Value
*context
, Value
*res
)
4492 value_set_si(*res
, 0);
4497 count_points(pos
, P
, context
, res
);
4501 value_init(LB
); value_init(UB
); value_init(k
);
4505 if (lower_upper_bounds(pos
,P
,context
,&LB
,&UB
) !=0) {
4506 /* Problem if UB or LB is INFINITY */
4507 value_clear(LB
); value_clear(UB
); value_clear(k
);
4508 if (pos
> P
->Dimension
- nparam
- exist
)
4509 value_set_si(*res
, 1);
4511 value_set_si(*res
, -1);
4518 for (value_assign(k
,LB
); value_le(k
,UB
); value_increment(k
,k
)) {
4519 fprintf(stderr
, "(");
4520 for (i
=1; i
<pos
; i
++) {
4521 value_print(stderr
,P_VALUE_FMT
,context
[i
]);
4522 fprintf(stderr
,",");
4524 value_print(stderr
,P_VALUE_FMT
,k
);
4525 fprintf(stderr
,")\n");
4530 value_set_si(context
[pos
],0);
4531 if (value_lt(UB
,LB
)) {
4532 value_clear(LB
); value_clear(UB
); value_clear(k
);
4533 value_set_si(*res
, 0);
4538 value_set_si(*res
, 1);
4540 value_subtract(k
,UB
,LB
);
4541 value_add_int(k
,k
,1);
4542 value_assign(*res
, k
);
4544 value_clear(LB
); value_clear(UB
); value_clear(k
);
4548 /*-----------------------------------------------------------------*/
4549 /* Optimization idea */
4550 /* If inner loops are not a function of k (the current index) */
4551 /* i.e. if P->Constraint[i][pos]==0 for all P following this and */
4553 /* Then CNT = (UB-LB+1)*count_points(pos+1, P->next, context) */
4554 /* (skip the for loop) */
4555 /*-----------------------------------------------------------------*/
4558 value_set_si(*res
, 0);
4559 for (value_assign(k
,LB
);value_le(k
,UB
);value_increment(k
,k
)) {
4560 /* Insert k in context */
4561 value_assign(context
[pos
],k
);
4562 count_points_e(pos
+1, P
->next
, exist
, nparam
, context
, &c
);
4563 if(value_notmone_p(c
))
4564 value_addto(*res
, *res
, c
);
4566 value_set_si(*res
, -1);
4569 if (pos
> P
->Dimension
- nparam
- exist
&&
4576 fprintf(stderr
,"%d\n",CNT
);
4580 value_set_si(context
[pos
],0);
4581 value_clear(LB
); value_clear(UB
); value_clear(k
);
4583 } /* count_points_e */