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
, p
->x
.p
->arr
[1].d
, d
);
313 static void poly_denom(evalue
*p
, Value
*d
)
315 poly_denom_not_constant(&p
, d
);
316 value_lcm(*d
, p
->d
, 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 Gcd(f
->d
, f
->x
.n
, &g
);
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 Gcd(pp
->d
, pp
->x
.n
, &r
);
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 Gcd(pp
->d
, pp
->x
.n
, &twice
);
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
, char **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
, char **pname
)
983 print_evalue_r(DST
, e
, pname
);
984 if (value_notzero_p(e
->d
))
988 void print_enode(FILE *DST
,enode
*p
,char **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 **names
= pname
;
1056 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
1057 if (!pname
|| p
->pos
< maxdim
) {
1058 NALLOC(names
, maxdim
);
1059 for (i
= 0; i
< p
->pos
; ++i
) {
1061 names
[i
] = pname
[i
];
1063 NALLOC(names
[i
], 10);
1064 snprintf(names
[i
], 10, "%c", 'P'+i
);
1067 for ( ; i
< maxdim
; ++i
) {
1068 NALLOC(names
[i
], 10);
1069 snprintf(names
[i
], 10, "_p%d", i
);
1073 for (i
=0; i
<p
->size
/2; i
++) {
1074 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
1075 print_evalue_r(DST
, &p
->arr
[2*i
+1], names
);
1078 if (!pname
|| p
->pos
< maxdim
) {
1079 for (i
= pname
? p
->pos
: 0; i
< maxdim
; ++i
)
1092 static void eadd_rev(const evalue
*e1
, evalue
*res
)
1096 evalue_copy(&ev
, e1
);
1098 free_evalue_refs(res
);
1102 static void eadd_rev_cst(const evalue
*e1
, evalue
*res
)
1106 evalue_copy(&ev
, e1
);
1107 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
1108 free_evalue_refs(res
);
1112 static int is_zero_on(evalue
*e
, Polyhedron
*D
)
1117 tmp
.x
.p
= new_enode(partition
, 2, D
->Dimension
);
1118 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Domain_Copy(D
));
1119 evalue_copy(&tmp
.x
.p
->arr
[1], e
);
1120 reduce_evalue(&tmp
);
1121 is_zero
= EVALUE_IS_ZERO(tmp
);
1122 free_evalue_refs(&tmp
);
1126 struct section
{ Polyhedron
* D
; evalue E
; };
1128 void eadd_partitions(const evalue
*e1
, evalue
*res
)
1133 s
= (struct section
*)
1134 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
1135 sizeof(struct section
));
1137 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1138 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1139 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1142 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1143 assert(res
->x
.p
->size
>= 2);
1144 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1145 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
1147 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
1149 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1158 /* See if we can extend one of the domains in res to cover fd */
1159 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1160 if (is_zero_on(&res
->x
.p
->arr
[2*i
+1], fd
))
1162 if (i
< res
->x
.p
->size
/2) {
1163 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
1164 DomainConcat(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
])));
1167 value_init(s
[n
].E
.d
);
1168 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
1172 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1173 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
1174 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1176 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1177 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1183 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1184 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1186 value_init(s
[n
].E
.d
);
1187 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1188 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1189 if (!emptyQ(fd
) && is_zero_on(&e1
->x
.p
->arr
[2*j
+1], fd
)) {
1190 d
= DomainConcat(fd
, d
);
1191 fd
= Empty_Polyhedron(fd
->Dimension
);
1197 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1201 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1204 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1205 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1206 value_clear(res
->x
.p
->arr
[2*i
].d
);
1211 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1212 for (j
= 0; j
< n
; ++j
) {
1213 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1214 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1215 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1216 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1222 static void explicit_complement(evalue
*res
)
1224 enode
*rel
= new_enode(relation
, 3, 0);
1226 value_clear(rel
->arr
[0].d
);
1227 rel
->arr
[0] = res
->x
.p
->arr
[0];
1228 value_clear(rel
->arr
[1].d
);
1229 rel
->arr
[1] = res
->x
.p
->arr
[1];
1230 value_set_si(rel
->arr
[2].d
, 1);
1231 value_init(rel
->arr
[2].x
.n
);
1232 value_set_si(rel
->arr
[2].x
.n
, 0);
1237 void eadd(const evalue
*e1
, evalue
*res
)
1240 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1241 /* Add two rational numbers */
1247 value_multiply(m1
,e1
->x
.n
,res
->d
);
1248 value_multiply(m2
,res
->x
.n
,e1
->d
);
1249 value_addto(res
->x
.n
,m1
,m2
);
1250 value_multiply(res
->d
,e1
->d
,res
->d
);
1251 Gcd(res
->x
.n
,res
->d
,&g
);
1252 if (value_notone_p(g
)) {
1253 value_division(res
->d
,res
->d
,g
);
1254 value_division(res
->x
.n
,res
->x
.n
,g
);
1256 value_clear(g
); value_clear(m1
); value_clear(m2
);
1259 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1260 switch (res
->x
.p
->type
) {
1262 /* Add the constant to the constant term of a polynomial*/
1263 eadd(e1
, &res
->x
.p
->arr
[0]);
1266 /* Add the constant to all elements of a periodic number */
1267 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1268 eadd(e1
, &res
->x
.p
->arr
[i
]);
1272 fprintf(stderr
, "eadd: cannot add const with vector\n");
1276 eadd(e1
, &res
->x
.p
->arr
[1]);
1279 assert(EVALUE_IS_ZERO(*e1
));
1280 break; /* Do nothing */
1282 /* Create (zero) complement if needed */
1283 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1284 explicit_complement(res
);
1285 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1286 eadd(e1
, &res
->x
.p
->arr
[i
]);
1292 /* add polynomial or periodic to constant
1293 * you have to exchange e1 and res, before doing addition */
1295 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1299 else { // ((e1->d==0) && (res->d==0))
1300 assert(!((e1
->x
.p
->type
== partition
) ^
1301 (res
->x
.p
->type
== partition
)));
1302 if (e1
->x
.p
->type
== partition
) {
1303 eadd_partitions(e1
, res
);
1306 if (e1
->x
.p
->type
== relation
&&
1307 (res
->x
.p
->type
!= relation
||
1308 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1312 if (res
->x
.p
->type
== relation
) {
1313 if (e1
->x
.p
->type
== relation
&&
1314 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1315 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1316 explicit_complement(res
);
1317 for (i
= 1; i
< e1
->x
.p
->size
; ++i
)
1318 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1321 if (res
->x
.p
->size
< 3)
1322 explicit_complement(res
);
1323 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1324 eadd(e1
, &res
->x
.p
->arr
[i
]);
1327 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1328 /* adding to evalues of different type. two cases are possible
1329 * res is periodic and e1 is polynomial, you have to exchange
1330 * e1 and res then to add e1 to the constant term of res */
1331 if (e1
->x
.p
->type
== polynomial
) {
1332 eadd_rev_cst(e1
, res
);
1334 else if (res
->x
.p
->type
== polynomial
) {
1335 /* res is polynomial and e1 is periodic,
1336 add e1 to the constant term of res */
1338 eadd(e1
,&res
->x
.p
->arr
[0]);
1344 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1345 ((res
->x
.p
->type
== fractional
||
1346 res
->x
.p
->type
== flooring
) &&
1347 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1348 /* adding evalues of different position (i.e function of different unknowns
1349 * to case are possible */
1351 switch (res
->x
.p
->type
) {
1354 if (mod_term_smaller(res
, e1
))
1355 eadd(e1
,&res
->x
.p
->arr
[1]);
1357 eadd_rev_cst(e1
, res
);
1359 case polynomial
: // res and e1 are polynomials
1360 // add e1 to the constant term of res
1362 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1363 eadd(e1
,&res
->x
.p
->arr
[0]);
1365 eadd_rev_cst(e1
, res
);
1366 // value_clear(g); value_clear(m1); value_clear(m2);
1368 case periodic
: // res and e1 are pointers to periodic numbers
1369 //add e1 to all elements of res
1371 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1372 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1373 eadd(e1
,&res
->x
.p
->arr
[i
]);
1384 //same type , same pos and same size
1385 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1386 // add any element in e1 to the corresponding element in res
1387 i
= type_offset(res
->x
.p
);
1389 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1390 for (; i
<res
->x
.p
->size
; i
++) {
1391 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1396 /* Sizes are different */
1397 switch(res
->x
.p
->type
) {
1401 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1402 /* new enode and add res to that new node. If you do not do */
1403 /* that, you lose the the upper weight part of e1 ! */
1405 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1408 i
= type_offset(res
->x
.p
);
1410 assert(eequal(&e1
->x
.p
->arr
[0],
1411 &res
->x
.p
->arr
[0]));
1412 for (; i
<e1
->x
.p
->size
; i
++) {
1413 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1420 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1423 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1424 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1425 to add periodicaly elements of e1 to elements of ne, and finaly to
1430 value_init(ex
); value_init(ey
);value_init(ep
);
1433 value_set_si(ex
,e1
->x
.p
->size
);
1434 value_set_si(ey
,res
->x
.p
->size
);
1435 value_assign (ep
,*Lcm(ex
,ey
));
1436 p
=(int)mpz_get_si(ep
);
1437 ne
= (evalue
*) malloc (sizeof(evalue
));
1439 value_set_si( ne
->d
,0);
1441 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1443 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1446 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1449 value_assign(res
->d
, ne
->d
);
1455 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1464 static void emul_rev(const evalue
*e1
, evalue
*res
)
1468 evalue_copy(&ev
, e1
);
1470 free_evalue_refs(res
);
1474 static void emul_poly(const evalue
*e1
, evalue
*res
)
1476 int i
, j
, offset
= type_offset(res
->x
.p
);
1479 int size
= (e1
->x
.p
->size
+ res
->x
.p
->size
- offset
- 1);
1481 p
= new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1483 for (i
= offset
; i
< e1
->x
.p
->size
-1; ++i
)
1484 if (!EVALUE_IS_ZERO(e1
->x
.p
->arr
[i
]))
1487 /* special case pure power */
1488 if (i
== e1
->x
.p
->size
-1) {
1490 value_clear(p
->arr
[0].d
);
1491 p
->arr
[0] = res
->x
.p
->arr
[0];
1493 for (i
= offset
; i
< e1
->x
.p
->size
-1; ++i
)
1494 evalue_set_si(&p
->arr
[i
], 0, 1);
1495 for (i
= offset
; i
< res
->x
.p
->size
; ++i
) {
1496 value_clear(p
->arr
[i
+e1
->x
.p
->size
-offset
-1].d
);
1497 p
->arr
[i
+e1
->x
.p
->size
-offset
-1] = res
->x
.p
->arr
[i
];
1498 emul(&e1
->x
.p
->arr
[e1
->x
.p
->size
-1],
1499 &p
->arr
[i
+e1
->x
.p
->size
-offset
-1]);
1507 value_set_si(tmp
.d
,0);
1510 evalue_copy(&p
->arr
[0], &e1
->x
.p
->arr
[0]);
1511 for (i
= offset
; i
< e1
->x
.p
->size
; i
++) {
1512 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1513 emul(&res
->x
.p
->arr
[offset
], &tmp
.x
.p
->arr
[i
]);
1516 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1517 for (i
= offset
+1; i
<res
->x
.p
->size
; i
++)
1518 for (j
= offset
; j
<e1
->x
.p
->size
; j
++) {
1521 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1522 emul(&res
->x
.p
->arr
[i
], &ev
);
1523 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-offset
]);
1524 free_evalue_refs(&ev
);
1526 free_evalue_refs(res
);
1530 void emul_partitions(const evalue
*e1
, evalue
*res
)
1535 s
= (struct section
*)
1536 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1537 sizeof(struct section
));
1539 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1540 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1541 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1544 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1545 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1546 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1547 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1553 /* This code is only needed because the partitions
1554 are not true partitions.
1556 for (k
= 0; k
< n
; ++k
) {
1557 if (DomainIncludes(s
[k
].D
, d
))
1559 if (DomainIncludes(d
, s
[k
].D
)) {
1560 Domain_Free(s
[k
].D
);
1561 free_evalue_refs(&s
[k
].E
);
1572 value_init(s
[n
].E
.d
);
1573 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1574 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1578 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1579 value_clear(res
->x
.p
->arr
[2*i
].d
);
1580 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1585 evalue_set_si(res
, 0, 1);
1587 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1588 for (j
= 0; j
< n
; ++j
) {
1589 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1590 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1591 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1592 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1599 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1601 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1602 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1603 * evalues is not treated here */
1605 void emul(const evalue
*e1
, evalue
*res
)
1609 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1610 fprintf(stderr
, "emul: do not proced on evector type !\n");
1614 if (EVALUE_IS_ZERO(*res
))
1617 if (EVALUE_IS_ONE(*e1
))
1620 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1621 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1622 emul_partitions(e1
, res
);
1625 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1626 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1627 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1629 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1630 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1631 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1632 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3) {
1633 free_evalue_refs(&res
->x
.p
->arr
[2]);
1636 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1637 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1640 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1641 emul(e1
, &res
->x
.p
->arr
[i
]);
1643 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1644 switch(e1
->x
.p
->type
) {
1646 switch(res
->x
.p
->type
) {
1648 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1649 /* Product of two polynomials of the same variable */
1654 /* Product of two polynomials of different variables */
1656 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1657 for( i
=0; i
<res
->x
.p
->size
; i
++)
1658 emul(e1
, &res
->x
.p
->arr
[i
]);
1667 /* Product of a polynomial and a periodic or fractional */
1674 switch(res
->x
.p
->type
) {
1676 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1677 /* Product of two periodics of the same parameter and period */
1679 for(i
=0; i
<res
->x
.p
->size
;i
++)
1680 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1685 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1686 /* Product of two periodics of the same parameter and different periods */
1690 value_init(x
); value_init(y
);value_init(z
);
1693 value_set_si(x
,e1
->x
.p
->size
);
1694 value_set_si(y
,res
->x
.p
->size
);
1695 value_assign (z
,*Lcm(x
,y
));
1696 lcm
=(int)mpz_get_si(z
);
1697 newp
= (evalue
*) malloc (sizeof(evalue
));
1698 value_init(newp
->d
);
1699 value_set_si( newp
->d
,0);
1700 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1701 for(i
=0;i
<lcm
;i
++) {
1702 evalue_copy(&newp
->x
.p
->arr
[i
],
1703 &res
->x
.p
->arr
[i
%iy
]);
1706 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1708 value_assign(res
->d
,newp
->d
);
1711 value_clear(x
); value_clear(y
);value_clear(z
);
1715 /* Product of two periodics of different parameters */
1717 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1718 for(i
=0; i
<res
->x
.p
->size
; i
++)
1719 emul(e1
, &(res
->x
.p
->arr
[i
]));
1727 /* Product of a periodic and a polynomial */
1729 for(i
=0; i
<res
->x
.p
->size
; i
++)
1730 emul(e1
, &(res
->x
.p
->arr
[i
]));
1737 switch(res
->x
.p
->type
) {
1739 for(i
=0; i
<res
->x
.p
->size
; i
++)
1740 emul(e1
, &(res
->x
.p
->arr
[i
]));
1747 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1748 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1749 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1752 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1753 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1758 value_set_si(d
.x
.n
, 1);
1759 /* { x }^2 == { x }/2 */
1760 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1761 assert(e1
->x
.p
->size
== 3);
1762 assert(res
->x
.p
->size
== 3);
1764 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1766 eadd(&res
->x
.p
->arr
[1], &tmp
);
1767 emul(&e1
->x
.p
->arr
[2], &tmp
);
1768 emul(&e1
->x
.p
->arr
[1], res
);
1769 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1770 free_evalue_refs(&tmp
);
1775 if(mod_term_smaller(res
, e1
))
1776 for(i
=1; i
<res
->x
.p
->size
; i
++)
1777 emul(e1
, &(res
->x
.p
->arr
[i
]));
1792 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1793 /* Product of two rational numbers */
1797 value_multiply(res
->d
,e1
->d
,res
->d
);
1798 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1799 Gcd(res
->x
.n
, res
->d
,&g
);
1800 if (value_notone_p(g
)) {
1801 value_division(res
->d
,res
->d
,g
);
1802 value_division(res
->x
.n
,res
->x
.n
,g
);
1808 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1809 /* Product of an expression (polynomial or peririodic) and a rational number */
1815 /* Product of a rationel number and an expression (polynomial or peririodic) */
1817 i
= type_offset(res
->x
.p
);
1818 for (; i
<res
->x
.p
->size
; i
++)
1819 emul(e1
, &res
->x
.p
->arr
[i
]);
1829 /* Frees mask content ! */
1830 void emask(evalue
*mask
, evalue
*res
) {
1837 if (EVALUE_IS_ZERO(*res
)) {
1838 free_evalue_refs(mask
);
1842 assert(value_zero_p(mask
->d
));
1843 assert(mask
->x
.p
->type
== partition
);
1844 assert(value_zero_p(res
->d
));
1845 assert(res
->x
.p
->type
== partition
);
1846 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1847 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1848 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1849 pos
= res
->x
.p
->pos
;
1851 s
= (struct section
*)
1852 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1853 sizeof(struct section
));
1857 evalue_set_si(&mone
, -1, 1);
1860 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1861 assert(mask
->x
.p
->size
>= 2);
1862 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1863 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1865 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1867 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1876 value_init(s
[n
].E
.d
);
1877 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1881 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1882 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1885 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1886 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1887 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1888 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1890 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1891 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1897 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1898 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1900 value_init(s
[n
].E
.d
);
1901 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1902 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1908 /* Just ignore; this may have been previously masked off */
1910 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1914 free_evalue_refs(&mone
);
1915 free_evalue_refs(mask
);
1916 free_evalue_refs(res
);
1919 evalue_set_si(res
, 0, 1);
1921 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1922 for (j
= 0; j
< n
; ++j
) {
1923 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1924 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1925 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1932 void evalue_copy(evalue
*dst
, const evalue
*src
)
1934 value_assign(dst
->d
, src
->d
);
1935 if(value_notzero_p(src
->d
)) {
1936 value_init(dst
->x
.n
);
1937 value_assign(dst
->x
.n
, src
->x
.n
);
1939 dst
->x
.p
= ecopy(src
->x
.p
);
1942 evalue
*evalue_dup(evalue
*e
)
1944 evalue
*res
= ALLOC(evalue
);
1946 evalue_copy(res
, e
);
1950 enode
*new_enode(enode_type type
,int size
,int pos
) {
1956 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1959 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1963 for(i
=0; i
<size
; i
++) {
1964 value_init(res
->arr
[i
].d
);
1965 value_set_si(res
->arr
[i
].d
,0);
1966 res
->arr
[i
].x
.p
= 0;
1971 enode
*ecopy(enode
*e
) {
1976 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1977 for(i
=0;i
<e
->size
;++i
) {
1978 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1979 if(value_zero_p(res
->arr
[i
].d
))
1980 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1981 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1982 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1984 value_init(res
->arr
[i
].x
.n
);
1985 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1991 int ecmp(const evalue
*e1
, const evalue
*e2
)
1997 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
2001 value_multiply(m
, e1
->x
.n
, e2
->d
);
2002 value_multiply(m2
, e2
->x
.n
, e1
->d
);
2004 if (value_lt(m
, m2
))
2006 else if (value_gt(m
, m2
))
2016 if (value_notzero_p(e1
->d
))
2018 if (value_notzero_p(e2
->d
))
2024 if (p1
->type
!= p2
->type
)
2025 return p1
->type
- p2
->type
;
2026 if (p1
->pos
!= p2
->pos
)
2027 return p1
->pos
- p2
->pos
;
2028 if (p1
->size
!= p2
->size
)
2029 return p1
->size
- p2
->size
;
2031 for (i
= p1
->size
-1; i
>= 0; --i
)
2032 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
2038 int eequal(const evalue
*e1
, const evalue
*e2
)
2043 if (value_ne(e1
->d
,e2
->d
))
2046 /* e1->d == e2->d */
2047 if (value_notzero_p(e1
->d
)) {
2048 if (value_ne(e1
->x
.n
,e2
->x
.n
))
2051 /* e1->d == e2->d != 0 AND e1->n == e2->n */
2055 /* e1->d == e2->d == 0 */
2058 if (p1
->type
!= p2
->type
) return 0;
2059 if (p1
->size
!= p2
->size
) return 0;
2060 if (p1
->pos
!= p2
->pos
) return 0;
2061 for (i
=0; i
<p1
->size
; i
++)
2062 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
2067 void free_evalue_refs(evalue
*e
) {
2072 if (EVALUE_IS_DOMAIN(*e
)) {
2073 Domain_Free(EVALUE_DOMAIN(*e
));
2076 } else if (value_pos_p(e
->d
)) {
2078 /* 'e' stores a constant */
2080 value_clear(e
->x
.n
);
2083 assert(value_zero_p(e
->d
));
2086 if (!p
) return; /* null pointer */
2087 for (i
=0; i
<p
->size
; i
++) {
2088 free_evalue_refs(&(p
->arr
[i
]));
2092 } /* free_evalue_refs */
2094 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
2095 Vector
* val
, evalue
*res
)
2097 unsigned nparam
= periods
->Size
;
2100 double d
= compute_evalue(e
, val
->p
);
2101 d
*= VALUE_TO_DOUBLE(m
);
2106 value_assign(res
->d
, m
);
2107 value_init(res
->x
.n
);
2108 value_set_double(res
->x
.n
, d
);
2109 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
2112 if (value_one_p(periods
->p
[p
]))
2113 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
2118 value_assign(tmp
, periods
->p
[p
]);
2119 value_set_si(res
->d
, 0);
2120 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
2122 value_decrement(tmp
, tmp
);
2123 value_assign(val
->p
[p
], tmp
);
2124 mod2table_r(e
, periods
, m
, p
+1, val
,
2125 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
2126 } while (value_pos_p(tmp
));
2132 static void rel2table(evalue
*e
, int zero
)
2134 if (value_pos_p(e
->d
)) {
2135 if (value_zero_p(e
->x
.n
) == zero
)
2136 value_set_si(e
->x
.n
, 1);
2138 value_set_si(e
->x
.n
, 0);
2139 value_set_si(e
->d
, 1);
2142 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
2143 rel2table(&e
->x
.p
->arr
[i
], zero
);
2147 void evalue_mod2table(evalue
*e
, int nparam
)
2152 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2155 for (i
=0; i
<p
->size
; i
++) {
2156 evalue_mod2table(&(p
->arr
[i
]), nparam
);
2158 if (p
->type
== relation
) {
2163 evalue_copy(©
, &p
->arr
[0]);
2165 rel2table(&p
->arr
[0], 1);
2166 emul(&p
->arr
[0], &p
->arr
[1]);
2168 rel2table(©
, 0);
2169 emul(©
, &p
->arr
[2]);
2170 eadd(&p
->arr
[2], &p
->arr
[1]);
2171 free_evalue_refs(&p
->arr
[2]);
2172 free_evalue_refs(©
);
2174 free_evalue_refs(&p
->arr
[0]);
2178 } else if (p
->type
== fractional
) {
2179 Vector
*periods
= Vector_Alloc(nparam
);
2180 Vector
*val
= Vector_Alloc(nparam
);
2186 value_set_si(tmp
, 1);
2187 Vector_Set(periods
->p
, 1, nparam
);
2188 Vector_Set(val
->p
, 0, nparam
);
2189 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2192 assert(p
->type
== polynomial
);
2193 assert(p
->size
== 2);
2194 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2195 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
2197 value_lcm(tmp
, ev
->d
, &tmp
);
2199 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2202 evalue_set_si(&res
, 0, 1);
2203 /* Compute the polynomial using Horner's rule */
2204 for (i
=p
->size
-1;i
>1;i
--) {
2205 eadd(&p
->arr
[i
], &res
);
2208 eadd(&p
->arr
[1], &res
);
2210 free_evalue_refs(e
);
2211 free_evalue_refs(&EP
);
2216 Vector_Free(periods
);
2218 } /* evalue_mod2table */
2220 /********************************************************/
2221 /* function in domain */
2222 /* check if the parameters in list_args */
2223 /* verifies the constraints of Domain P */
2224 /********************************************************/
2225 int in_domain(Polyhedron
*P
, Value
*list_args
)
2228 Value v
; /* value of the constraint of a row when
2229 parameters are instantiated*/
2233 for (row
= 0; row
< P
->NbConstraints
; row
++) {
2234 Inner_Product(P
->Constraint
[row
]+1, list_args
, P
->Dimension
, &v
);
2235 value_addto(v
, v
, P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2236 if (value_neg_p(v
) ||
2237 value_zero_p(P
->Constraint
[row
][0]) && value_notzero_p(v
)) {
2244 return in
|| (P
->next
&& in_domain(P
->next
, list_args
));
2247 /****************************************************/
2248 /* function compute enode */
2249 /* compute the value of enode p with parameters */
2250 /* list "list_args */
2251 /* compute the polynomial or the periodic */
2252 /****************************************************/
2254 static double compute_enode(enode
*p
, Value
*list_args
) {
2266 if (p
->type
== polynomial
) {
2268 value_assign(param
,list_args
[p
->pos
-1]);
2270 /* Compute the polynomial using Horner's rule */
2271 for (i
=p
->size
-1;i
>0;i
--) {
2272 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2273 res
*=VALUE_TO_DOUBLE(param
);
2275 res
+=compute_evalue(&p
->arr
[0],list_args
);
2277 else if (p
->type
== fractional
) {
2278 double d
= compute_evalue(&p
->arr
[0], list_args
);
2279 d
-= floor(d
+1e-10);
2281 /* Compute the polynomial using Horner's rule */
2282 for (i
=p
->size
-1;i
>1;i
--) {
2283 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2286 res
+=compute_evalue(&p
->arr
[1],list_args
);
2288 else if (p
->type
== flooring
) {
2289 double d
= compute_evalue(&p
->arr
[0], list_args
);
2292 /* Compute the polynomial using Horner's rule */
2293 for (i
=p
->size
-1;i
>1;i
--) {
2294 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2297 res
+=compute_evalue(&p
->arr
[1],list_args
);
2299 else if (p
->type
== periodic
) {
2300 value_assign(m
,list_args
[p
->pos
-1]);
2302 /* Choose the right element of the periodic */
2303 value_set_si(param
,p
->size
);
2304 value_pmodulus(m
,m
,param
);
2305 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2307 else if (p
->type
== relation
) {
2308 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2309 res
= compute_evalue(&p
->arr
[1], list_args
);
2310 else if (p
->size
> 2)
2311 res
= compute_evalue(&p
->arr
[2], list_args
);
2313 else if (p
->type
== partition
) {
2314 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2315 Value
*vals
= list_args
;
2318 for (i
= 0; i
< dim
; ++i
) {
2319 value_init(vals
[i
]);
2321 value_assign(vals
[i
], list_args
[i
]);
2324 for (i
= 0; i
< p
->size
/2; ++i
)
2325 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2326 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2330 for (i
= 0; i
< dim
; ++i
)
2331 value_clear(vals
[i
]);
2340 } /* compute_enode */
2342 /*************************************************/
2343 /* return the value of Ehrhart Polynomial */
2344 /* It returns a double, because since it is */
2345 /* a recursive function, some intermediate value */
2346 /* might not be integral */
2347 /*************************************************/
2349 double compute_evalue(const evalue
*e
, Value
*list_args
)
2353 if (value_notzero_p(e
->d
)) {
2354 if (value_notone_p(e
->d
))
2355 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2357 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2360 res
= compute_enode(e
->x
.p
,list_args
);
2362 } /* compute_evalue */
2365 /****************************************************/
2366 /* function compute_poly : */
2367 /* Check for the good validity domain */
2368 /* return the number of point in the Polyhedron */
2369 /* in allocated memory */
2370 /* Using the Ehrhart pseudo-polynomial */
2371 /****************************************************/
2372 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2375 /* double d; int i; */
2377 tmp
= (Value
*) malloc (sizeof(Value
));
2378 assert(tmp
!= NULL
);
2380 value_set_si(*tmp
,0);
2383 return(tmp
); /* no ehrhart polynomial */
2384 if(en
->ValidityDomain
) {
2385 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2386 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2391 return(tmp
); /* no Validity Domain */
2393 if(in_domain(en
->ValidityDomain
,list_args
)) {
2395 #ifdef EVAL_EHRHART_DEBUG
2396 Print_Domain(stdout
,en
->ValidityDomain
);
2397 print_evalue(stdout
,&en
->EP
);
2400 /* d = compute_evalue(&en->EP,list_args);
2402 printf("(double)%lf = %d\n", d, i ); */
2403 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2409 value_set_si(*tmp
,0);
2410 return(tmp
); /* no compatible domain with the arguments */
2411 } /* compute_poly */
2413 static evalue
*eval_polynomial(const enode
*p
, int offset
,
2414 evalue
*base
, Value
*values
)
2419 res
= evalue_zero();
2420 for (i
= p
->size
-1; i
> offset
; --i
) {
2421 c
= evalue_eval(&p
->arr
[i
], values
);
2423 free_evalue_refs(c
);
2427 c
= evalue_eval(&p
->arr
[offset
], values
);
2429 free_evalue_refs(c
);
2435 evalue
*evalue_eval(const evalue
*e
, Value
*values
)
2442 if (value_notzero_p(e
->d
)) {
2443 res
= ALLOC(evalue
);
2445 evalue_copy(res
, e
);
2448 switch (e
->x
.p
->type
) {
2450 value_init(param
.x
.n
);
2451 value_assign(param
.x
.n
, values
[e
->x
.p
->pos
-1]);
2452 value_init(param
.d
);
2453 value_set_si(param
.d
, 1);
2455 res
= eval_polynomial(e
->x
.p
, 0, ¶m
, values
);
2456 free_evalue_refs(¶m
);
2459 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2460 mpz_fdiv_r(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2462 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2463 free_evalue_refs(param2
);
2467 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2468 mpz_fdiv_q(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2469 value_set_si(param2
->d
, 1);
2471 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2472 free_evalue_refs(param2
);
2476 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2477 if (value_zero_p(param2
->x
.n
))
2478 res
= evalue_eval(&e
->x
.p
->arr
[1], values
);
2479 else if (e
->x
.p
->size
> 2)
2480 res
= evalue_eval(&e
->x
.p
->arr
[2], values
);
2482 res
= evalue_zero();
2483 free_evalue_refs(param2
);
2487 assert(e
->x
.p
->pos
== EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
);
2488 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2489 if (in_domain(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), values
)) {
2490 res
= evalue_eval(&e
->x
.p
->arr
[2*i
+1], values
);
2494 res
= evalue_zero();
2502 size_t value_size(Value v
) {
2503 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2504 * sizeof(v
[0]._mp_d
[0]);
2507 size_t domain_size(Polyhedron
*D
)
2510 size_t s
= sizeof(*D
);
2512 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2513 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2514 s
+= value_size(D
->Constraint
[i
][j
]);
2517 for (i = 0; i < D->NbRays; ++i)
2518 for (j = 0; j < D->Dimension+2; ++j)
2519 s += value_size(D->Ray[i][j]);
2522 return D
->next
? s
+domain_size(D
->next
) : s
;
2525 size_t enode_size(enode
*p
) {
2526 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2529 if (p
->type
== partition
)
2530 for (i
= 0; i
< p
->size
/2; ++i
) {
2531 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2532 s
+= evalue_size(&p
->arr
[2*i
+1]);
2535 for (i
= 0; i
< p
->size
; ++i
) {
2536 s
+= evalue_size(&p
->arr
[i
]);
2541 size_t evalue_size(evalue
*e
)
2543 size_t s
= sizeof(*e
);
2544 s
+= value_size(e
->d
);
2545 if (value_notzero_p(e
->d
))
2546 s
+= value_size(e
->x
.n
);
2548 s
+= enode_size(e
->x
.p
);
2552 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2554 evalue
*found
= NULL
;
2559 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2562 value_init(offset
.d
);
2563 value_init(offset
.x
.n
);
2564 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2565 value_lcm(m
, offset
.d
, &offset
.d
);
2566 value_set_si(offset
.x
.n
, 1);
2569 evalue_copy(©
, cst
);
2572 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2574 if (eequal(base
, &e
->x
.p
->arr
[0]))
2575 found
= &e
->x
.p
->arr
[0];
2577 value_set_si(offset
.x
.n
, -2);
2580 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2582 if (eequal(base
, &e
->x
.p
->arr
[0]))
2585 free_evalue_refs(cst
);
2586 free_evalue_refs(&offset
);
2589 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2590 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2595 static evalue
*find_relation_pair(evalue
*e
)
2598 evalue
*found
= NULL
;
2600 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2603 if (e
->x
.p
->type
== fractional
) {
2608 poly_denom(&e
->x
.p
->arr
[0], &m
);
2610 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2611 cst
= &cst
->x
.p
->arr
[0])
2614 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2615 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2620 i
= e
->x
.p
->type
== relation
;
2621 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2622 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2627 void evalue_mod2relation(evalue
*e
) {
2630 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2633 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2634 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2635 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2636 value_clear(e
->x
.p
->arr
[2*i
].d
);
2637 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2639 if (2*i
< e
->x
.p
->size
) {
2640 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2641 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2646 if (e
->x
.p
->size
== 0) {
2648 evalue_set_si(e
, 0, 1);
2654 while ((d
= find_relation_pair(e
)) != NULL
) {
2658 value_init(split
.d
);
2659 value_set_si(split
.d
, 0);
2660 split
.x
.p
= new_enode(relation
, 3, 0);
2661 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2662 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2664 ev
= &split
.x
.p
->arr
[0];
2665 value_set_si(ev
->d
, 0);
2666 ev
->x
.p
= new_enode(fractional
, 3, -1);
2667 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2668 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2669 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2675 free_evalue_refs(&split
);
2679 static int evalue_comp(const void * a
, const void * b
)
2681 const evalue
*e1
= *(const evalue
**)a
;
2682 const evalue
*e2
= *(const evalue
**)b
;
2683 return ecmp(e1
, e2
);
2686 void evalue_combine(evalue
*e
)
2693 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2696 NALLOC(evs
, e
->x
.p
->size
/2);
2697 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2698 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2699 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2700 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2701 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2702 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2703 value_clear(p
->arr
[2*k
].d
);
2704 value_clear(p
->arr
[2*k
+1].d
);
2705 p
->arr
[2*k
] = *(evs
[i
]-1);
2706 p
->arr
[2*k
+1] = *(evs
[i
]);
2709 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2712 value_clear((evs
[i
]-1)->d
);
2716 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2717 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2718 free_evalue_refs(evs
[i
]);
2722 for (i
= 2*k
; i
< p
->size
; ++i
)
2723 value_clear(p
->arr
[i
].d
);
2730 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2732 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2734 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2737 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2738 Polyhedron
*D
, *N
, **P
;
2741 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2748 if (D
->NbEq
<= H
->NbEq
) {
2754 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2755 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2756 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2757 reduce_evalue(&tmp
);
2758 if (value_notzero_p(tmp
.d
) ||
2759 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2762 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2763 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2766 free_evalue_refs(&tmp
);
2772 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2774 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2776 value_clear(e
->x
.p
->arr
[2*i
].d
);
2777 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2779 if (2*i
< e
->x
.p
->size
) {
2780 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2781 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2788 H
= DomainConvex(D
, 0);
2789 E
= DomainDifference(H
, D
, 0);
2791 D
= DomainDifference(H
, E
, 0);
2794 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2798 /* Use smallest representative for coefficients in affine form in
2799 * argument of fractional.
2800 * Since any change will make the argument non-standard,
2801 * the containing evalue will have to be reduced again afterward.
2803 static void fractional_minimal_coefficients(enode
*p
)
2809 assert(p
->type
== fractional
);
2811 while (value_zero_p(pp
->d
)) {
2812 assert(pp
->x
.p
->type
== polynomial
);
2813 assert(pp
->x
.p
->size
== 2);
2814 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2815 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2816 if (value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2817 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2818 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2819 pp
= &pp
->x
.p
->arr
[0];
2825 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2830 unsigned dim
= D
->Dimension
;
2831 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2834 assert(p
->type
== fractional
|| p
->type
== flooring
);
2835 value_set_si(T
->p
[1][dim
], 1);
2836 evalue_extract_affine(&p
->arr
[0], T
->p
[0], &T
->p
[0][dim
], d
);
2837 I
= DomainImage(D
, T
, 0);
2838 H
= DomainConvex(I
, 0);
2848 static void replace_by_affine(evalue
*e
, Value offset
)
2855 value_init(inc
.x
.n
);
2856 value_set_si(inc
.d
, 1);
2857 value_oppose(inc
.x
.n
, offset
);
2858 eadd(&inc
, &p
->arr
[0]);
2859 reorder_terms_about(p
, &p
->arr
[0]); /* frees arr[0] */
2863 free_evalue_refs(&inc
);
2866 int evalue_range_reduction_in_domain(evalue
*e
, Polyhedron
*D
)
2875 if (value_notzero_p(e
->d
))
2880 if (p
->type
== relation
) {
2887 fractional_minimal_coefficients(p
->arr
[0].x
.p
);
2888 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
);
2889 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2890 equal
= value_eq(min
, max
);
2891 mpz_cdiv_q(min
, min
, d
);
2892 mpz_fdiv_q(max
, max
, d
);
2894 if (bounded
&& value_gt(min
, max
)) {
2900 evalue_set_si(e
, 0, 1);
2903 free_evalue_refs(&(p
->arr
[1]));
2904 free_evalue_refs(&(p
->arr
[0]));
2910 return r
? r
: evalue_range_reduction_in_domain(e
, D
);
2911 } else if (bounded
&& equal
) {
2914 free_evalue_refs(&(p
->arr
[2]));
2917 free_evalue_refs(&(p
->arr
[0]));
2923 return evalue_range_reduction_in_domain(e
, D
);
2924 } else if (bounded
&& value_eq(min
, max
)) {
2925 /* zero for a single value */
2927 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2928 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2929 value_multiply(min
, min
, d
);
2930 value_subtract(M
->p
[0][D
->Dimension
+1],
2931 M
->p
[0][D
->Dimension
+1], min
);
2932 E
= DomainAddConstraints(D
, M
, 0);
2938 r
= evalue_range_reduction_in_domain(&p
->arr
[1], E
);
2940 r
|= evalue_range_reduction_in_domain(&p
->arr
[2], D
);
2942 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2950 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2953 i
= p
->type
== relation
? 1 :
2954 p
->type
== fractional
? 1 : 0;
2955 for (; i
<p
->size
; i
++)
2956 r
|= evalue_range_reduction_in_domain(&p
->arr
[i
], D
);
2958 if (p
->type
!= fractional
) {
2959 if (r
&& p
->type
== polynomial
) {
2962 value_set_si(f
.d
, 0);
2963 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2964 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2965 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2966 reorder_terms_about(p
, &f
);
2977 fractional_minimal_coefficients(p
);
2978 I
= polynomial_projection(p
, D
, &d
, NULL
);
2979 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2980 mpz_fdiv_q(min
, min
, d
);
2981 mpz_fdiv_q(max
, max
, d
);
2982 value_subtract(d
, max
, min
);
2984 if (bounded
&& value_eq(min
, max
)) {
2985 replace_by_affine(e
, min
);
2987 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2988 /* replace {g}^2 by -(g-min)^2 + (2{g}+1)*(g-min) - {g}
2989 * See pages 199-200 of PhD thesis.
2997 value_set_si(rem
.d
, 0);
2998 rem
.x
.p
= new_enode(fractional
, 3, -1);
2999 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
3000 value_clear(rem
.x
.p
->arr
[1].d
);
3001 value_clear(rem
.x
.p
->arr
[2].d
);
3002 rem
.x
.p
->arr
[1] = p
->arr
[1];
3003 rem
.x
.p
->arr
[2] = p
->arr
[2];
3004 for (i
= 3; i
< p
->size
; ++i
)
3005 p
->arr
[i
-2] = p
->arr
[i
];
3009 value_init(inc
.x
.n
);
3010 value_set_si(inc
.d
, 1);
3011 value_oppose(inc
.x
.n
, min
);
3014 evalue_copy(&t
, &p
->arr
[0]);
3018 value_set_si(f
.d
, 0);
3019 f
.x
.p
= new_enode(fractional
, 3, -1);
3020 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3021 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3022 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
3024 value_init(factor
.d
);
3025 evalue_set_si(&factor
, -1, 1);
3031 value_clear(f
.x
.p
->arr
[1].x
.n
);
3032 value_clear(f
.x
.p
->arr
[2].x
.n
);
3033 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3034 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3038 reorder_terms(&rem
);
3045 free_evalue_refs(&inc
);
3046 free_evalue_refs(&t
);
3047 free_evalue_refs(&f
);
3048 free_evalue_refs(&factor
);
3049 free_evalue_refs(&rem
);
3051 evalue_range_reduction_in_domain(e
, D
);
3055 _reduce_evalue(&p
->arr
[0], 0, 1);
3067 void evalue_range_reduction(evalue
*e
)
3070 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
3073 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3074 if (evalue_range_reduction_in_domain(&e
->x
.p
->arr
[2*i
+1],
3075 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
3076 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3078 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
3079 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
3080 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3081 value_clear(e
->x
.p
->arr
[2*i
].d
);
3083 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
3084 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
3092 Enumeration
* partition2enumeration(evalue
*EP
)
3095 Enumeration
*en
, *res
= NULL
;
3097 if (EVALUE_IS_ZERO(*EP
)) {
3102 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
3103 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
3104 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
3107 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
3108 value_clear(EP
->x
.p
->arr
[2*i
].d
);
3109 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
3117 int evalue_frac2floor_in_domain3(evalue
*e
, Polyhedron
*D
, int shift
)
3126 if (value_notzero_p(e
->d
))
3131 i
= p
->type
== relation
? 1 :
3132 p
->type
== fractional
? 1 : 0;
3133 for (; i
<p
->size
; i
++)
3134 r
|= evalue_frac2floor_in_domain3(&p
->arr
[i
], D
, shift
);
3136 if (p
->type
!= fractional
) {
3137 if (r
&& p
->type
== polynomial
) {
3140 value_set_si(f
.d
, 0);
3141 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
3142 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
3143 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3144 reorder_terms_about(p
, &f
);
3154 I
= polynomial_projection(p
, D
, &d
, NULL
);
3157 Polyhedron_Print(stderr, P_VALUE_FMT, I);
3160 assert(I
->NbEq
== 0); /* Should have been reduced */
3163 for (i
= 0; i
< I
->NbConstraints
; ++i
)
3164 if (value_pos_p(I
->Constraint
[i
][1]))
3167 if (i
< I
->NbConstraints
) {
3169 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
3170 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
3171 if (value_neg_p(min
)) {
3173 mpz_fdiv_q(min
, min
, d
);
3174 value_init(offset
.d
);
3175 value_set_si(offset
.d
, 1);
3176 value_init(offset
.x
.n
);
3177 value_oppose(offset
.x
.n
, min
);
3178 eadd(&offset
, &p
->arr
[0]);
3179 free_evalue_refs(&offset
);
3189 value_set_si(fl
.d
, 0);
3190 fl
.x
.p
= new_enode(flooring
, 3, -1);
3191 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
3192 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
3193 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
3195 eadd(&fl
, &p
->arr
[0]);
3196 reorder_terms_about(p
, &p
->arr
[0]);
3200 free_evalue_refs(&fl
);
3205 int evalue_frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
3207 return evalue_frac2floor_in_domain3(e
, D
, 1);
3210 void evalue_frac2floor2(evalue
*e
, int shift
)
3213 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
3215 if (evalue_frac2floor_in_domain3(e
, NULL
, 0))
3221 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3222 if (evalue_frac2floor_in_domain3(&e
->x
.p
->arr
[2*i
+1],
3223 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), shift
))
3224 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3227 void evalue_frac2floor(evalue
*e
)
3229 evalue_frac2floor2(e
, 1);
3232 /* Add a new variable with lower bound 1 and upper bound specified
3233 * by row. If negative is true, then the new variable has upper
3234 * bound -1 and lower bound specified by row.
3236 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
3237 Vector
*row
, int negative
)
3241 int nparam
= D
->Dimension
- nvar
;
3244 nr
= D
->NbConstraints
+ 2;
3245 nc
= D
->Dimension
+ 2 + 1;
3246 C
= Matrix_Alloc(nr
, nc
);
3247 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
3248 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
3249 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3250 D
->Dimension
+ 1 - nvar
);
3255 nc
= C
->NbColumns
+ 1;
3256 C
= Matrix_Alloc(nr
, nc
);
3257 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
3258 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
3259 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3260 oldC
->NbColumns
- 1 - nvar
);
3263 value_set_si(C
->p
[nr
-2][0], 1);
3265 value_set_si(C
->p
[nr
-2][1 + nvar
], -1);
3267 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
3268 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
3270 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
3271 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
3277 static void floor2frac_r(evalue
*e
, int nvar
)
3284 if (value_notzero_p(e
->d
))
3289 assert(p
->type
== flooring
);
3290 for (i
= 1; i
< p
->size
; i
++)
3291 floor2frac_r(&p
->arr
[i
], nvar
);
3293 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3294 assert(pp
->x
.p
->type
== polynomial
);
3295 pp
->x
.p
->pos
-= nvar
;
3299 value_set_si(f
.d
, 0);
3300 f
.x
.p
= new_enode(fractional
, 3, -1);
3301 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3302 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3303 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3305 eadd(&f
, &p
->arr
[0]);
3306 reorder_terms_about(p
, &p
->arr
[0]);
3310 free_evalue_refs(&f
);
3313 /* Convert flooring back to fractional and shift position
3314 * of the parameters by nvar
3316 static void floor2frac(evalue
*e
, int nvar
)
3318 floor2frac_r(e
, nvar
);
3322 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
3325 int nparam
= D
->Dimension
- nvar
;
3329 D
= Constraints2Polyhedron(C
, 0);
3333 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3335 /* Double check that D was not unbounded. */
3336 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3344 static evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3345 int *signs
, Matrix
*C
, unsigned MaxRays
)
3351 evalue
*factor
= NULL
;
3355 if (EVALUE_IS_ZERO(*e
))
3359 Polyhedron
*DD
= Disjoint_Domain(D
, 0, MaxRays
);
3366 res
= esum_over_domain(e
, nvar
, Q
, signs
, C
, MaxRays
);
3369 for (Q
= DD
; Q
; Q
= DD
) {
3375 t
= esum_over_domain(e
, nvar
, Q
, signs
, C
, MaxRays
);
3382 free_evalue_refs(t
);
3389 if (value_notzero_p(e
->d
)) {
3392 t
= esum_over_domain_cst(nvar
, D
, C
);
3394 if (!EVALUE_IS_ONE(*e
))
3400 switch (e
->x
.p
->type
) {
3402 evalue
*pp
= &e
->x
.p
->arr
[0];
3404 if (pp
->x
.p
->pos
> nvar
) {
3405 /* remainder is independent of the summated vars */
3411 floor2frac(&f
, nvar
);
3413 t
= esum_over_domain_cst(nvar
, D
, C
);
3417 free_evalue_refs(&f
);
3422 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3423 poly_denom(pp
, &row
->p
[1 + nvar
]);
3424 value_set_si(row
->p
[0], 1);
3425 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3426 pp
= &pp
->x
.p
->arr
[0]) {
3428 assert(pp
->x
.p
->type
== polynomial
);
3430 if (pos
>= 1 + nvar
)
3432 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3433 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3434 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3436 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3437 value_division(row
->p
[1 + D
->Dimension
+ 1],
3438 row
->p
[1 + D
->Dimension
+ 1],
3440 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3441 row
->p
[1 + D
->Dimension
+ 1],
3443 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3447 int pos
= e
->x
.p
->pos
;
3450 factor
= ALLOC(evalue
);
3451 value_init(factor
->d
);
3452 value_set_si(factor
->d
, 0);
3453 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3454 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3455 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3459 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3460 negative
= signs
[pos
-1] < 0;
3461 value_set_si(row
->p
[0], 1);
3463 value_set_si(row
->p
[pos
], -1);
3464 value_set_si(row
->p
[1 + nvar
], 1);
3466 value_set_si(row
->p
[pos
], 1);
3467 value_set_si(row
->p
[1 + nvar
], -1);
3475 offset
= type_offset(e
->x
.p
);
3477 res
= esum_over_domain(&e
->x
.p
->arr
[offset
], nvar
, D
, signs
, C
, MaxRays
);
3481 evalue_copy(&cum
, factor
);
3485 for (i
= 1; offset
+i
< e
->x
.p
->size
; ++i
) {
3489 C
= esum_add_constraint(nvar
, D
, C
, row
, negative
);
3495 Vector_Print(stderr, P_VALUE_FMT, row);
3497 Matrix_Print(stderr, P_VALUE_FMT, C);
3499 t
= esum_over_domain(&e
->x
.p
->arr
[offset
+i
], nvar
, D
, signs
, C
, MaxRays
);
3504 if (negative
&& (i
% 2))
3512 free_evalue_refs(t
);
3515 if (factor
&& offset
+i
+1 < e
->x
.p
->size
)
3522 free_evalue_refs(factor
);
3523 free_evalue_refs(&cum
);
3535 static void domain_signs(Polyhedron
*D
, int *signs
)
3539 POL_ENSURE_VERTICES(D
);
3540 for (j
= 0; j
< D
->Dimension
; ++j
) {
3542 for (k
= 0; k
< D
->NbRays
; ++k
) {
3543 signs
[j
] = value_sign(D
->Ray
[k
][1+j
]);
3550 static void shift_floor_in_domain(evalue
*e
, Polyhedron
*D
)
3557 if (value_notzero_p(e
->d
))
3562 for (i
= type_offset(p
); i
< p
->size
; ++i
)
3563 shift_floor_in_domain(&p
->arr
[i
], D
);
3565 if (p
->type
!= flooring
)
3571 I
= polynomial_projection(p
, D
, &d
, NULL
);
3572 assert(I
->NbEq
== 0); /* Should have been reduced */
3574 for (i
= 0; i
< I
->NbConstraints
; ++i
)
3575 if (value_pos_p(I
->Constraint
[i
][1]))
3577 assert(i
< I
->NbConstraints
);
3578 if (i
< I
->NbConstraints
) {
3579 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
3580 mpz_fdiv_q(m
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
3581 if (value_neg_p(m
)) {
3582 /* replace [e] by [e-m]+m such that e-m >= 0 */
3587 value_set_si(f
.d
, 1);
3588 value_oppose(f
.x
.n
, m
);
3589 eadd(&f
, &p
->arr
[0]);
3592 value_set_si(f
.d
, 0);
3593 f
.x
.p
= new_enode(flooring
, 3, -1);
3594 value_clear(f
.x
.p
->arr
[0].d
);
3595 f
.x
.p
->arr
[0] = p
->arr
[0];
3596 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
3597 value_set_si(f
.x
.p
->arr
[1].d
, 1);
3598 value_init(f
.x
.p
->arr
[1].x
.n
);
3599 value_assign(f
.x
.p
->arr
[1].x
.n
, m
);
3600 reorder_terms_about(p
, &f
);
3611 /* Make arguments of all floors non-negative */
3612 static void shift_floor_arguments(evalue
*e
)
3616 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
3619 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3620 shift_floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
3621 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3624 evalue
*evalue_sum(evalue
*e
, int nvar
, unsigned MaxRays
)
3628 evalue
*res
= ALLOC(evalue
);
3632 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3633 evalue_copy(res
, e
);
3637 evalue_split_domains_into_orthants(e
, MaxRays
);
3638 evalue_frac2floor2(e
, 0);
3639 evalue_set_si(res
, 0, 1);
3641 assert(value_zero_p(e
->d
));
3642 assert(e
->x
.p
->type
== partition
);
3643 shift_floor_arguments(e
);
3645 assert(e
->x
.p
->size
>= 2);
3646 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3648 signs
= alloca(sizeof(int) * dim
);
3650 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3652 domain_signs(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), signs
);
3653 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3654 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), signs
, 0,
3657 free_evalue_refs(t
);
3666 evalue
*esum(evalue
*e
, int nvar
)
3668 return evalue_sum(e
, nvar
, 0);
3671 /* Initial silly implementation */
3672 void eor(evalue
*e1
, evalue
*res
)
3678 evalue_set_si(&mone
, -1, 1);
3680 evalue_copy(&E
, res
);
3686 free_evalue_refs(&E
);
3687 free_evalue_refs(&mone
);
3690 /* computes denominator of polynomial evalue
3691 * d should point to a value initialized to 1
3693 void evalue_denom(const evalue
*e
, Value
*d
)
3697 if (value_notzero_p(e
->d
)) {
3698 value_lcm(*d
, e
->d
, d
);
3701 assert(e
->x
.p
->type
== polynomial
||
3702 e
->x
.p
->type
== fractional
||
3703 e
->x
.p
->type
== flooring
);
3704 offset
= type_offset(e
->x
.p
);
3705 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3706 evalue_denom(&e
->x
.p
->arr
[i
], d
);
3709 /* Divides the evalue e by the integer n */
3710 void evalue_div(evalue
* e
, Value n
)
3714 if (value_notzero_p(e
->d
)) {
3717 value_multiply(e
->d
, e
->d
, n
);
3718 Gcd(e
->x
.n
, e
->d
, &gc
);
3719 if (value_notone_p(gc
)) {
3720 value_division(e
->d
, e
->d
, gc
);
3721 value_division(e
->x
.n
, e
->x
.n
, gc
);
3726 if (e
->x
.p
->type
== partition
) {
3727 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3728 evalue_div(&e
->x
.p
->arr
[2*i
+1], n
);
3731 offset
= type_offset(e
->x
.p
);
3732 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3733 evalue_div(&e
->x
.p
->arr
[i
], n
);
3736 void evalue_negate(evalue
*e
)
3740 if (value_notzero_p(e
->d
)) {
3741 value_oppose(e
->x
.n
, e
->x
.n
);
3744 if (e
->x
.p
->type
== partition
) {
3745 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3746 evalue_negate(&e
->x
.p
->arr
[2*i
+1]);
3749 offset
= type_offset(e
->x
.p
);
3750 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3751 evalue_negate(&e
->x
.p
->arr
[i
]);
3754 void evalue_add_constant(evalue
*e
, const Value cst
)
3758 if (value_zero_p(e
->d
)) {
3759 if (e
->x
.p
->type
== partition
) {
3760 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3761 evalue_add_constant(&e
->x
.p
->arr
[2*i
+1], cst
);
3764 if (e
->x
.p
->type
== relation
) {
3765 for (i
= 1; i
< e
->x
.p
->size
; ++i
)
3766 evalue_add_constant(&e
->x
.p
->arr
[i
], cst
);
3770 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)];
3771 } while (value_zero_p(e
->d
));
3773 value_addmul(e
->x
.n
, cst
, e
->d
);
3776 static void evalue_frac2polynomial_r(evalue
*e
, int *signs
, int sign
, int in_frac
)
3781 int sign_odd
= sign
;
3783 if (value_notzero_p(e
->d
)) {
3784 if (in_frac
&& sign
* value_sign(e
->x
.n
) < 0) {
3785 value_set_si(e
->x
.n
, 0);
3786 value_set_si(e
->d
, 1);
3791 if (e
->x
.p
->type
== relation
) {
3792 for (i
= e
->x
.p
->size
-1; i
>= 1; --i
)
3793 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
, sign
, in_frac
);
3797 if (e
->x
.p
->type
== polynomial
)
3798 sign_odd
*= signs
[e
->x
.p
->pos
-1];
3799 offset
= type_offset(e
->x
.p
);
3800 evalue_frac2polynomial_r(&e
->x
.p
->arr
[offset
], signs
, sign
, in_frac
);
3801 in_frac
|= e
->x
.p
->type
== fractional
;
3802 for (i
= e
->x
.p
->size
-1; i
> offset
; --i
)
3803 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
,
3804 (i
- offset
) % 2 ? sign_odd
: sign
, in_frac
);
3806 if (e
->x
.p
->type
!= fractional
)
3809 /* replace { a/m } by (m-1)/m if sign != 0
3810 * and by (m-1)/(2m) if sign == 0
3814 evalue_denom(&e
->x
.p
->arr
[0], &d
);
3815 free_evalue_refs(&e
->x
.p
->arr
[0]);
3816 value_init(e
->x
.p
->arr
[0].d
);
3817 value_init(e
->x
.p
->arr
[0].x
.n
);
3819 value_addto(e
->x
.p
->arr
[0].d
, d
, d
);
3821 value_assign(e
->x
.p
->arr
[0].d
, d
);
3822 value_decrement(e
->x
.p
->arr
[0].x
.n
, d
);
3826 reorder_terms_about(p
, &p
->arr
[0]);
3832 /* Approximate the evalue in fractional representation by a polynomial.
3833 * If sign > 0, the result is an upper bound;
3834 * if sign < 0, the result is a lower bound;
3835 * if sign = 0, the result is an intermediate approximation.
3837 void evalue_frac2polynomial(evalue
*e
, int sign
, unsigned MaxRays
)
3842 if (value_notzero_p(e
->d
))
3844 assert(e
->x
.p
->type
== partition
);
3845 /* make sure all variables in the domains have a fixed sign */
3847 evalue_split_domains_into_orthants(e
, MaxRays
);
3849 assert(e
->x
.p
->size
>= 2);
3850 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3852 signs
= alloca(sizeof(int) * dim
);
3855 for (i
= 0; i
< dim
; ++i
)
3857 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3859 domain_signs(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), signs
);
3860 evalue_frac2polynomial_r(&e
->x
.p
->arr
[2*i
+1], signs
, sign
, 0);
3864 /* Split the domains of e (which is assumed to be a partition)
3865 * such that each resulting domain lies entirely in one orthant.
3867 void evalue_split_domains_into_orthants(evalue
*e
, unsigned MaxRays
)
3870 assert(value_zero_p(e
->d
));
3871 assert(e
->x
.p
->type
== partition
);
3872 assert(e
->x
.p
->size
>= 2);
3873 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3875 for (i
= 0; i
< dim
; ++i
) {
3878 C
= Matrix_Alloc(1, 1 + dim
+ 1);
3879 value_set_si(C
->p
[0][0], 1);
3880 value_init(split
.d
);
3881 value_set_si(split
.d
, 0);
3882 split
.x
.p
= new_enode(partition
, 4, dim
);
3883 value_set_si(C
->p
[0][1+i
], 1);
3884 C2
= Matrix_Copy(C
);
3885 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[0], Constraints2Polyhedron(C2
, MaxRays
));
3887 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
3888 value_set_si(C
->p
[0][1+i
], -1);
3889 value_set_si(C
->p
[0][1+dim
], -1);
3890 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[2], Constraints2Polyhedron(C
, MaxRays
));
3891 evalue_set_si(&split
.x
.p
->arr
[3], 1, 1);
3893 free_evalue_refs(&split
);
3899 static evalue
*find_fractional_with_max_periods(evalue
*e
, Polyhedron
*D
,
3902 Value
*min
, Value
*max
)
3909 if (value_notzero_p(e
->d
))
3912 if (e
->x
.p
->type
== fractional
) {
3917 I
= polynomial_projection(e
->x
.p
, D
, &d
, &T
);
3918 bounded
= line_minmax(I
, min
, max
); /* frees I */
3922 value_set_si(mp
, max_periods
);
3923 mpz_fdiv_q(*min
, *min
, d
);
3924 mpz_fdiv_q(*max
, *max
, d
);
3925 value_assign(T
->p
[1][D
->Dimension
], d
);
3926 value_subtract(d
, *max
, *min
);
3927 if (value_ge(d
, mp
))
3930 f
= evalue_dup(&e
->x
.p
->arr
[0]);
3941 for (i
= type_offset(e
->x
.p
); i
< e
->x
.p
->size
; ++i
)
3942 if ((f
= find_fractional_with_max_periods(&e
->x
.p
->arr
[i
], D
, max_periods
,
3949 static void replace_fract_by_affine(evalue
*e
, evalue
*f
, Value val
)
3953 if (value_notzero_p(e
->d
))
3956 offset
= type_offset(e
->x
.p
);
3957 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3958 replace_fract_by_affine(&e
->x
.p
->arr
[i
], f
, val
);
3960 if (e
->x
.p
->type
!= fractional
)
3963 if (!eequal(&e
->x
.p
->arr
[0], f
))
3966 replace_by_affine(e
, val
);
3969 /* Look for fractional parts that can be removed by splitting the corresponding
3970 * domain into at most max_periods parts.
3971 * We use a very simply strategy that looks for the first fractional part
3972 * that satisfies the condition, performs the split and then continues
3973 * looking for other fractional parts in the split domains until no
3974 * such fractional part can be found anymore.
3976 void evalue_split_periods(evalue
*e
, int max_periods
, unsigned int MaxRays
)
3983 if (EVALUE_IS_ZERO(*e
))
3985 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
3987 "WARNING: evalue_split_periods called on incorrect evalue type\n");
3995 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
4000 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
4002 f
= find_fractional_with_max_periods(&e
->x
.p
->arr
[2*i
+1], D
, max_periods
,
4007 M
= Matrix_Alloc(2, 2+D
->Dimension
);
4009 value_subtract(d
, max
, min
);
4010 n
= VALUE_TO_INT(d
)+1;
4012 value_set_si(M
->p
[0][0], 1);
4013 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
4014 value_multiply(d
, max
, T
->p
[1][D
->Dimension
]);
4015 value_subtract(M
->p
[0][1+D
->Dimension
], M
->p
[0][1+D
->Dimension
], d
);
4016 value_set_si(d
, -1);
4017 value_set_si(M
->p
[1][0], 1);
4018 Vector_Scale(T
->p
[0], M
->p
[1]+1, d
, D
->Dimension
+1);
4019 value_addmul(M
->p
[1][1+D
->Dimension
], max
, T
->p
[1][D
->Dimension
]);
4020 value_addto(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
],
4021 T
->p
[1][D
->Dimension
]);
4022 value_decrement(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
]);
4024 p
= new_enode(partition
, e
->x
.p
->size
+ (n
-1)*2, e
->x
.p
->pos
);
4025 for (j
= 0; j
< 2*i
; ++j
) {
4026 value_clear(p
->arr
[j
].d
);
4027 p
->arr
[j
] = e
->x
.p
->arr
[j
];
4029 for (j
= 2*i
+2; j
< e
->x
.p
->size
; ++j
) {
4030 value_clear(p
->arr
[j
+2*(n
-1)].d
);
4031 p
->arr
[j
+2*(n
-1)] = e
->x
.p
->arr
[j
];
4033 for (j
= n
-1; j
>= 0; --j
) {
4035 value_clear(p
->arr
[2*i
+1].d
);
4036 p
->arr
[2*i
+1] = e
->x
.p
->arr
[2*i
+1];
4038 evalue_copy(&p
->arr
[2*(i
+j
)+1], &e
->x
.p
->arr
[2*i
+1]);
4040 value_subtract(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
],
4041 T
->p
[1][D
->Dimension
]);
4042 value_addto(M
->p
[0][1+D
->Dimension
], M
->p
[0][1+D
->Dimension
],
4043 T
->p
[1][D
->Dimension
]);
4045 replace_fract_by_affine(&p
->arr
[2*(i
+j
)+1], f
, max
);
4046 E
= DomainAddConstraints(D
, M
, MaxRays
);
4047 EVALUE_SET_DOMAIN(p
->arr
[2*(i
+j
)], E
);
4048 if (evalue_range_reduction_in_domain(&p
->arr
[2*(i
+j
)+1], E
))
4049 reduce_evalue(&p
->arr
[2*(i
+j
)+1]);
4050 value_decrement(max
, max
);
4052 value_clear(e
->x
.p
->arr
[2*i
].d
);
4056 free_evalue_refs(f
);
4068 void evalue_extract_affine(const evalue
*e
, Value
*coeff
, Value
*cst
, Value
*d
)
4070 value_set_si(*d
, 1);
4072 for ( ; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[0]) {
4074 assert(e
->x
.p
->type
== polynomial
);
4075 assert(e
->x
.p
->size
== 2);
4076 c
= &e
->x
.p
->arr
[1];
4077 value_multiply(coeff
[e
->x
.p
->pos
-1], *d
, c
->x
.n
);
4078 value_division(coeff
[e
->x
.p
->pos
-1], coeff
[e
->x
.p
->pos
-1], c
->d
);
4080 value_multiply(*cst
, *d
, e
->x
.n
);
4081 value_division(*cst
, *cst
, e
->d
);
4084 /* returns an evalue that corresponds to
4088 static evalue
*term(int param
, Value c
, Value den
)
4090 evalue
*EP
= ALLOC(evalue
);
4092 value_set_si(EP
->d
,0);
4093 EP
->x
.p
= new_enode(polynomial
, 2, param
+ 1);
4094 evalue_set_si(&EP
->x
.p
->arr
[0], 0, 1);
4095 value_init(EP
->x
.p
->arr
[1].x
.n
);
4096 value_assign(EP
->x
.p
->arr
[1].d
, den
);
4097 value_assign(EP
->x
.p
->arr
[1].x
.n
, c
);
4101 evalue
*affine2evalue(Value
*coeff
, Value denom
, int nvar
)
4104 evalue
*E
= ALLOC(evalue
);
4106 evalue_set(E
, coeff
[nvar
], denom
);
4107 for (i
= 0; i
< nvar
; ++i
) {
4108 if (value_zero_p(coeff
[i
]))
4110 evalue
*t
= term(i
, coeff
[i
], denom
);
4112 free_evalue_refs(t
);
4118 void evalue_substitute(evalue
*e
, evalue
**subs
)
4124 if (value_notzero_p(e
->d
))
4128 assert(p
->type
!= partition
);
4130 for (i
= 0; i
< p
->size
; ++i
)
4131 evalue_substitute(&p
->arr
[i
], subs
);
4133 if (p
->type
== polynomial
)
4138 value_set_si(v
->d
, 0);
4139 v
->x
.p
= new_enode(p
->type
, 3, -1);
4140 value_clear(v
->x
.p
->arr
[0].d
);
4141 v
->x
.p
->arr
[0] = p
->arr
[0];
4142 evalue_set_si(&v
->x
.p
->arr
[1], 0, 1);
4143 evalue_set_si(&v
->x
.p
->arr
[2], 1, 1);
4146 offset
= type_offset(p
);
4148 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
4149 emul(v
, &p
->arr
[i
]);
4150 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
4151 free_evalue_refs(&(p
->arr
[i
]));
4154 if (p
->type
!= polynomial
) {
4155 free_evalue_refs(v
);
4160 *e
= p
->arr
[offset
];
4164 /* evalue e is given in terms of "new" parameter; CP maps the new
4165 * parameters back to the old parameters.
4166 * Transforms e such that it refers back to the old parameters.
4168 void evalue_backsubstitute(evalue
*e
, Matrix
*CP
, unsigned MaxRays
)
4175 unsigned nparam
= CP
->NbColumns
-1;
4178 if (EVALUE_IS_ZERO(*e
))
4181 assert(value_zero_p(e
->d
));
4183 assert(p
->type
== partition
);
4185 inv
= left_inverse(CP
, &eq
);
4186 subs
= ALLOCN(evalue
*, nparam
);
4187 for (i
= 0; i
< nparam
; ++i
)
4188 subs
[i
] = affine2evalue(inv
->p
[i
], inv
->p
[nparam
][inv
->NbColumns
-1],
4191 CEq
= Constraints2Polyhedron(eq
, MaxRays
);
4192 addeliminatedparams_partition(p
, inv
, CEq
, inv
->NbColumns
-1, MaxRays
);
4193 Polyhedron_Free(CEq
);
4195 for (i
= 0; i
< p
->size
/2; ++i
)
4196 evalue_substitute(&p
->arr
[2*i
+1], subs
);
4198 for (i
= 0; i
< nparam
; ++i
) {
4199 free_evalue_refs(subs
[i
]);
4207 evalue
*evalue_polynomial(Vector
*c
, evalue
* X
)
4209 unsigned dim
= c
->Size
-2;
4211 evalue
*EP
= ALLOC(evalue
);
4215 evalue_set(&EC
, c
->p
[dim
], c
->p
[dim
+1]);
4218 evalue_set(EP
, c
->p
[dim
], c
->p
[dim
+1]);
4220 for (i
= dim
-1; i
>= 0; --i
) {
4222 value_assign(EC
.x
.n
, c
->p
[i
]);
4225 free_evalue_refs(&EC
);