1 /***********************************************************************/
2 /* copyright 1997, Doran Wilde */
3 /* copyright 1997-2000, Vincent Loechner */
4 /* copyright 2003-2006, Sven Verdoolaege */
5 /* Permission is granted to copy, use, and distribute */
6 /* for any commercial or noncommercial purpose under the terms */
7 /* of the GNU General Public license, version 2, June 1991 */
8 /* (see file : LICENSE). */
9 /***********************************************************************/
15 #include <barvinok/evalue.h>
16 #include <barvinok/barvinok.h>
17 #include <barvinok/util.h>
19 #ifndef value_pmodulus
20 #define value_pmodulus(ref,val1,val2) (mpz_fdiv_r((ref),(val1),(val2)))
23 #define ALLOC(type) (type*)malloc(sizeof(type))
24 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
27 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
29 #define NALLOC(p,n) p = (void *)malloc((n) * sizeof(*p))
32 void evalue_set_si(evalue
*ev
, int n
, int d
) {
33 value_set_si(ev
->d
, d
);
35 value_set_si(ev
->x
.n
, n
);
38 void evalue_set(evalue
*ev
, Value n
, Value d
) {
39 value_assign(ev
->d
, d
);
41 value_assign(ev
->x
.n
, n
);
46 evalue
*EP
= ALLOC(evalue
);
48 evalue_set_si(EP
, 0, 1);
52 void aep_evalue(evalue
*e
, int *ref
) {
57 if (value_notzero_p(e
->d
))
58 return; /* a rational number, its already reduced */
60 return; /* hum... an overflow probably occured */
62 /* First check the components of p */
63 for (i
=0;i
<p
->size
;i
++)
64 aep_evalue(&p
->arr
[i
],ref
);
71 p
->pos
= ref
[p
->pos
-1]+1;
77 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
83 if (value_notzero_p(e
->d
))
84 return; /* a rational number, its already reduced */
86 return; /* hum... an overflow probably occured */
89 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
90 for(i
=0;i
<CT
->NbRows
-1;i
++)
91 for(j
=0;j
<CT
->NbColumns
;j
++)
92 if(value_notzero_p(CT
->p
[i
][j
])) {
97 /* Transform the references in e, using ref */
101 } /* addeliminatedparams_evalue */
103 static void addeliminatedparams_partition(enode
*p
, Matrix
*CT
, Polyhedron
*CEq
,
104 unsigned nparam
, unsigned MaxRays
)
107 assert(p
->type
== partition
);
110 for (i
= 0; i
< p
->size
/2; i
++) {
111 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
112 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
116 T
= DomainIntersection(D
, CEq
, MaxRays
);
119 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
123 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
124 unsigned MaxRays
, unsigned nparam
)
129 if (CT
->NbRows
== CT
->NbColumns
)
132 if (EVALUE_IS_ZERO(*e
))
135 if (value_notzero_p(e
->d
)) {
138 value_set_si(res
.d
, 0);
139 res
.x
.p
= new_enode(partition
, 2, nparam
);
140 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
141 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
142 value_clear(res
.x
.p
->arr
[1].d
);
143 res
.x
.p
->arr
[1] = *e
;
151 addeliminatedparams_partition(p
, CT
, CEq
, nparam
, MaxRays
);
152 for (i
= 0; i
< p
->size
/2; i
++)
153 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
156 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
164 assert(value_notzero_p(e1
->d
));
165 assert(value_notzero_p(e2
->d
));
166 value_multiply(m
, e1
->x
.n
, e2
->d
);
167 value_multiply(m2
, e2
->x
.n
, e1
->d
);
170 else if (value_gt(m
, m2
))
180 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
182 if (value_notzero_p(e1
->d
)) {
184 if (value_zero_p(e2
->d
))
186 r
= mod_rational_smaller(e1
, e2
);
187 return r
== -1 ? 0 : r
;
189 if (value_notzero_p(e2
->d
))
191 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
193 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
196 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
198 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
203 static int mod_term_smaller(const evalue
*e1
, const evalue
*e2
)
205 assert(value_zero_p(e1
->d
));
206 assert(value_zero_p(e2
->d
));
207 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
208 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
209 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
212 static void check_order(const evalue
*e
)
217 if (value_notzero_p(e
->d
))
220 switch (e
->x
.p
->type
) {
222 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
223 check_order(&e
->x
.p
->arr
[2*i
+1]);
226 for (i
= 1; i
< e
->x
.p
->size
; ++i
) {
228 if (value_notzero_p(a
->d
))
230 switch (a
->x
.p
->type
) {
232 assert(mod_term_smaller(&e
->x
.p
->arr
[0], &a
->x
.p
->arr
[0]));
241 for (i
= 0; i
< e
->x
.p
->size
; ++i
) {
243 if (value_notzero_p(a
->d
))
245 switch (a
->x
.p
->type
) {
247 assert(e
->x
.p
->pos
< a
->x
.p
->pos
);
258 for (i
= 1; i
< e
->x
.p
->size
; ++i
) {
260 if (value_notzero_p(a
->d
))
262 switch (a
->x
.p
->type
) {
273 /* Negative pos means inequality */
274 /* s is negative of substitution if m is not zero */
283 struct fixed_param
*fixed
;
288 static int relations_depth(evalue
*e
)
293 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
294 e
= &e
->x
.p
->arr
[1], ++d
);
298 static void poly_denom_not_constant(evalue
**pp
, Value
*d
)
303 while (value_zero_p(p
->d
)) {
304 assert(p
->x
.p
->type
== polynomial
);
305 assert(p
->x
.p
->size
== 2);
306 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
307 value_lcm(*d
, *d
, p
->x
.p
->arr
[1].d
);
313 static void poly_denom(evalue
*p
, Value
*d
)
315 poly_denom_not_constant(&p
, d
);
316 value_lcm(*d
, *d
, p
->d
);
319 static void realloc_substitution(struct subst
*s
, int d
)
321 struct fixed_param
*n
;
324 for (i
= 0; i
< s
->n
; ++i
)
331 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
337 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
340 /* May have been reduced already */
341 if (value_notzero_p(m
->d
))
344 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
345 assert(m
->x
.p
->size
== 3);
347 /* fractional was inverted during reduction
348 * invert it back and move constant in
350 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
351 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
352 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
353 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
354 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
355 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
356 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
357 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
358 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
359 value_set_si(m
->x
.p
->arr
[1].d
, 1);
362 /* Oops. Nested identical relations. */
363 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
366 if (s
->n
>= s
->max
) {
367 int d
= relations_depth(r
);
368 realloc_substitution(s
, d
);
372 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
373 assert(p
->x
.p
->size
== 2);
376 assert(value_pos_p(f
->x
.n
));
378 value_init(s
->fixed
[s
->n
].m
);
379 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
380 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
381 value_init(s
->fixed
[s
->n
].d
);
382 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
383 value_init(s
->fixed
[s
->n
].s
.d
);
384 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
390 static int type_offset(enode
*p
)
392 return p
->type
== fractional
? 1 :
393 p
->type
== flooring
? 1 : 0;
396 static void reorder_terms_about(enode
*p
, evalue
*v
)
399 int offset
= type_offset(p
);
401 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
403 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
404 free_evalue_refs(&(p
->arr
[i
]));
410 static void reorder_terms(evalue
*e
)
415 assert(value_zero_p(e
->d
));
417 assert(p
->type
== fractional
); /* for now */
420 value_set_si(f
.d
, 0);
421 f
.x
.p
= new_enode(fractional
, 3, -1);
422 value_clear(f
.x
.p
->arr
[0].d
);
423 f
.x
.p
->arr
[0] = p
->arr
[0];
424 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
425 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
426 reorder_terms_about(p
, &f
);
432 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
438 if (value_notzero_p(e
->d
)) {
440 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
441 return; /* a rational number, its already reduced */
445 return; /* hum... an overflow probably occured */
447 /* First reduce the components of p */
448 add
= p
->type
== relation
;
449 for (i
=0; i
<p
->size
; i
++) {
451 add
= add_modulo_substitution(s
, e
);
453 if (i
== 0 && p
->type
==fractional
)
454 _reduce_evalue(&p
->arr
[i
], s
, 1);
456 _reduce_evalue(&p
->arr
[i
], s
, fract
);
458 if (add
&& i
== p
->size
-1) {
460 value_clear(s
->fixed
[s
->n
].m
);
461 value_clear(s
->fixed
[s
->n
].d
);
462 free_evalue_refs(&s
->fixed
[s
->n
].s
);
463 } else if (add
&& i
== 1)
464 s
->fixed
[s
->n
-1].pos
*= -1;
467 if (p
->type
==periodic
) {
469 /* Try to reduce the period */
470 for (i
=1; i
<=(p
->size
)/2; i
++) {
471 if ((p
->size
% i
)==0) {
473 /* Can we reduce the size to i ? */
475 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
476 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
479 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
483 you_lose
: /* OK, lets not do it */
488 /* Try to reduce its strength */
491 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
495 else if (p
->type
==polynomial
) {
496 for (k
= 0; s
&& k
< s
->n
; ++k
) {
497 if (s
->fixed
[k
].pos
== p
->pos
) {
498 int divide
= value_notone_p(s
->fixed
[k
].d
);
501 if (value_notzero_p(s
->fixed
[k
].m
)) {
504 assert(p
->size
== 2);
505 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
507 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
514 value_assign(d
.d
, s
->fixed
[k
].d
);
516 if (value_notzero_p(s
->fixed
[k
].m
))
517 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
519 value_set_si(d
.x
.n
, 1);
522 for (i
=p
->size
-1;i
>=1;i
--) {
523 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
525 emul(&d
, &p
->arr
[i
]);
526 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
527 free_evalue_refs(&(p
->arr
[i
]));
530 _reduce_evalue(&p
->arr
[0], s
, fract
);
533 free_evalue_refs(&d
);
539 /* Try to reduce the degree */
540 for (i
=p
->size
-1;i
>=1;i
--) {
541 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
543 /* Zero coefficient */
544 free_evalue_refs(&(p
->arr
[i
]));
549 /* Try to reduce its strength */
552 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
556 else if (p
->type
==fractional
) {
560 if (value_notzero_p(p
->arr
[0].d
)) {
562 value_assign(v
.d
, p
->arr
[0].d
);
564 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
569 evalue
*pp
= &p
->arr
[0];
570 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
571 assert(pp
->x
.p
->size
== 2);
573 /* search for exact duplicate among the modulo inequalities */
575 f
= &pp
->x
.p
->arr
[1];
576 for (k
= 0; s
&& k
< s
->n
; ++k
) {
577 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
578 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
579 value_eq(s
->fixed
[k
].m
, f
->d
) &&
580 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
587 /* replace { E/m } by { (E-1)/m } + 1/m */
592 evalue_set_si(&extra
, 1, 1);
593 value_assign(extra
.d
, g
);
594 eadd(&extra
, &v
.x
.p
->arr
[1]);
595 free_evalue_refs(&extra
);
597 /* We've been going in circles; stop now */
598 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
599 free_evalue_refs(&v
);
601 evalue_set_si(&v
, 0, 1);
606 value_set_si(v
.d
, 0);
607 v
.x
.p
= new_enode(fractional
, 3, -1);
608 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
609 value_assign(v
.x
.p
->arr
[1].d
, g
);
610 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
611 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
614 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
617 value_division(f
->d
, g
, f
->d
);
618 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
619 value_assign(f
->d
, g
);
620 value_decrement(f
->x
.n
, f
->x
.n
);
621 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
623 value_gcd(g
, f
->d
, f
->x
.n
);
624 value_division(f
->d
, f
->d
, g
);
625 value_division(f
->x
.n
, f
->x
.n
, g
);
634 /* reduction may have made this fractional arg smaller */
635 i
= reorder
? p
->size
: 1;
636 for ( ; i
< p
->size
; ++i
)
637 if (value_zero_p(p
->arr
[i
].d
) &&
638 p
->arr
[i
].x
.p
->type
== fractional
&&
639 !mod_term_smaller(e
, &p
->arr
[i
]))
643 value_set_si(v
.d
, 0);
644 v
.x
.p
= new_enode(fractional
, 3, -1);
645 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
646 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
647 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
655 evalue
*pp
= &p
->arr
[0];
658 poly_denom_not_constant(&pp
, &m
);
659 mpz_fdiv_r(r
, m
, pp
->d
);
660 if (value_notzero_p(r
)) {
662 value_set_si(v
.d
, 0);
663 v
.x
.p
= new_enode(fractional
, 3, -1);
665 value_multiply(r
, m
, pp
->x
.n
);
666 value_multiply(v
.x
.p
->arr
[1].d
, m
, pp
->d
);
667 value_init(v
.x
.p
->arr
[1].x
.n
);
668 mpz_fdiv_r(v
.x
.p
->arr
[1].x
.n
, r
, pp
->d
);
669 mpz_fdiv_q(r
, r
, pp
->d
);
671 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
672 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
674 while (value_zero_p(pp
->d
))
675 pp
= &pp
->x
.p
->arr
[0];
677 value_assign(pp
->d
, m
);
678 value_assign(pp
->x
.n
, r
);
680 value_gcd(r
, pp
->d
, pp
->x
.n
);
681 value_division(pp
->d
, pp
->d
, r
);
682 value_division(pp
->x
.n
, pp
->x
.n
, r
);
695 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
696 pp
= &pp
->x
.p
->arr
[0]) {
697 f
= &pp
->x
.p
->arr
[1];
698 assert(value_pos_p(f
->d
));
699 mpz_mul_ui(twice
, f
->x
.n
, 2);
700 if (value_lt(twice
, f
->d
))
702 if (value_eq(twice
, f
->d
))
710 value_set_si(v
.d
, 0);
711 v
.x
.p
= new_enode(fractional
, 3, -1);
712 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
713 poly_denom(&p
->arr
[0], &twice
);
714 value_assign(v
.x
.p
->arr
[1].d
, twice
);
715 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
716 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
717 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
719 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
720 pp
= &pp
->x
.p
->arr
[0]) {
721 f
= &pp
->x
.p
->arr
[1];
722 value_oppose(f
->x
.n
, f
->x
.n
);
723 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
725 value_division(pp
->d
, twice
, pp
->d
);
726 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
727 value_assign(pp
->d
, twice
);
728 value_oppose(pp
->x
.n
, pp
->x
.n
);
729 value_decrement(pp
->x
.n
, pp
->x
.n
);
730 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
732 /* Maybe we should do this during reduction of
735 value_gcd(twice
, pp
->d
, pp
->x
.n
);
736 value_division(pp
->d
, pp
->d
, twice
);
737 value_division(pp
->x
.n
, pp
->x
.n
, twice
);
747 reorder_terms_about(p
, &v
);
748 _reduce_evalue(&p
->arr
[1], s
, fract
);
751 /* Try to reduce the degree */
752 for (i
=p
->size
-1;i
>=2;i
--) {
753 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
755 /* Zero coefficient */
756 free_evalue_refs(&(p
->arr
[i
]));
761 /* Try to reduce its strength */
764 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
765 free_evalue_refs(&(p
->arr
[0]));
769 else if (p
->type
== flooring
) {
770 /* Try to reduce the degree */
771 for (i
=p
->size
-1;i
>=2;i
--) {
772 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
774 /* Zero coefficient */
775 free_evalue_refs(&(p
->arr
[i
]));
780 /* Try to reduce its strength */
783 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
784 free_evalue_refs(&(p
->arr
[0]));
788 else if (p
->type
== relation
) {
789 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
790 free_evalue_refs(&(p
->arr
[2]));
791 free_evalue_refs(&(p
->arr
[0]));
798 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
799 free_evalue_refs(&(p
->arr
[2]));
802 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
803 free_evalue_refs(&(p
->arr
[1]));
804 free_evalue_refs(&(p
->arr
[0]));
805 evalue_set_si(e
, 0, 1);
812 /* Relation was reduced by means of an identical
813 * inequality => remove
815 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
818 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
819 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
821 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
823 free_evalue_refs(&(p
->arr
[2]));
827 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
829 evalue_set_si(e
, 0, 1);
830 free_evalue_refs(&(p
->arr
[1]));
832 free_evalue_refs(&(p
->arr
[0]));
838 } /* reduce_evalue */
840 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
845 for (k
= 0; k
< dim
; ++k
)
846 if (value_notzero_p(row
[k
+1]))
849 Vector_Normalize_Positive(row
+1, dim
+1, k
);
850 assert(s
->n
< s
->max
);
851 value_init(s
->fixed
[s
->n
].d
);
852 value_init(s
->fixed
[s
->n
].m
);
853 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
854 s
->fixed
[s
->n
].pos
= k
+1;
855 value_set_si(s
->fixed
[s
->n
].m
, 0);
856 r
= &s
->fixed
[s
->n
].s
;
858 for (l
= k
+1; l
< dim
; ++l
)
859 if (value_notzero_p(row
[l
+1])) {
860 value_set_si(r
->d
, 0);
861 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
862 value_init(r
->x
.p
->arr
[1].x
.n
);
863 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
864 value_set_si(r
->x
.p
->arr
[1].d
, 1);
868 value_oppose(r
->x
.n
, row
[dim
+1]);
869 value_set_si(r
->d
, 1);
873 static void _reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
, struct subst
*s
)
876 Polyhedron
*orig
= D
;
881 D
= DomainConvex(D
, 0);
882 if (!D
->next
&& D
->NbEq
) {
886 realloc_substitution(s
, dim
);
888 int d
= relations_depth(e
);
890 NALLOC(s
->fixed
, s
->max
);
893 for (j
= 0; j
< D
->NbEq
; ++j
)
894 add_substitution(s
, D
->Constraint
[j
], dim
);
898 _reduce_evalue(e
, s
, 0);
901 for (j
= 0; j
< s
->n
; ++j
) {
902 value_clear(s
->fixed
[j
].d
);
903 value_clear(s
->fixed
[j
].m
);
904 free_evalue_refs(&s
->fixed
[j
].s
);
909 void reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
)
911 struct subst s
= { NULL
, 0, 0 };
913 if (EVALUE_IS_ZERO(*e
))
917 evalue_set_si(e
, 0, 1);
920 _reduce_evalue_in_domain(e
, D
, &s
);
925 void reduce_evalue (evalue
*e
) {
926 struct subst s
= { NULL
, 0, 0 };
928 if (value_notzero_p(e
->d
))
929 return; /* a rational number, its already reduced */
931 if (e
->x
.p
->type
== partition
) {
934 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
935 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
937 /* This shouldn't really happen;
938 * Empty domains should not be added.
940 POL_ENSURE_VERTICES(D
);
942 _reduce_evalue_in_domain(&e
->x
.p
->arr
[2*i
+1], D
, &s
);
944 if (emptyQ(D
) || EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
945 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
946 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
947 value_clear(e
->x
.p
->arr
[2*i
].d
);
949 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
950 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
954 if (e
->x
.p
->size
== 0) {
956 evalue_set_si(e
, 0, 1);
959 _reduce_evalue(e
, &s
, 0);
964 static void print_evalue_r(FILE *DST
, const evalue
*e
, const char *const *pname
)
966 if(value_notzero_p(e
->d
)) {
967 if(value_notone_p(e
->d
)) {
968 value_print(DST
,VALUE_FMT
,e
->x
.n
);
970 value_print(DST
,VALUE_FMT
,e
->d
);
973 value_print(DST
,VALUE_FMT
,e
->x
.n
);
977 print_enode(DST
,e
->x
.p
,pname
);
981 void print_evalue(FILE *DST
, const evalue
*e
, const char * const *pname
)
983 print_evalue_r(DST
, e
, pname
);
984 if (value_notzero_p(e
->d
))
988 void print_enode(FILE *DST
, enode
*p
, const char *const *pname
)
993 fprintf(DST
, "NULL");
999 for (i
=0; i
<p
->size
; i
++) {
1000 print_evalue_r(DST
, &p
->arr
[i
], pname
);
1004 fprintf(DST
, " }\n");
1008 for (i
=p
->size
-1; i
>=0; i
--) {
1009 print_evalue_r(DST
, &p
->arr
[i
], pname
);
1010 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
1012 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
1014 fprintf(DST
, " )\n");
1018 for (i
=0; i
<p
->size
; i
++) {
1019 print_evalue_r(DST
, &p
->arr
[i
], pname
);
1020 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
1022 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
1027 for (i
=p
->size
-1; i
>=1; i
--) {
1028 print_evalue_r(DST
, &p
->arr
[i
], pname
);
1030 fprintf(DST
, " * ");
1031 fprintf(DST
, p
->type
== flooring
? "[" : "{");
1032 print_evalue_r(DST
, &p
->arr
[0], pname
);
1033 fprintf(DST
, p
->type
== flooring
? "]" : "}");
1035 fprintf(DST
, "^%d + ", i
-1);
1037 fprintf(DST
, " + ");
1040 fprintf(DST
, " )\n");
1044 print_evalue_r(DST
, &p
->arr
[0], pname
);
1045 fprintf(DST
, "= 0 ] * \n");
1046 print_evalue_r(DST
, &p
->arr
[1], pname
);
1048 fprintf(DST
, " +\n [ ");
1049 print_evalue_r(DST
, &p
->arr
[0], pname
);
1050 fprintf(DST
, "!= 0 ] * \n");
1051 print_evalue_r(DST
, &p
->arr
[2], pname
);
1055 char **new_names
= NULL
;
1056 const char *const *names
= pname
;
1057 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
1058 if (!pname
|| p
->pos
< maxdim
) {
1059 new_names
= ALLOCN(char *, maxdim
);
1060 for (i
= 0; i
< p
->pos
; ++i
) {
1062 new_names
[i
] = (char *)pname
[i
];
1064 new_names
[i
] = ALLOCN(char, 10);
1065 snprintf(new_names
[i
], 10, "%c", 'P'+i
);
1068 for ( ; i
< maxdim
; ++i
) {
1069 new_names
[i
] = ALLOCN(char, 10);
1070 snprintf(new_names
[i
], 10, "_p%d", i
);
1072 names
= (const char**)new_names
;
1075 for (i
=0; i
<p
->size
/2; i
++) {
1076 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
1077 print_evalue_r(DST
, &p
->arr
[2*i
+1], names
);
1078 if (value_notzero_p(p
->arr
[2*i
+1].d
))
1082 if (!pname
|| p
->pos
< maxdim
) {
1083 for (i
= pname
? p
->pos
: 0; i
< maxdim
; ++i
)
1096 static void eadd_rev(const evalue
*e1
, evalue
*res
)
1100 evalue_copy(&ev
, e1
);
1102 free_evalue_refs(res
);
1106 static void eadd_rev_cst(const evalue
*e1
, evalue
*res
)
1110 evalue_copy(&ev
, e1
);
1111 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
1112 free_evalue_refs(res
);
1116 static int is_zero_on(evalue
*e
, Polyhedron
*D
)
1121 tmp
.x
.p
= new_enode(partition
, 2, D
->Dimension
);
1122 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Domain_Copy(D
));
1123 evalue_copy(&tmp
.x
.p
->arr
[1], e
);
1124 reduce_evalue(&tmp
);
1125 is_zero
= EVALUE_IS_ZERO(tmp
);
1126 free_evalue_refs(&tmp
);
1130 struct section
{ Polyhedron
* D
; evalue E
; };
1132 void eadd_partitions(const evalue
*e1
, evalue
*res
)
1137 s
= (struct section
*)
1138 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
1139 sizeof(struct section
));
1141 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1142 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1143 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1146 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1147 assert(res
->x
.p
->size
>= 2);
1148 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1149 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
1151 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
1153 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1162 /* See if we can extend one of the domains in res to cover fd */
1163 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1164 if (is_zero_on(&res
->x
.p
->arr
[2*i
+1], fd
))
1166 if (i
< res
->x
.p
->size
/2) {
1167 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
1168 DomainConcat(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
])));
1171 value_init(s
[n
].E
.d
);
1172 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
1176 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1177 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
1178 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1180 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1181 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1187 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1188 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1190 value_init(s
[n
].E
.d
);
1191 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1192 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1193 if (!emptyQ(fd
) && is_zero_on(&e1
->x
.p
->arr
[2*j
+1], fd
)) {
1194 d
= DomainConcat(fd
, d
);
1195 fd
= Empty_Polyhedron(fd
->Dimension
);
1201 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1205 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1208 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1209 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1210 value_clear(res
->x
.p
->arr
[2*i
].d
);
1215 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1216 for (j
= 0; j
< n
; ++j
) {
1217 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1218 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1219 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1220 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1226 static void explicit_complement(evalue
*res
)
1228 enode
*rel
= new_enode(relation
, 3, 0);
1230 value_clear(rel
->arr
[0].d
);
1231 rel
->arr
[0] = res
->x
.p
->arr
[0];
1232 value_clear(rel
->arr
[1].d
);
1233 rel
->arr
[1] = res
->x
.p
->arr
[1];
1234 value_set_si(rel
->arr
[2].d
, 1);
1235 value_init(rel
->arr
[2].x
.n
);
1236 value_set_si(rel
->arr
[2].x
.n
, 0);
1241 static void reduce_constant(evalue
*e
)
1246 value_gcd(g
, e
->x
.n
, e
->d
);
1247 if (value_notone_p(g
)) {
1248 value_division(e
->d
, e
->d
,g
);
1249 value_division(e
->x
.n
, e
->x
.n
,g
);
1254 void eadd(const evalue
*e1
, evalue
*res
)
1258 if (EVALUE_IS_ZERO(*e1
))
1261 if (EVALUE_IS_ZERO(*res
)) {
1262 if (value_notzero_p(e1
->d
)) {
1263 value_assign(res
->d
, e1
->d
);
1264 value_assign(res
->x
.n
, e1
->x
.n
);
1266 value_clear(res
->x
.n
);
1267 value_set_si(res
->d
, 0);
1268 res
->x
.p
= ecopy(e1
->x
.p
);
1273 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1274 /* Add two rational numbers */
1275 if (value_eq(e1
->d
, res
->d
))
1276 value_addto(res
->x
.n
, res
->x
.n
, e1
->x
.n
);
1278 value_multiply(res
->x
.n
, res
->x
.n
, e1
->d
);
1279 value_addmul(res
->x
.n
, e1
->x
.n
, res
->d
);
1280 value_multiply(res
->d
,e1
->d
,res
->d
);
1282 reduce_constant(res
);
1285 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1286 switch (res
->x
.p
->type
) {
1288 /* Add the constant to the constant term of a polynomial*/
1289 eadd(e1
, &res
->x
.p
->arr
[0]);
1292 /* Add the constant to all elements of a periodic number */
1293 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1294 eadd(e1
, &res
->x
.p
->arr
[i
]);
1298 fprintf(stderr
, "eadd: cannot add const with vector\n");
1302 eadd(e1
, &res
->x
.p
->arr
[1]);
1305 assert(EVALUE_IS_ZERO(*e1
));
1306 break; /* Do nothing */
1308 /* Create (zero) complement if needed */
1309 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1310 explicit_complement(res
);
1311 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1312 eadd(e1
, &res
->x
.p
->arr
[i
]);
1318 /* add polynomial or periodic to constant
1319 * you have to exchange e1 and res, before doing addition */
1321 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1325 else { // ((e1->d==0) && (res->d==0))
1326 assert(!((e1
->x
.p
->type
== partition
) ^
1327 (res
->x
.p
->type
== partition
)));
1328 if (e1
->x
.p
->type
== partition
) {
1329 eadd_partitions(e1
, res
);
1332 if (e1
->x
.p
->type
== relation
&&
1333 (res
->x
.p
->type
!= relation
||
1334 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1338 if (res
->x
.p
->type
== relation
) {
1339 if (e1
->x
.p
->type
== relation
&&
1340 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1341 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1342 explicit_complement(res
);
1343 for (i
= 1; i
< e1
->x
.p
->size
; ++i
)
1344 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1347 if (res
->x
.p
->size
< 3)
1348 explicit_complement(res
);
1349 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1350 eadd(e1
, &res
->x
.p
->arr
[i
]);
1353 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1354 /* adding to evalues of different type. two cases are possible
1355 * res is periodic and e1 is polynomial, you have to exchange
1356 * e1 and res then to add e1 to the constant term of res */
1357 if (e1
->x
.p
->type
== polynomial
) {
1358 eadd_rev_cst(e1
, res
);
1360 else if (res
->x
.p
->type
== polynomial
) {
1361 /* res is polynomial and e1 is periodic,
1362 add e1 to the constant term of res */
1364 eadd(e1
,&res
->x
.p
->arr
[0]);
1370 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1371 ((res
->x
.p
->type
== fractional
||
1372 res
->x
.p
->type
== flooring
) &&
1373 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1374 /* adding evalues of different position (i.e function of different unknowns
1375 * to case are possible */
1377 switch (res
->x
.p
->type
) {
1380 if (mod_term_smaller(res
, e1
))
1381 eadd(e1
,&res
->x
.p
->arr
[1]);
1383 eadd_rev_cst(e1
, res
);
1385 case polynomial
: // res and e1 are polynomials
1386 // add e1 to the constant term of res
1388 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1389 eadd(e1
,&res
->x
.p
->arr
[0]);
1391 eadd_rev_cst(e1
, res
);
1392 // value_clear(g); value_clear(m1); value_clear(m2);
1394 case periodic
: // res and e1 are pointers to periodic numbers
1395 //add e1 to all elements of res
1397 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1398 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1399 eadd(e1
,&res
->x
.p
->arr
[i
]);
1410 //same type , same pos and same size
1411 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1412 // add any element in e1 to the corresponding element in res
1413 i
= type_offset(res
->x
.p
);
1415 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1416 for (; i
<res
->x
.p
->size
; i
++) {
1417 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1422 /* Sizes are different */
1423 switch(res
->x
.p
->type
) {
1427 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1428 /* new enode and add res to that new node. If you do not do */
1429 /* that, you lose the the upper weight part of e1 ! */
1431 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1434 i
= type_offset(res
->x
.p
);
1436 assert(eequal(&e1
->x
.p
->arr
[0],
1437 &res
->x
.p
->arr
[0]));
1438 for (; i
<e1
->x
.p
->size
; i
++) {
1439 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1446 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1449 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1450 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1451 to add periodicaly elements of e1 to elements of ne, and finaly to
1456 value_init(ex
); value_init(ey
);value_init(ep
);
1459 value_set_si(ex
,e1
->x
.p
->size
);
1460 value_set_si(ey
,res
->x
.p
->size
);
1461 value_assign (ep
,*Lcm(ex
,ey
));
1462 p
=(int)mpz_get_si(ep
);
1463 ne
= (evalue
*) malloc (sizeof(evalue
));
1465 value_set_si( ne
->d
,0);
1467 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1469 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1472 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1475 value_assign(res
->d
, ne
->d
);
1481 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1490 static void emul_rev(const evalue
*e1
, evalue
*res
)
1494 evalue_copy(&ev
, e1
);
1496 free_evalue_refs(res
);
1500 static void emul_poly(const evalue
*e1
, evalue
*res
)
1502 int i
, j
, offset
= type_offset(res
->x
.p
);
1505 int size
= (e1
->x
.p
->size
+ res
->x
.p
->size
- offset
- 1);
1507 p
= new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1509 for (i
= offset
; i
< e1
->x
.p
->size
-1; ++i
)
1510 if (!EVALUE_IS_ZERO(e1
->x
.p
->arr
[i
]))
1513 /* special case pure power */
1514 if (i
== e1
->x
.p
->size
-1) {
1516 value_clear(p
->arr
[0].d
);
1517 p
->arr
[0] = res
->x
.p
->arr
[0];
1519 for (i
= offset
; i
< e1
->x
.p
->size
-1; ++i
)
1520 evalue_set_si(&p
->arr
[i
], 0, 1);
1521 for (i
= offset
; i
< res
->x
.p
->size
; ++i
) {
1522 value_clear(p
->arr
[i
+e1
->x
.p
->size
-offset
-1].d
);
1523 p
->arr
[i
+e1
->x
.p
->size
-offset
-1] = res
->x
.p
->arr
[i
];
1524 emul(&e1
->x
.p
->arr
[e1
->x
.p
->size
-1],
1525 &p
->arr
[i
+e1
->x
.p
->size
-offset
-1]);
1533 value_set_si(tmp
.d
,0);
1536 evalue_copy(&p
->arr
[0], &e1
->x
.p
->arr
[0]);
1537 for (i
= offset
; i
< e1
->x
.p
->size
; i
++) {
1538 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1539 emul(&res
->x
.p
->arr
[offset
], &tmp
.x
.p
->arr
[i
]);
1542 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1543 for (i
= offset
+1; i
<res
->x
.p
->size
; i
++)
1544 for (j
= offset
; j
<e1
->x
.p
->size
; j
++) {
1547 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1548 emul(&res
->x
.p
->arr
[i
], &ev
);
1549 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-offset
]);
1550 free_evalue_refs(&ev
);
1552 free_evalue_refs(res
);
1556 void emul_partitions(const evalue
*e1
, evalue
*res
)
1561 s
= (struct section
*)
1562 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1563 sizeof(struct section
));
1565 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1566 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1567 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1570 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1571 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1572 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1573 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1579 /* This code is only needed because the partitions
1580 are not true partitions.
1582 for (k
= 0; k
< n
; ++k
) {
1583 if (DomainIncludes(s
[k
].D
, d
))
1585 if (DomainIncludes(d
, s
[k
].D
)) {
1586 Domain_Free(s
[k
].D
);
1587 free_evalue_refs(&s
[k
].E
);
1598 value_init(s
[n
].E
.d
);
1599 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1600 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1604 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1605 value_clear(res
->x
.p
->arr
[2*i
].d
);
1606 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1611 evalue_set_si(res
, 0, 1);
1613 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1614 for (j
= 0; j
< n
; ++j
) {
1615 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1616 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1617 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1618 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1625 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1627 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1628 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1629 * evalues is not treated here */
1631 void emul(const evalue
*e1
, evalue
*res
)
1635 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1636 fprintf(stderr
, "emul: do not proced on evector type !\n");
1640 if (EVALUE_IS_ZERO(*res
))
1643 if (EVALUE_IS_ONE(*e1
))
1646 if (EVALUE_IS_ZERO(*e1
)) {
1647 if (value_notzero_p(res
->d
)) {
1648 value_assign(res
->d
, e1
->d
);
1649 value_assign(res
->x
.n
, e1
->x
.n
);
1651 free_evalue_refs(res
);
1653 evalue_set_si(res
, 0, 1);
1658 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1659 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1660 emul_partitions(e1
, res
);
1663 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1664 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1665 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1667 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1668 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1669 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1670 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3) {
1671 free_evalue_refs(&res
->x
.p
->arr
[2]);
1674 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1675 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1678 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1679 emul(e1
, &res
->x
.p
->arr
[i
]);
1681 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1682 switch(e1
->x
.p
->type
) {
1684 switch(res
->x
.p
->type
) {
1686 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1687 /* Product of two polynomials of the same variable */
1692 /* Product of two polynomials of different variables */
1694 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1695 for( i
=0; i
<res
->x
.p
->size
; i
++)
1696 emul(e1
, &res
->x
.p
->arr
[i
]);
1705 /* Product of a polynomial and a periodic or fractional */
1712 switch(res
->x
.p
->type
) {
1714 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1715 /* Product of two periodics of the same parameter and period */
1717 for(i
=0; i
<res
->x
.p
->size
;i
++)
1718 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1723 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1724 /* Product of two periodics of the same parameter and different periods */
1728 value_init(x
); value_init(y
);value_init(z
);
1731 value_set_si(x
,e1
->x
.p
->size
);
1732 value_set_si(y
,res
->x
.p
->size
);
1733 value_assign (z
,*Lcm(x
,y
));
1734 lcm
=(int)mpz_get_si(z
);
1735 newp
= (evalue
*) malloc (sizeof(evalue
));
1736 value_init(newp
->d
);
1737 value_set_si( newp
->d
,0);
1738 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1739 for(i
=0;i
<lcm
;i
++) {
1740 evalue_copy(&newp
->x
.p
->arr
[i
],
1741 &res
->x
.p
->arr
[i
%iy
]);
1744 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1746 value_assign(res
->d
,newp
->d
);
1749 value_clear(x
); value_clear(y
);value_clear(z
);
1753 /* Product of two periodics of different parameters */
1755 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1756 for(i
=0; i
<res
->x
.p
->size
; i
++)
1757 emul(e1
, &(res
->x
.p
->arr
[i
]));
1765 /* Product of a periodic and a polynomial */
1767 for(i
=0; i
<res
->x
.p
->size
; i
++)
1768 emul(e1
, &(res
->x
.p
->arr
[i
]));
1775 switch(res
->x
.p
->type
) {
1777 for(i
=0; i
<res
->x
.p
->size
; i
++)
1778 emul(e1
, &(res
->x
.p
->arr
[i
]));
1785 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1786 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1787 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1790 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1791 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1796 value_set_si(d
.x
.n
, 1);
1797 /* { x }^2 == { x }/2 */
1798 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1799 assert(e1
->x
.p
->size
== 3);
1800 assert(res
->x
.p
->size
== 3);
1802 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1804 eadd(&res
->x
.p
->arr
[1], &tmp
);
1805 emul(&e1
->x
.p
->arr
[2], &tmp
);
1806 emul(&e1
->x
.p
->arr
[1], &res
->x
.p
->arr
[1]);
1807 emul(&e1
->x
.p
->arr
[1], &res
->x
.p
->arr
[2]);
1808 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1809 free_evalue_refs(&tmp
);
1814 if(mod_term_smaller(res
, e1
))
1815 for(i
=1; i
<res
->x
.p
->size
; i
++)
1816 emul(e1
, &(res
->x
.p
->arr
[i
]));
1831 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1832 /* Product of two rational numbers */
1833 value_multiply(res
->d
,e1
->d
,res
->d
);
1834 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1835 reduce_constant(res
);
1839 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1840 /* Product of an expression (polynomial or peririodic) and a rational number */
1846 /* Product of a rationel number and an expression (polynomial or peririodic) */
1848 i
= type_offset(res
->x
.p
);
1849 for (; i
<res
->x
.p
->size
; i
++)
1850 emul(e1
, &res
->x
.p
->arr
[i
]);
1860 /* Frees mask content ! */
1861 void emask(evalue
*mask
, evalue
*res
) {
1868 if (EVALUE_IS_ZERO(*res
)) {
1869 free_evalue_refs(mask
);
1873 assert(value_zero_p(mask
->d
));
1874 assert(mask
->x
.p
->type
== partition
);
1875 assert(value_zero_p(res
->d
));
1876 assert(res
->x
.p
->type
== partition
);
1877 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1878 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1879 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1880 pos
= res
->x
.p
->pos
;
1882 s
= (struct section
*)
1883 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1884 sizeof(struct section
));
1888 evalue_set_si(&mone
, -1, 1);
1891 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1892 assert(mask
->x
.p
->size
>= 2);
1893 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1894 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1896 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1898 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1907 value_init(s
[n
].E
.d
);
1908 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1912 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1913 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1916 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1917 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1918 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1919 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1921 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1922 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1928 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1929 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1931 value_init(s
[n
].E
.d
);
1932 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1933 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1939 /* Just ignore; this may have been previously masked off */
1941 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1945 free_evalue_refs(&mone
);
1946 free_evalue_refs(mask
);
1947 free_evalue_refs(res
);
1950 evalue_set_si(res
, 0, 1);
1952 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1953 for (j
= 0; j
< n
; ++j
) {
1954 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1955 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1956 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1963 void evalue_copy(evalue
*dst
, const evalue
*src
)
1965 value_assign(dst
->d
, src
->d
);
1966 if(value_notzero_p(src
->d
)) {
1967 value_init(dst
->x
.n
);
1968 value_assign(dst
->x
.n
, src
->x
.n
);
1970 dst
->x
.p
= ecopy(src
->x
.p
);
1973 evalue
*evalue_dup(const evalue
*e
)
1975 evalue
*res
= ALLOC(evalue
);
1977 evalue_copy(res
, e
);
1981 enode
*new_enode(enode_type type
,int size
,int pos
) {
1987 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1990 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1994 for(i
=0; i
<size
; i
++) {
1995 value_init(res
->arr
[i
].d
);
1996 value_set_si(res
->arr
[i
].d
,0);
1997 res
->arr
[i
].x
.p
= 0;
2002 enode
*ecopy(enode
*e
) {
2007 res
= new_enode(e
->type
,e
->size
,e
->pos
);
2008 for(i
=0;i
<e
->size
;++i
) {
2009 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
2010 if(value_zero_p(res
->arr
[i
].d
))
2011 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
2012 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
2013 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
2015 value_init(res
->arr
[i
].x
.n
);
2016 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
2022 int ecmp(const evalue
*e1
, const evalue
*e2
)
2028 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
2032 value_multiply(m
, e1
->x
.n
, e2
->d
);
2033 value_multiply(m2
, e2
->x
.n
, e1
->d
);
2035 if (value_lt(m
, m2
))
2037 else if (value_gt(m
, m2
))
2047 if (value_notzero_p(e1
->d
))
2049 if (value_notzero_p(e2
->d
))
2055 if (p1
->type
!= p2
->type
)
2056 return p1
->type
- p2
->type
;
2057 if (p1
->pos
!= p2
->pos
)
2058 return p1
->pos
- p2
->pos
;
2059 if (p1
->size
!= p2
->size
)
2060 return p1
->size
- p2
->size
;
2062 for (i
= p1
->size
-1; i
>= 0; --i
)
2063 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
2069 int eequal(const evalue
*e1
, const evalue
*e2
)
2074 if (value_ne(e1
->d
,e2
->d
))
2077 /* e1->d == e2->d */
2078 if (value_notzero_p(e1
->d
)) {
2079 if (value_ne(e1
->x
.n
,e2
->x
.n
))
2082 /* e1->d == e2->d != 0 AND e1->n == e2->n */
2086 /* e1->d == e2->d == 0 */
2089 if (p1
->type
!= p2
->type
) return 0;
2090 if (p1
->size
!= p2
->size
) return 0;
2091 if (p1
->pos
!= p2
->pos
) return 0;
2092 for (i
=0; i
<p1
->size
; i
++)
2093 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
2098 void free_evalue_refs(evalue
*e
) {
2103 if (EVALUE_IS_DOMAIN(*e
)) {
2104 Domain_Free(EVALUE_DOMAIN(*e
));
2107 } else if (value_pos_p(e
->d
)) {
2109 /* 'e' stores a constant */
2111 value_clear(e
->x
.n
);
2114 assert(value_zero_p(e
->d
));
2117 if (!p
) return; /* null pointer */
2118 for (i
=0; i
<p
->size
; i
++) {
2119 free_evalue_refs(&(p
->arr
[i
]));
2123 } /* free_evalue_refs */
2125 void evalue_free(evalue
*e
)
2127 free_evalue_refs(e
);
2131 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
2132 Vector
* val
, evalue
*res
)
2134 unsigned nparam
= periods
->Size
;
2137 double d
= compute_evalue(e
, val
->p
);
2138 d
*= VALUE_TO_DOUBLE(m
);
2143 value_assign(res
->d
, m
);
2144 value_init(res
->x
.n
);
2145 value_set_double(res
->x
.n
, d
);
2146 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
2149 if (value_one_p(periods
->p
[p
]))
2150 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
2155 value_assign(tmp
, periods
->p
[p
]);
2156 value_set_si(res
->d
, 0);
2157 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
2159 value_decrement(tmp
, tmp
);
2160 value_assign(val
->p
[p
], tmp
);
2161 mod2table_r(e
, periods
, m
, p
+1, val
,
2162 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
2163 } while (value_pos_p(tmp
));
2169 static void rel2table(evalue
*e
, int zero
)
2171 if (value_pos_p(e
->d
)) {
2172 if (value_zero_p(e
->x
.n
) == zero
)
2173 value_set_si(e
->x
.n
, 1);
2175 value_set_si(e
->x
.n
, 0);
2176 value_set_si(e
->d
, 1);
2179 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
2180 rel2table(&e
->x
.p
->arr
[i
], zero
);
2184 void evalue_mod2table(evalue
*e
, int nparam
)
2189 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2192 for (i
=0; i
<p
->size
; i
++) {
2193 evalue_mod2table(&(p
->arr
[i
]), nparam
);
2195 if (p
->type
== relation
) {
2200 evalue_copy(©
, &p
->arr
[0]);
2202 rel2table(&p
->arr
[0], 1);
2203 emul(&p
->arr
[0], &p
->arr
[1]);
2205 rel2table(©
, 0);
2206 emul(©
, &p
->arr
[2]);
2207 eadd(&p
->arr
[2], &p
->arr
[1]);
2208 free_evalue_refs(&p
->arr
[2]);
2209 free_evalue_refs(©
);
2211 free_evalue_refs(&p
->arr
[0]);
2215 } else if (p
->type
== fractional
) {
2216 Vector
*periods
= Vector_Alloc(nparam
);
2217 Vector
*val
= Vector_Alloc(nparam
);
2223 value_set_si(tmp
, 1);
2224 Vector_Set(periods
->p
, 1, nparam
);
2225 Vector_Set(val
->p
, 0, nparam
);
2226 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2229 assert(p
->type
== polynomial
);
2230 assert(p
->size
== 2);
2231 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2232 value_lcm(tmp
, tmp
, p
->arr
[1].d
);
2234 value_lcm(tmp
, tmp
, ev
->d
);
2236 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2239 evalue_set_si(&res
, 0, 1);
2240 /* Compute the polynomial using Horner's rule */
2241 for (i
=p
->size
-1;i
>1;i
--) {
2242 eadd(&p
->arr
[i
], &res
);
2245 eadd(&p
->arr
[1], &res
);
2247 free_evalue_refs(e
);
2248 free_evalue_refs(&EP
);
2253 Vector_Free(periods
);
2255 } /* evalue_mod2table */
2257 /********************************************************/
2258 /* function in domain */
2259 /* check if the parameters in list_args */
2260 /* verifies the constraints of Domain P */
2261 /********************************************************/
2262 int in_domain(Polyhedron
*P
, Value
*list_args
)
2265 Value v
; /* value of the constraint of a row when
2266 parameters are instantiated*/
2270 for (row
= 0; row
< P
->NbConstraints
; row
++) {
2271 Inner_Product(P
->Constraint
[row
]+1, list_args
, P
->Dimension
, &v
);
2272 value_addto(v
, v
, P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2273 if (value_neg_p(v
) ||
2274 value_zero_p(P
->Constraint
[row
][0]) && value_notzero_p(v
)) {
2281 return in
|| (P
->next
&& in_domain(P
->next
, list_args
));
2284 /****************************************************/
2285 /* function compute enode */
2286 /* compute the value of enode p with parameters */
2287 /* list "list_args */
2288 /* compute the polynomial or the periodic */
2289 /****************************************************/
2291 static double compute_enode(enode
*p
, Value
*list_args
) {
2303 if (p
->type
== polynomial
) {
2305 value_assign(param
,list_args
[p
->pos
-1]);
2307 /* Compute the polynomial using Horner's rule */
2308 for (i
=p
->size
-1;i
>0;i
--) {
2309 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2310 res
*=VALUE_TO_DOUBLE(param
);
2312 res
+=compute_evalue(&p
->arr
[0],list_args
);
2314 else if (p
->type
== fractional
) {
2315 double d
= compute_evalue(&p
->arr
[0], list_args
);
2316 d
-= floor(d
+1e-10);
2318 /* Compute the polynomial using Horner's rule */
2319 for (i
=p
->size
-1;i
>1;i
--) {
2320 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2323 res
+=compute_evalue(&p
->arr
[1],list_args
);
2325 else if (p
->type
== flooring
) {
2326 double d
= compute_evalue(&p
->arr
[0], list_args
);
2329 /* Compute the polynomial using Horner's rule */
2330 for (i
=p
->size
-1;i
>1;i
--) {
2331 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2334 res
+=compute_evalue(&p
->arr
[1],list_args
);
2336 else if (p
->type
== periodic
) {
2337 value_assign(m
,list_args
[p
->pos
-1]);
2339 /* Choose the right element of the periodic */
2340 value_set_si(param
,p
->size
);
2341 value_pmodulus(m
,m
,param
);
2342 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2344 else if (p
->type
== relation
) {
2345 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2346 res
= compute_evalue(&p
->arr
[1], list_args
);
2347 else if (p
->size
> 2)
2348 res
= compute_evalue(&p
->arr
[2], list_args
);
2350 else if (p
->type
== partition
) {
2351 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2352 Value
*vals
= list_args
;
2355 for (i
= 0; i
< dim
; ++i
) {
2356 value_init(vals
[i
]);
2358 value_assign(vals
[i
], list_args
[i
]);
2361 for (i
= 0; i
< p
->size
/2; ++i
)
2362 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2363 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2367 for (i
= 0; i
< dim
; ++i
)
2368 value_clear(vals
[i
]);
2377 } /* compute_enode */
2379 /*************************************************/
2380 /* return the value of Ehrhart Polynomial */
2381 /* It returns a double, because since it is */
2382 /* a recursive function, some intermediate value */
2383 /* might not be integral */
2384 /*************************************************/
2386 double compute_evalue(const evalue
*e
, Value
*list_args
)
2390 if (value_notzero_p(e
->d
)) {
2391 if (value_notone_p(e
->d
))
2392 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2394 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2397 res
= compute_enode(e
->x
.p
,list_args
);
2399 } /* compute_evalue */
2402 /****************************************************/
2403 /* function compute_poly : */
2404 /* Check for the good validity domain */
2405 /* return the number of point in the Polyhedron */
2406 /* in allocated memory */
2407 /* Using the Ehrhart pseudo-polynomial */
2408 /****************************************************/
2409 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2412 /* double d; int i; */
2414 tmp
= (Value
*) malloc (sizeof(Value
));
2415 assert(tmp
!= NULL
);
2417 value_set_si(*tmp
,0);
2420 return(tmp
); /* no ehrhart polynomial */
2421 if(en
->ValidityDomain
) {
2422 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2423 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2428 return(tmp
); /* no Validity Domain */
2430 if(in_domain(en
->ValidityDomain
,list_args
)) {
2432 #ifdef EVAL_EHRHART_DEBUG
2433 Print_Domain(stdout
,en
->ValidityDomain
);
2434 print_evalue(stdout
,&en
->EP
);
2437 /* d = compute_evalue(&en->EP,list_args);
2439 printf("(double)%lf = %d\n", d, i ); */
2440 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2446 value_set_si(*tmp
,0);
2447 return(tmp
); /* no compatible domain with the arguments */
2448 } /* compute_poly */
2450 static evalue
*eval_polynomial(const enode
*p
, int offset
,
2451 evalue
*base
, Value
*values
)
2456 res
= evalue_zero();
2457 for (i
= p
->size
-1; i
> offset
; --i
) {
2458 c
= evalue_eval(&p
->arr
[i
], values
);
2463 c
= evalue_eval(&p
->arr
[offset
], values
);
2470 evalue
*evalue_eval(const evalue
*e
, Value
*values
)
2477 if (value_notzero_p(e
->d
)) {
2478 res
= ALLOC(evalue
);
2480 evalue_copy(res
, e
);
2483 switch (e
->x
.p
->type
) {
2485 value_init(param
.x
.n
);
2486 value_assign(param
.x
.n
, values
[e
->x
.p
->pos
-1]);
2487 value_init(param
.d
);
2488 value_set_si(param
.d
, 1);
2490 res
= eval_polynomial(e
->x
.p
, 0, ¶m
, values
);
2491 free_evalue_refs(¶m
);
2494 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2495 mpz_fdiv_r(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2497 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2498 evalue_free(param2
);
2501 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2502 mpz_fdiv_q(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2503 value_set_si(param2
->d
, 1);
2505 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2506 evalue_free(param2
);
2509 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2510 if (value_zero_p(param2
->x
.n
))
2511 res
= evalue_eval(&e
->x
.p
->arr
[1], values
);
2512 else if (e
->x
.p
->size
> 2)
2513 res
= evalue_eval(&e
->x
.p
->arr
[2], values
);
2515 res
= evalue_zero();
2516 evalue_free(param2
);
2519 assert(e
->x
.p
->pos
== EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
);
2520 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2521 if (in_domain(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), values
)) {
2522 res
= evalue_eval(&e
->x
.p
->arr
[2*i
+1], values
);
2526 res
= evalue_zero();
2534 size_t value_size(Value v
) {
2535 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2536 * sizeof(v
[0]._mp_d
[0]);
2539 size_t domain_size(Polyhedron
*D
)
2542 size_t s
= sizeof(*D
);
2544 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2545 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2546 s
+= value_size(D
->Constraint
[i
][j
]);
2549 for (i = 0; i < D->NbRays; ++i)
2550 for (j = 0; j < D->Dimension+2; ++j)
2551 s += value_size(D->Ray[i][j]);
2554 return D
->next
? s
+domain_size(D
->next
) : s
;
2557 size_t enode_size(enode
*p
) {
2558 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2561 if (p
->type
== partition
)
2562 for (i
= 0; i
< p
->size
/2; ++i
) {
2563 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2564 s
+= evalue_size(&p
->arr
[2*i
+1]);
2567 for (i
= 0; i
< p
->size
; ++i
) {
2568 s
+= evalue_size(&p
->arr
[i
]);
2573 size_t evalue_size(evalue
*e
)
2575 size_t s
= sizeof(*e
);
2576 s
+= value_size(e
->d
);
2577 if (value_notzero_p(e
->d
))
2578 s
+= value_size(e
->x
.n
);
2580 s
+= enode_size(e
->x
.p
);
2584 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2586 evalue
*found
= NULL
;
2591 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2594 value_init(offset
.d
);
2595 value_init(offset
.x
.n
);
2596 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2597 value_lcm(offset
.d
, m
, offset
.d
);
2598 value_set_si(offset
.x
.n
, 1);
2601 evalue_copy(©
, cst
);
2604 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2606 if (eequal(base
, &e
->x
.p
->arr
[0]))
2607 found
= &e
->x
.p
->arr
[0];
2609 value_set_si(offset
.x
.n
, -2);
2612 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2614 if (eequal(base
, &e
->x
.p
->arr
[0]))
2617 free_evalue_refs(cst
);
2618 free_evalue_refs(&offset
);
2621 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2622 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2627 static evalue
*find_relation_pair(evalue
*e
)
2630 evalue
*found
= NULL
;
2632 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2635 if (e
->x
.p
->type
== fractional
) {
2640 poly_denom(&e
->x
.p
->arr
[0], &m
);
2642 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2643 cst
= &cst
->x
.p
->arr
[0])
2646 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2647 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2652 i
= e
->x
.p
->type
== relation
;
2653 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2654 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2659 void evalue_mod2relation(evalue
*e
) {
2662 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2665 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2666 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2667 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2668 value_clear(e
->x
.p
->arr
[2*i
].d
);
2669 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2671 if (2*i
< e
->x
.p
->size
) {
2672 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2673 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2678 if (e
->x
.p
->size
== 0) {
2680 evalue_set_si(e
, 0, 1);
2686 while ((d
= find_relation_pair(e
)) != NULL
) {
2690 value_init(split
.d
);
2691 value_set_si(split
.d
, 0);
2692 split
.x
.p
= new_enode(relation
, 3, 0);
2693 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2694 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2696 ev
= &split
.x
.p
->arr
[0];
2697 value_set_si(ev
->d
, 0);
2698 ev
->x
.p
= new_enode(fractional
, 3, -1);
2699 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2700 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2701 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2707 free_evalue_refs(&split
);
2711 static int evalue_comp(const void * a
, const void * b
)
2713 const evalue
*e1
= *(const evalue
**)a
;
2714 const evalue
*e2
= *(const evalue
**)b
;
2715 return ecmp(e1
, e2
);
2718 void evalue_combine(evalue
*e
)
2725 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2728 NALLOC(evs
, e
->x
.p
->size
/2);
2729 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2730 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2731 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2732 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2733 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2734 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2735 value_clear(p
->arr
[2*k
].d
);
2736 value_clear(p
->arr
[2*k
+1].d
);
2737 p
->arr
[2*k
] = *(evs
[i
]-1);
2738 p
->arr
[2*k
+1] = *(evs
[i
]);
2741 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2744 value_clear((evs
[i
]-1)->d
);
2748 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2749 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2750 free_evalue_refs(evs
[i
]);
2754 for (i
= 2*k
; i
< p
->size
; ++i
)
2755 value_clear(p
->arr
[i
].d
);
2762 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2764 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2766 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2769 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2770 Polyhedron
*D
, *N
, **P
;
2773 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2780 if (D
->NbEq
<= H
->NbEq
) {
2786 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2787 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2788 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2789 reduce_evalue(&tmp
);
2790 if (value_notzero_p(tmp
.d
) ||
2791 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2794 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2795 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2798 free_evalue_refs(&tmp
);
2804 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2806 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2808 value_clear(e
->x
.p
->arr
[2*i
].d
);
2809 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2811 if (2*i
< e
->x
.p
->size
) {
2812 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2813 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2820 H
= DomainConvex(D
, 0);
2821 E
= DomainDifference(H
, D
, 0);
2823 D
= DomainDifference(H
, E
, 0);
2826 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2830 /* Use smallest representative for coefficients in affine form in
2831 * argument of fractional.
2832 * Since any change will make the argument non-standard,
2833 * the containing evalue will have to be reduced again afterward.
2835 static void fractional_minimal_coefficients(enode
*p
)
2841 assert(p
->type
== fractional
);
2843 while (value_zero_p(pp
->d
)) {
2844 assert(pp
->x
.p
->type
== polynomial
);
2845 assert(pp
->x
.p
->size
== 2);
2846 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2847 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2848 if (value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2849 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2850 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2851 pp
= &pp
->x
.p
->arr
[0];
2857 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2862 unsigned dim
= D
->Dimension
;
2863 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2866 assert(p
->type
== fractional
|| p
->type
== flooring
);
2867 value_set_si(T
->p
[1][dim
], 1);
2868 evalue_extract_affine(&p
->arr
[0], T
->p
[0], &T
->p
[0][dim
], d
);
2869 I
= DomainImage(D
, T
, 0);
2870 H
= DomainConvex(I
, 0);
2880 static void replace_by_affine(evalue
*e
, Value offset
)
2887 value_init(inc
.x
.n
);
2888 value_set_si(inc
.d
, 1);
2889 value_oppose(inc
.x
.n
, offset
);
2890 eadd(&inc
, &p
->arr
[0]);
2891 reorder_terms_about(p
, &p
->arr
[0]); /* frees arr[0] */
2895 free_evalue_refs(&inc
);
2898 int evalue_range_reduction_in_domain(evalue
*e
, Polyhedron
*D
)
2907 if (value_notzero_p(e
->d
))
2912 if (p
->type
== relation
) {
2919 fractional_minimal_coefficients(p
->arr
[0].x
.p
);
2920 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
);
2921 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2922 equal
= value_eq(min
, max
);
2923 mpz_cdiv_q(min
, min
, d
);
2924 mpz_fdiv_q(max
, max
, d
);
2926 if (bounded
&& value_gt(min
, max
)) {
2932 evalue_set_si(e
, 0, 1);
2935 free_evalue_refs(&(p
->arr
[1]));
2936 free_evalue_refs(&(p
->arr
[0]));
2942 return r
? r
: evalue_range_reduction_in_domain(e
, D
);
2943 } else if (bounded
&& equal
) {
2946 free_evalue_refs(&(p
->arr
[2]));
2949 free_evalue_refs(&(p
->arr
[0]));
2955 return evalue_range_reduction_in_domain(e
, D
);
2956 } else if (bounded
&& value_eq(min
, max
)) {
2957 /* zero for a single value */
2959 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2960 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2961 value_multiply(min
, min
, d
);
2962 value_subtract(M
->p
[0][D
->Dimension
+1],
2963 M
->p
[0][D
->Dimension
+1], min
);
2964 E
= DomainAddConstraints(D
, M
, 0);
2970 r
= evalue_range_reduction_in_domain(&p
->arr
[1], E
);
2972 r
|= evalue_range_reduction_in_domain(&p
->arr
[2], D
);
2974 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2982 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2985 i
= p
->type
== relation
? 1 :
2986 p
->type
== fractional
? 1 : 0;
2987 for (; i
<p
->size
; i
++)
2988 r
|= evalue_range_reduction_in_domain(&p
->arr
[i
], D
);
2990 if (p
->type
!= fractional
) {
2991 if (r
&& p
->type
== polynomial
) {
2994 value_set_si(f
.d
, 0);
2995 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2996 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2997 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2998 reorder_terms_about(p
, &f
);
3009 fractional_minimal_coefficients(p
);
3010 I
= polynomial_projection(p
, D
, &d
, NULL
);
3011 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
3012 mpz_fdiv_q(min
, min
, d
);
3013 mpz_fdiv_q(max
, max
, d
);
3014 value_subtract(d
, max
, min
);
3016 if (bounded
&& value_eq(min
, max
)) {
3017 replace_by_affine(e
, min
);
3019 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
3020 /* replace {g}^2 by -(g-min)^2 + (2{g}+1)*(g-min) - {g}
3021 * See pages 199-200 of PhD thesis.
3029 value_set_si(rem
.d
, 0);
3030 rem
.x
.p
= new_enode(fractional
, 3, -1);
3031 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
3032 value_clear(rem
.x
.p
->arr
[1].d
);
3033 value_clear(rem
.x
.p
->arr
[2].d
);
3034 rem
.x
.p
->arr
[1] = p
->arr
[1];
3035 rem
.x
.p
->arr
[2] = p
->arr
[2];
3036 for (i
= 3; i
< p
->size
; ++i
)
3037 p
->arr
[i
-2] = p
->arr
[i
];
3041 value_init(inc
.x
.n
);
3042 value_set_si(inc
.d
, 1);
3043 value_oppose(inc
.x
.n
, min
);
3046 evalue_copy(&t
, &p
->arr
[0]);
3050 value_set_si(f
.d
, 0);
3051 f
.x
.p
= new_enode(fractional
, 3, -1);
3052 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3053 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3054 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
3056 value_init(factor
.d
);
3057 evalue_set_si(&factor
, -1, 1);
3063 value_clear(f
.x
.p
->arr
[1].x
.n
);
3064 value_clear(f
.x
.p
->arr
[2].x
.n
);
3065 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3066 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3070 reorder_terms(&rem
);
3077 free_evalue_refs(&inc
);
3078 free_evalue_refs(&t
);
3079 free_evalue_refs(&f
);
3080 free_evalue_refs(&factor
);
3081 free_evalue_refs(&rem
);
3083 evalue_range_reduction_in_domain(e
, D
);
3087 _reduce_evalue(&p
->arr
[0], 0, 1);
3099 void evalue_range_reduction(evalue
*e
)
3102 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
3105 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3106 if (evalue_range_reduction_in_domain(&e
->x
.p
->arr
[2*i
+1],
3107 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
3108 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3110 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
3111 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
3112 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3113 value_clear(e
->x
.p
->arr
[2*i
].d
);
3115 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
3116 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
3124 Enumeration
* partition2enumeration(evalue
*EP
)
3127 Enumeration
*en
, *res
= NULL
;
3129 if (EVALUE_IS_ZERO(*EP
)) {
3134 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
3135 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
3136 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
3139 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
3140 value_clear(EP
->x
.p
->arr
[2*i
].d
);
3141 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
3149 int evalue_frac2floor_in_domain3(evalue
*e
, Polyhedron
*D
, int shift
)
3158 if (value_notzero_p(e
->d
))
3163 i
= p
->type
== relation
? 1 :
3164 p
->type
== fractional
? 1 : 0;
3165 for (; i
<p
->size
; i
++)
3166 r
|= evalue_frac2floor_in_domain3(&p
->arr
[i
], D
, shift
);
3168 if (p
->type
!= fractional
) {
3169 if (r
&& p
->type
== polynomial
) {
3172 value_set_si(f
.d
, 0);
3173 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
3174 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
3175 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3176 reorder_terms_about(p
, &f
);
3186 I
= polynomial_projection(p
, D
, &d
, NULL
);
3189 Polyhedron_Print(stderr, P_VALUE_FMT, I);
3192 assert(I
->NbEq
== 0); /* Should have been reduced */
3195 for (i
= 0; i
< I
->NbConstraints
; ++i
)
3196 if (value_pos_p(I
->Constraint
[i
][1]))
3199 if (i
< I
->NbConstraints
) {
3201 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
3202 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
3203 if (value_neg_p(min
)) {
3205 mpz_fdiv_q(min
, min
, d
);
3206 value_init(offset
.d
);
3207 value_set_si(offset
.d
, 1);
3208 value_init(offset
.x
.n
);
3209 value_oppose(offset
.x
.n
, min
);
3210 eadd(&offset
, &p
->arr
[0]);
3211 free_evalue_refs(&offset
);
3221 value_set_si(fl
.d
, 0);
3222 fl
.x
.p
= new_enode(flooring
, 3, -1);
3223 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
3224 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
3225 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
3227 eadd(&fl
, &p
->arr
[0]);
3228 reorder_terms_about(p
, &p
->arr
[0]);
3232 free_evalue_refs(&fl
);
3237 int evalue_frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
3239 return evalue_frac2floor_in_domain3(e
, D
, 1);
3242 void evalue_frac2floor2(evalue
*e
, int shift
)
3245 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
3247 if (evalue_frac2floor_in_domain3(e
, NULL
, 0))
3253 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3254 if (evalue_frac2floor_in_domain3(&e
->x
.p
->arr
[2*i
+1],
3255 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), shift
))
3256 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3259 void evalue_frac2floor(evalue
*e
)
3261 evalue_frac2floor2(e
, 1);
3264 /* Add a new variable with lower bound 1 and upper bound specified
3265 * by row. If negative is true, then the new variable has upper
3266 * bound -1 and lower bound specified by row.
3268 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
3269 Vector
*row
, int negative
)
3273 int nparam
= D
->Dimension
- nvar
;
3276 nr
= D
->NbConstraints
+ 2;
3277 nc
= D
->Dimension
+ 2 + 1;
3278 C
= Matrix_Alloc(nr
, nc
);
3279 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
3280 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
3281 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3282 D
->Dimension
+ 1 - nvar
);
3287 nc
= C
->NbColumns
+ 1;
3288 C
= Matrix_Alloc(nr
, nc
);
3289 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
3290 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
3291 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3292 oldC
->NbColumns
- 1 - nvar
);
3295 value_set_si(C
->p
[nr
-2][0], 1);
3297 value_set_si(C
->p
[nr
-2][1 + nvar
], -1);
3299 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
3300 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
3302 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
3303 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
3309 static void floor2frac_r(evalue
*e
, int nvar
)
3316 if (value_notzero_p(e
->d
))
3321 assert(p
->type
== flooring
);
3322 for (i
= 1; i
< p
->size
; i
++)
3323 floor2frac_r(&p
->arr
[i
], nvar
);
3325 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3326 assert(pp
->x
.p
->type
== polynomial
);
3327 pp
->x
.p
->pos
-= nvar
;
3331 value_set_si(f
.d
, 0);
3332 f
.x
.p
= new_enode(fractional
, 3, -1);
3333 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3334 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3335 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3337 eadd(&f
, &p
->arr
[0]);
3338 reorder_terms_about(p
, &p
->arr
[0]);
3342 free_evalue_refs(&f
);
3345 /* Convert flooring back to fractional and shift position
3346 * of the parameters by nvar
3348 static void floor2frac(evalue
*e
, int nvar
)
3350 floor2frac_r(e
, nvar
);
3354 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
3357 int nparam
= D
->Dimension
- nvar
;
3361 D
= Constraints2Polyhedron(C
, 0);
3365 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3367 /* Double check that D was not unbounded. */
3368 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3376 static evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3377 int *signs
, Matrix
*C
, unsigned MaxRays
)
3383 evalue
*factor
= NULL
;
3387 if (EVALUE_IS_ZERO(*e
))
3391 Polyhedron
*DD
= Disjoint_Domain(D
, 0, MaxRays
);
3398 res
= esum_over_domain(e
, nvar
, Q
, signs
, C
, MaxRays
);
3401 for (Q
= DD
; Q
; Q
= DD
) {
3407 t
= esum_over_domain(e
, nvar
, Q
, signs
, C
, MaxRays
);
3420 if (value_notzero_p(e
->d
)) {
3423 t
= esum_over_domain_cst(nvar
, D
, C
);
3425 if (!EVALUE_IS_ONE(*e
))
3431 switch (e
->x
.p
->type
) {
3433 evalue
*pp
= &e
->x
.p
->arr
[0];
3435 if (pp
->x
.p
->pos
> nvar
) {
3436 /* remainder is independent of the summated vars */
3442 floor2frac(&f
, nvar
);
3444 t
= esum_over_domain_cst(nvar
, D
, C
);
3448 free_evalue_refs(&f
);
3453 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3454 poly_denom(pp
, &row
->p
[1 + nvar
]);
3455 value_set_si(row
->p
[0], 1);
3456 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3457 pp
= &pp
->x
.p
->arr
[0]) {
3459 assert(pp
->x
.p
->type
== polynomial
);
3461 if (pos
>= 1 + nvar
)
3463 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3464 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3465 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3467 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3468 value_division(row
->p
[1 + D
->Dimension
+ 1],
3469 row
->p
[1 + D
->Dimension
+ 1],
3471 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3472 row
->p
[1 + D
->Dimension
+ 1],
3474 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3478 int pos
= e
->x
.p
->pos
;
3481 factor
= ALLOC(evalue
);
3482 value_init(factor
->d
);
3483 value_set_si(factor
->d
, 0);
3484 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3485 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3486 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3490 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3491 negative
= signs
[pos
-1] < 0;
3492 value_set_si(row
->p
[0], 1);
3494 value_set_si(row
->p
[pos
], -1);
3495 value_set_si(row
->p
[1 + nvar
], 1);
3497 value_set_si(row
->p
[pos
], 1);
3498 value_set_si(row
->p
[1 + nvar
], -1);
3506 offset
= type_offset(e
->x
.p
);
3508 res
= esum_over_domain(&e
->x
.p
->arr
[offset
], nvar
, D
, signs
, C
, MaxRays
);
3512 evalue_copy(&cum
, factor
);
3516 for (i
= 1; offset
+i
< e
->x
.p
->size
; ++i
) {
3520 C
= esum_add_constraint(nvar
, D
, C
, row
, negative
);
3526 Vector_Print(stderr, P_VALUE_FMT, row);
3528 Matrix_Print(stderr, P_VALUE_FMT, C);
3530 t
= esum_over_domain(&e
->x
.p
->arr
[offset
+i
], nvar
, D
, signs
, C
, MaxRays
);
3535 if (negative
&& (i
% 2))
3545 if (factor
&& offset
+i
+1 < e
->x
.p
->size
)
3552 free_evalue_refs(&cum
);
3553 evalue_free(factor
);
3564 static void domain_signs(Polyhedron
*D
, int *signs
)
3568 POL_ENSURE_VERTICES(D
);
3569 for (j
= 0; j
< D
->Dimension
; ++j
) {
3571 for (k
= 0; k
< D
->NbRays
; ++k
) {
3572 signs
[j
] = value_sign(D
->Ray
[k
][1+j
]);
3579 static void shift_floor_in_domain(evalue
*e
, Polyhedron
*D
)
3586 if (value_notzero_p(e
->d
))
3591 for (i
= type_offset(p
); i
< p
->size
; ++i
)
3592 shift_floor_in_domain(&p
->arr
[i
], D
);
3594 if (p
->type
!= flooring
)
3600 I
= polynomial_projection(p
, D
, &d
, NULL
);
3601 assert(I
->NbEq
== 0); /* Should have been reduced */
3603 for (i
= 0; i
< I
->NbConstraints
; ++i
)
3604 if (value_pos_p(I
->Constraint
[i
][1]))
3606 assert(i
< I
->NbConstraints
);
3607 if (i
< I
->NbConstraints
) {
3608 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
3609 mpz_fdiv_q(m
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
3610 if (value_neg_p(m
)) {
3611 /* replace [e] by [e-m]+m such that e-m >= 0 */
3616 value_set_si(f
.d
, 1);
3617 value_oppose(f
.x
.n
, m
);
3618 eadd(&f
, &p
->arr
[0]);
3621 value_set_si(f
.d
, 0);
3622 f
.x
.p
= new_enode(flooring
, 3, -1);
3623 value_clear(f
.x
.p
->arr
[0].d
);
3624 f
.x
.p
->arr
[0] = p
->arr
[0];
3625 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
3626 value_set_si(f
.x
.p
->arr
[1].d
, 1);
3627 value_init(f
.x
.p
->arr
[1].x
.n
);
3628 value_assign(f
.x
.p
->arr
[1].x
.n
, m
);
3629 reorder_terms_about(p
, &f
);
3640 /* Make arguments of all floors non-negative */
3641 static void shift_floor_arguments(evalue
*e
)
3645 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
3648 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3649 shift_floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
3650 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3653 evalue
*evalue_sum(evalue
*e
, int nvar
, unsigned MaxRays
)
3657 evalue
*res
= ALLOC(evalue
);
3661 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3662 evalue_copy(res
, e
);
3666 evalue_split_domains_into_orthants(e
, MaxRays
);
3667 evalue_frac2floor2(e
, 0);
3668 evalue_set_si(res
, 0, 1);
3670 assert(value_zero_p(e
->d
));
3671 assert(e
->x
.p
->type
== partition
);
3672 shift_floor_arguments(e
);
3674 assert(e
->x
.p
->size
>= 2);
3675 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3677 signs
= alloca(sizeof(int) * dim
);
3679 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3681 domain_signs(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), signs
);
3682 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3683 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), signs
, 0,
3694 evalue
*esum(evalue
*e
, int nvar
)
3696 return evalue_sum(e
, nvar
, 0);
3699 /* Initial silly implementation */
3700 void eor(evalue
*e1
, evalue
*res
)
3706 evalue_set_si(&mone
, -1, 1);
3708 evalue_copy(&E
, res
);
3714 free_evalue_refs(&E
);
3715 free_evalue_refs(&mone
);
3718 /* computes denominator of polynomial evalue
3719 * d should point to a value initialized to 1
3721 void evalue_denom(const evalue
*e
, Value
*d
)
3725 if (value_notzero_p(e
->d
)) {
3726 value_lcm(*d
, *d
, e
->d
);
3729 assert(e
->x
.p
->type
== polynomial
||
3730 e
->x
.p
->type
== fractional
||
3731 e
->x
.p
->type
== flooring
);
3732 offset
= type_offset(e
->x
.p
);
3733 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3734 evalue_denom(&e
->x
.p
->arr
[i
], d
);
3737 /* Divides the evalue e by the integer n */
3738 void evalue_div(evalue
*e
, Value n
)
3742 if (value_one_p(n
) || EVALUE_IS_ZERO(*e
))
3745 if (value_notzero_p(e
->d
)) {
3748 value_multiply(e
->d
, e
->d
, n
);
3749 value_gcd(gc
, e
->x
.n
, e
->d
);
3750 if (value_notone_p(gc
)) {
3751 value_division(e
->d
, e
->d
, gc
);
3752 value_division(e
->x
.n
, e
->x
.n
, gc
);
3757 if (e
->x
.p
->type
== partition
) {
3758 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3759 evalue_div(&e
->x
.p
->arr
[2*i
+1], n
);
3762 offset
= type_offset(e
->x
.p
);
3763 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3764 evalue_div(&e
->x
.p
->arr
[i
], n
);
3767 /* Multiplies the evalue e by the integer n */
3768 void evalue_mul(evalue
*e
, Value n
)
3772 if (value_one_p(n
) || EVALUE_IS_ZERO(*e
))
3775 if (value_notzero_p(e
->d
)) {
3778 value_multiply(e
->x
.n
, e
->x
.n
, n
);
3779 value_gcd(gc
, e
->x
.n
, e
->d
);
3780 if (value_notone_p(gc
)) {
3781 value_division(e
->d
, e
->d
, gc
);
3782 value_division(e
->x
.n
, e
->x
.n
, gc
);
3787 if (e
->x
.p
->type
== partition
) {
3788 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3789 evalue_mul(&e
->x
.p
->arr
[2*i
+1], n
);
3792 offset
= type_offset(e
->x
.p
);
3793 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3794 evalue_mul(&e
->x
.p
->arr
[i
], n
);
3797 /* Multiplies the evalue e by the n/d */
3798 void evalue_mul_div(evalue
*e
, Value n
, Value d
)
3802 if ((value_one_p(n
) && value_one_p(d
)) || EVALUE_IS_ZERO(*e
))
3805 if (value_notzero_p(e
->d
)) {
3808 value_multiply(e
->x
.n
, e
->x
.n
, n
);
3809 value_multiply(e
->d
, e
->d
, d
);
3810 value_gcd(gc
, e
->x
.n
, e
->d
);
3811 if (value_notone_p(gc
)) {
3812 value_division(e
->d
, e
->d
, gc
);
3813 value_division(e
->x
.n
, e
->x
.n
, gc
);
3818 if (e
->x
.p
->type
== partition
) {
3819 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3820 evalue_mul_div(&e
->x
.p
->arr
[2*i
+1], n
, d
);
3823 offset
= type_offset(e
->x
.p
);
3824 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3825 evalue_mul_div(&e
->x
.p
->arr
[i
], n
, d
);
3828 void evalue_negate(evalue
*e
)
3832 if (value_notzero_p(e
->d
)) {
3833 value_oppose(e
->x
.n
, e
->x
.n
);
3836 if (e
->x
.p
->type
== partition
) {
3837 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3838 evalue_negate(&e
->x
.p
->arr
[2*i
+1]);
3841 offset
= type_offset(e
->x
.p
);
3842 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3843 evalue_negate(&e
->x
.p
->arr
[i
]);
3846 void evalue_add_constant(evalue
*e
, const Value cst
)
3850 if (value_zero_p(e
->d
)) {
3851 if (e
->x
.p
->type
== partition
) {
3852 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3853 evalue_add_constant(&e
->x
.p
->arr
[2*i
+1], cst
);
3856 if (e
->x
.p
->type
== relation
) {
3857 for (i
= 1; i
< e
->x
.p
->size
; ++i
)
3858 evalue_add_constant(&e
->x
.p
->arr
[i
], cst
);
3862 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)];
3863 } while (value_zero_p(e
->d
));
3865 value_addmul(e
->x
.n
, cst
, e
->d
);
3868 static void evalue_frac2polynomial_r(evalue
*e
, int *signs
, int sign
, int in_frac
)
3873 int sign_odd
= sign
;
3875 if (value_notzero_p(e
->d
)) {
3876 if (in_frac
&& sign
* value_sign(e
->x
.n
) < 0) {
3877 value_set_si(e
->x
.n
, 0);
3878 value_set_si(e
->d
, 1);
3883 if (e
->x
.p
->type
== relation
) {
3884 for (i
= e
->x
.p
->size
-1; i
>= 1; --i
)
3885 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
, sign
, in_frac
);
3889 if (e
->x
.p
->type
== polynomial
)
3890 sign_odd
*= signs
[e
->x
.p
->pos
-1];
3891 offset
= type_offset(e
->x
.p
);
3892 evalue_frac2polynomial_r(&e
->x
.p
->arr
[offset
], signs
, sign
, in_frac
);
3893 in_frac
|= e
->x
.p
->type
== fractional
;
3894 for (i
= e
->x
.p
->size
-1; i
> offset
; --i
)
3895 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
,
3896 (i
- offset
) % 2 ? sign_odd
: sign
, in_frac
);
3898 if (e
->x
.p
->type
!= fractional
)
3901 /* replace { a/m } by (m-1)/m if sign != 0
3902 * and by (m-1)/(2m) if sign == 0
3906 evalue_denom(&e
->x
.p
->arr
[0], &d
);
3907 free_evalue_refs(&e
->x
.p
->arr
[0]);
3908 value_init(e
->x
.p
->arr
[0].d
);
3909 value_init(e
->x
.p
->arr
[0].x
.n
);
3911 value_addto(e
->x
.p
->arr
[0].d
, d
, d
);
3913 value_assign(e
->x
.p
->arr
[0].d
, d
);
3914 value_decrement(e
->x
.p
->arr
[0].x
.n
, d
);
3918 reorder_terms_about(p
, &p
->arr
[0]);
3924 /* Approximate the evalue in fractional representation by a polynomial.
3925 * If sign > 0, the result is an upper bound;
3926 * if sign < 0, the result is a lower bound;
3927 * if sign = 0, the result is an intermediate approximation.
3929 void evalue_frac2polynomial(evalue
*e
, int sign
, unsigned MaxRays
)
3934 if (value_notzero_p(e
->d
))
3936 assert(e
->x
.p
->type
== partition
);
3937 /* make sure all variables in the domains have a fixed sign */
3939 evalue_split_domains_into_orthants(e
, MaxRays
);
3940 if (EVALUE_IS_ZERO(*e
))
3944 assert(e
->x
.p
->size
>= 2);
3945 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3947 signs
= alloca(sizeof(int) * dim
);
3950 for (i
= 0; i
< dim
; ++i
)
3952 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3954 domain_signs(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), signs
);
3955 evalue_frac2polynomial_r(&e
->x
.p
->arr
[2*i
+1], signs
, sign
, 0);
3959 /* Split the domains of e (which is assumed to be a partition)
3960 * such that each resulting domain lies entirely in one orthant.
3962 void evalue_split_domains_into_orthants(evalue
*e
, unsigned MaxRays
)
3965 assert(value_zero_p(e
->d
));
3966 assert(e
->x
.p
->type
== partition
);
3967 assert(e
->x
.p
->size
>= 2);
3968 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3970 for (i
= 0; i
< dim
; ++i
) {
3973 C
= Matrix_Alloc(1, 1 + dim
+ 1);
3974 value_set_si(C
->p
[0][0], 1);
3975 value_init(split
.d
);
3976 value_set_si(split
.d
, 0);
3977 split
.x
.p
= new_enode(partition
, 4, dim
);
3978 value_set_si(C
->p
[0][1+i
], 1);
3979 C2
= Matrix_Copy(C
);
3980 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[0], Constraints2Polyhedron(C2
, MaxRays
));
3982 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
3983 value_set_si(C
->p
[0][1+i
], -1);
3984 value_set_si(C
->p
[0][1+dim
], -1);
3985 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[2], Constraints2Polyhedron(C
, MaxRays
));
3986 evalue_set_si(&split
.x
.p
->arr
[3], 1, 1);
3988 free_evalue_refs(&split
);
3994 static evalue
*find_fractional_with_max_periods(evalue
*e
, Polyhedron
*D
,
3997 Value
*min
, Value
*max
)
4004 if (value_notzero_p(e
->d
))
4007 if (e
->x
.p
->type
== fractional
) {
4012 I
= polynomial_projection(e
->x
.p
, D
, &d
, &T
);
4013 bounded
= line_minmax(I
, min
, max
); /* frees I */
4017 value_set_si(mp
, max_periods
);
4018 mpz_fdiv_q(*min
, *min
, d
);
4019 mpz_fdiv_q(*max
, *max
, d
);
4020 value_assign(T
->p
[1][D
->Dimension
], d
);
4021 value_subtract(d
, *max
, *min
);
4022 if (value_ge(d
, mp
))
4025 f
= evalue_dup(&e
->x
.p
->arr
[0]);
4036 for (i
= type_offset(e
->x
.p
); i
< e
->x
.p
->size
; ++i
)
4037 if ((f
= find_fractional_with_max_periods(&e
->x
.p
->arr
[i
], D
, max_periods
,
4044 static void replace_fract_by_affine(evalue
*e
, evalue
*f
, Value val
)
4048 if (value_notzero_p(e
->d
))
4051 offset
= type_offset(e
->x
.p
);
4052 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
4053 replace_fract_by_affine(&e
->x
.p
->arr
[i
], f
, val
);
4055 if (e
->x
.p
->type
!= fractional
)
4058 if (!eequal(&e
->x
.p
->arr
[0], f
))
4061 replace_by_affine(e
, val
);
4064 /* Look for fractional parts that can be removed by splitting the corresponding
4065 * domain into at most max_periods parts.
4066 * We use a very simply strategy that looks for the first fractional part
4067 * that satisfies the condition, performs the split and then continues
4068 * looking for other fractional parts in the split domains until no
4069 * such fractional part can be found anymore.
4071 void evalue_split_periods(evalue
*e
, int max_periods
, unsigned int MaxRays
)
4078 if (EVALUE_IS_ZERO(*e
))
4080 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
4082 "WARNING: evalue_split_periods called on incorrect evalue type\n");
4090 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
4095 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
4097 f
= find_fractional_with_max_periods(&e
->x
.p
->arr
[2*i
+1], D
, max_periods
,
4102 M
= Matrix_Alloc(2, 2+D
->Dimension
);
4104 value_subtract(d
, max
, min
);
4105 n
= VALUE_TO_INT(d
)+1;
4107 value_set_si(M
->p
[0][0], 1);
4108 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
4109 value_multiply(d
, max
, T
->p
[1][D
->Dimension
]);
4110 value_subtract(M
->p
[0][1+D
->Dimension
], M
->p
[0][1+D
->Dimension
], d
);
4111 value_set_si(d
, -1);
4112 value_set_si(M
->p
[1][0], 1);
4113 Vector_Scale(T
->p
[0], M
->p
[1]+1, d
, D
->Dimension
+1);
4114 value_addmul(M
->p
[1][1+D
->Dimension
], max
, T
->p
[1][D
->Dimension
]);
4115 value_addto(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
],
4116 T
->p
[1][D
->Dimension
]);
4117 value_decrement(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
]);
4119 p
= new_enode(partition
, e
->x
.p
->size
+ (n
-1)*2, e
->x
.p
->pos
);
4120 for (j
= 0; j
< 2*i
; ++j
) {
4121 value_clear(p
->arr
[j
].d
);
4122 p
->arr
[j
] = e
->x
.p
->arr
[j
];
4124 for (j
= 2*i
+2; j
< e
->x
.p
->size
; ++j
) {
4125 value_clear(p
->arr
[j
+2*(n
-1)].d
);
4126 p
->arr
[j
+2*(n
-1)] = e
->x
.p
->arr
[j
];
4128 for (j
= n
-1; j
>= 0; --j
) {
4130 value_clear(p
->arr
[2*i
+1].d
);
4131 p
->arr
[2*i
+1] = e
->x
.p
->arr
[2*i
+1];
4133 evalue_copy(&p
->arr
[2*(i
+j
)+1], &e
->x
.p
->arr
[2*i
+1]);
4135 value_subtract(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
],
4136 T
->p
[1][D
->Dimension
]);
4137 value_addto(M
->p
[0][1+D
->Dimension
], M
->p
[0][1+D
->Dimension
],
4138 T
->p
[1][D
->Dimension
]);
4140 replace_fract_by_affine(&p
->arr
[2*(i
+j
)+1], f
, max
);
4141 E
= DomainAddConstraints(D
, M
, MaxRays
);
4142 EVALUE_SET_DOMAIN(p
->arr
[2*(i
+j
)], E
);
4143 if (evalue_range_reduction_in_domain(&p
->arr
[2*(i
+j
)+1], E
))
4144 reduce_evalue(&p
->arr
[2*(i
+j
)+1]);
4145 value_decrement(max
, max
);
4147 value_clear(e
->x
.p
->arr
[2*i
].d
);
4162 void evalue_extract_affine(const evalue
*e
, Value
*coeff
, Value
*cst
, Value
*d
)
4164 value_set_si(*d
, 1);
4166 for ( ; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[0]) {
4168 assert(e
->x
.p
->type
== polynomial
);
4169 assert(e
->x
.p
->size
== 2);
4170 c
= &e
->x
.p
->arr
[1];
4171 value_multiply(coeff
[e
->x
.p
->pos
-1], *d
, c
->x
.n
);
4172 value_division(coeff
[e
->x
.p
->pos
-1], coeff
[e
->x
.p
->pos
-1], c
->d
);
4174 value_multiply(*cst
, *d
, e
->x
.n
);
4175 value_division(*cst
, *cst
, e
->d
);
4178 /* returns an evalue that corresponds to
4182 static evalue
*term(int param
, Value c
, Value den
)
4184 evalue
*EP
= ALLOC(evalue
);
4186 value_set_si(EP
->d
,0);
4187 EP
->x
.p
= new_enode(polynomial
, 2, param
+ 1);
4188 evalue_set_si(&EP
->x
.p
->arr
[0], 0, 1);
4189 value_init(EP
->x
.p
->arr
[1].x
.n
);
4190 value_assign(EP
->x
.p
->arr
[1].d
, den
);
4191 value_assign(EP
->x
.p
->arr
[1].x
.n
, c
);
4195 evalue
*affine2evalue(Value
*coeff
, Value denom
, int nvar
)
4198 evalue
*E
= ALLOC(evalue
);
4200 evalue_set(E
, coeff
[nvar
], denom
);
4201 for (i
= 0; i
< nvar
; ++i
) {
4203 if (value_zero_p(coeff
[i
]))
4205 t
= term(i
, coeff
[i
], denom
);
4212 void evalue_substitute(evalue
*e
, evalue
**subs
)
4218 if (value_notzero_p(e
->d
))
4222 assert(p
->type
!= partition
);
4224 for (i
= 0; i
< p
->size
; ++i
)
4225 evalue_substitute(&p
->arr
[i
], subs
);
4227 if (p
->type
== polynomial
)
4232 value_set_si(v
->d
, 0);
4233 v
->x
.p
= new_enode(p
->type
, 3, -1);
4234 value_clear(v
->x
.p
->arr
[0].d
);
4235 v
->x
.p
->arr
[0] = p
->arr
[0];
4236 evalue_set_si(&v
->x
.p
->arr
[1], 0, 1);
4237 evalue_set_si(&v
->x
.p
->arr
[2], 1, 1);
4240 offset
= type_offset(p
);
4242 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
4243 emul(v
, &p
->arr
[i
]);
4244 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
4245 free_evalue_refs(&(p
->arr
[i
]));
4248 if (p
->type
!= polynomial
)
4252 *e
= p
->arr
[offset
];
4256 /* evalue e is given in terms of "new" parameter; CP maps the new
4257 * parameters back to the old parameters.
4258 * Transforms e such that it refers back to the old parameters.
4260 void evalue_backsubstitute(evalue
*e
, Matrix
*CP
, unsigned MaxRays
)
4267 unsigned nparam
= CP
->NbColumns
-1;
4270 if (EVALUE_IS_ZERO(*e
))
4273 assert(value_zero_p(e
->d
));
4275 assert(p
->type
== partition
);
4277 inv
= left_inverse(CP
, &eq
);
4278 subs
= ALLOCN(evalue
*, nparam
);
4279 for (i
= 0; i
< nparam
; ++i
)
4280 subs
[i
] = affine2evalue(inv
->p
[i
], inv
->p
[nparam
][inv
->NbColumns
-1],
4283 CEq
= Constraints2Polyhedron(eq
, MaxRays
);
4284 addeliminatedparams_partition(p
, inv
, CEq
, inv
->NbColumns
-1, MaxRays
);
4285 Polyhedron_Free(CEq
);
4287 for (i
= 0; i
< p
->size
/2; ++i
)
4288 evalue_substitute(&p
->arr
[2*i
+1], subs
);
4290 for (i
= 0; i
< nparam
; ++i
)
4291 evalue_free(subs
[i
]);
4299 * \sum_{i=0}^n c_i/d X^i
4301 * where d is the last element in the vector c.
4303 evalue
*evalue_polynomial(Vector
*c
, const evalue
* X
)
4305 unsigned dim
= c
->Size
-2;
4307 evalue
*EP
= ALLOC(evalue
);
4312 if (EVALUE_IS_ZERO(*X
) || dim
== 0) {
4313 evalue_set(EP
, c
->p
[0], c
->p
[dim
+1]);
4314 reduce_constant(EP
);
4318 evalue_set(EP
, c
->p
[dim
], c
->p
[dim
+1]);
4321 evalue_set(&EC
, c
->p
[dim
], c
->p
[dim
+1]);
4323 for (i
= dim
-1; i
>= 0; --i
) {
4325 value_assign(EC
.x
.n
, c
->p
[i
]);
4328 free_evalue_refs(&EC
);
4332 /* Create an evalue from an array of pairs of domains and evalues. */
4333 evalue
*evalue_from_section_array(struct evalue_section
*s
, int n
)
4338 res
= ALLOC(evalue
);
4342 evalue_set_si(res
, 0, 1);
4344 value_set_si(res
->d
, 0);
4345 res
->x
.p
= new_enode(partition
, 2*n
, s
[0].D
->Dimension
);
4346 for (i
= 0; i
< n
; ++i
) {
4347 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
], s
[i
].D
);
4348 value_clear(res
->x
.p
->arr
[2*i
+1].d
);
4349 res
->x
.p
->arr
[2*i
+1] = *s
[i
].E
;