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
, 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
);
1080 if (!pname
|| p
->pos
< maxdim
) {
1081 for (i
= pname
? p
->pos
: 0; i
< maxdim
; ++i
)
1094 static void eadd_rev(const evalue
*e1
, evalue
*res
)
1098 evalue_copy(&ev
, e1
);
1100 free_evalue_refs(res
);
1104 static void eadd_rev_cst(const evalue
*e1
, evalue
*res
)
1108 evalue_copy(&ev
, e1
);
1109 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
1110 free_evalue_refs(res
);
1114 static int is_zero_on(evalue
*e
, Polyhedron
*D
)
1119 tmp
.x
.p
= new_enode(partition
, 2, D
->Dimension
);
1120 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Domain_Copy(D
));
1121 evalue_copy(&tmp
.x
.p
->arr
[1], e
);
1122 reduce_evalue(&tmp
);
1123 is_zero
= EVALUE_IS_ZERO(tmp
);
1124 free_evalue_refs(&tmp
);
1128 struct section
{ Polyhedron
* D
; evalue E
; };
1130 void eadd_partitions(const evalue
*e1
, evalue
*res
)
1135 s
= (struct section
*)
1136 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
1137 sizeof(struct section
));
1139 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1140 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1141 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1144 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1145 assert(res
->x
.p
->size
>= 2);
1146 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1147 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
1149 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
1151 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1160 /* See if we can extend one of the domains in res to cover fd */
1161 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1162 if (is_zero_on(&res
->x
.p
->arr
[2*i
+1], fd
))
1164 if (i
< res
->x
.p
->size
/2) {
1165 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
1166 DomainConcat(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
])));
1169 value_init(s
[n
].E
.d
);
1170 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
1174 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1175 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
1176 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1178 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1179 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1185 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1186 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1188 value_init(s
[n
].E
.d
);
1189 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1190 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1191 if (!emptyQ(fd
) && is_zero_on(&e1
->x
.p
->arr
[2*j
+1], fd
)) {
1192 d
= DomainConcat(fd
, d
);
1193 fd
= Empty_Polyhedron(fd
->Dimension
);
1199 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1203 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1206 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1207 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1208 value_clear(res
->x
.p
->arr
[2*i
].d
);
1213 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1214 for (j
= 0; j
< n
; ++j
) {
1215 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1216 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1217 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1218 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1224 static void explicit_complement(evalue
*res
)
1226 enode
*rel
= new_enode(relation
, 3, 0);
1228 value_clear(rel
->arr
[0].d
);
1229 rel
->arr
[0] = res
->x
.p
->arr
[0];
1230 value_clear(rel
->arr
[1].d
);
1231 rel
->arr
[1] = res
->x
.p
->arr
[1];
1232 value_set_si(rel
->arr
[2].d
, 1);
1233 value_init(rel
->arr
[2].x
.n
);
1234 value_set_si(rel
->arr
[2].x
.n
, 0);
1239 void eadd(const evalue
*e1
, evalue
*res
)
1242 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1243 /* Add two rational numbers */
1249 value_multiply(m1
,e1
->x
.n
,res
->d
);
1250 value_multiply(m2
,res
->x
.n
,e1
->d
);
1251 value_addto(res
->x
.n
,m1
,m2
);
1252 value_multiply(res
->d
,e1
->d
,res
->d
);
1253 Gcd(res
->x
.n
,res
->d
,&g
);
1254 if (value_notone_p(g
)) {
1255 value_division(res
->d
,res
->d
,g
);
1256 value_division(res
->x
.n
,res
->x
.n
,g
);
1258 value_clear(g
); value_clear(m1
); value_clear(m2
);
1261 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1262 switch (res
->x
.p
->type
) {
1264 /* Add the constant to the constant term of a polynomial*/
1265 eadd(e1
, &res
->x
.p
->arr
[0]);
1268 /* Add the constant to all elements of a periodic number */
1269 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1270 eadd(e1
, &res
->x
.p
->arr
[i
]);
1274 fprintf(stderr
, "eadd: cannot add const with vector\n");
1278 eadd(e1
, &res
->x
.p
->arr
[1]);
1281 assert(EVALUE_IS_ZERO(*e1
));
1282 break; /* Do nothing */
1284 /* Create (zero) complement if needed */
1285 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1286 explicit_complement(res
);
1287 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1288 eadd(e1
, &res
->x
.p
->arr
[i
]);
1294 /* add polynomial or periodic to constant
1295 * you have to exchange e1 and res, before doing addition */
1297 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1301 else { // ((e1->d==0) && (res->d==0))
1302 assert(!((e1
->x
.p
->type
== partition
) ^
1303 (res
->x
.p
->type
== partition
)));
1304 if (e1
->x
.p
->type
== partition
) {
1305 eadd_partitions(e1
, res
);
1308 if (e1
->x
.p
->type
== relation
&&
1309 (res
->x
.p
->type
!= relation
||
1310 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1314 if (res
->x
.p
->type
== relation
) {
1315 if (e1
->x
.p
->type
== relation
&&
1316 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1317 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1318 explicit_complement(res
);
1319 for (i
= 1; i
< e1
->x
.p
->size
; ++i
)
1320 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1323 if (res
->x
.p
->size
< 3)
1324 explicit_complement(res
);
1325 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1326 eadd(e1
, &res
->x
.p
->arr
[i
]);
1329 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1330 /* adding to evalues of different type. two cases are possible
1331 * res is periodic and e1 is polynomial, you have to exchange
1332 * e1 and res then to add e1 to the constant term of res */
1333 if (e1
->x
.p
->type
== polynomial
) {
1334 eadd_rev_cst(e1
, res
);
1336 else if (res
->x
.p
->type
== polynomial
) {
1337 /* res is polynomial and e1 is periodic,
1338 add e1 to the constant term of res */
1340 eadd(e1
,&res
->x
.p
->arr
[0]);
1346 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1347 ((res
->x
.p
->type
== fractional
||
1348 res
->x
.p
->type
== flooring
) &&
1349 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1350 /* adding evalues of different position (i.e function of different unknowns
1351 * to case are possible */
1353 switch (res
->x
.p
->type
) {
1356 if (mod_term_smaller(res
, e1
))
1357 eadd(e1
,&res
->x
.p
->arr
[1]);
1359 eadd_rev_cst(e1
, res
);
1361 case polynomial
: // res and e1 are polynomials
1362 // add e1 to the constant term of res
1364 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1365 eadd(e1
,&res
->x
.p
->arr
[0]);
1367 eadd_rev_cst(e1
, res
);
1368 // value_clear(g); value_clear(m1); value_clear(m2);
1370 case periodic
: // res and e1 are pointers to periodic numbers
1371 //add e1 to all elements of res
1373 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1374 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1375 eadd(e1
,&res
->x
.p
->arr
[i
]);
1386 //same type , same pos and same size
1387 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1388 // add any element in e1 to the corresponding element in res
1389 i
= type_offset(res
->x
.p
);
1391 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1392 for (; i
<res
->x
.p
->size
; i
++) {
1393 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1398 /* Sizes are different */
1399 switch(res
->x
.p
->type
) {
1403 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1404 /* new enode and add res to that new node. If you do not do */
1405 /* that, you lose the the upper weight part of e1 ! */
1407 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1410 i
= type_offset(res
->x
.p
);
1412 assert(eequal(&e1
->x
.p
->arr
[0],
1413 &res
->x
.p
->arr
[0]));
1414 for (; i
<e1
->x
.p
->size
; i
++) {
1415 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1422 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1425 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1426 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1427 to add periodicaly elements of e1 to elements of ne, and finaly to
1432 value_init(ex
); value_init(ey
);value_init(ep
);
1435 value_set_si(ex
,e1
->x
.p
->size
);
1436 value_set_si(ey
,res
->x
.p
->size
);
1437 value_assign (ep
,*Lcm(ex
,ey
));
1438 p
=(int)mpz_get_si(ep
);
1439 ne
= (evalue
*) malloc (sizeof(evalue
));
1441 value_set_si( ne
->d
,0);
1443 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1445 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1448 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1451 value_assign(res
->d
, ne
->d
);
1457 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1466 static void emul_rev(const evalue
*e1
, evalue
*res
)
1470 evalue_copy(&ev
, e1
);
1472 free_evalue_refs(res
);
1476 static void emul_poly(const evalue
*e1
, evalue
*res
)
1478 int i
, j
, offset
= type_offset(res
->x
.p
);
1481 int size
= (e1
->x
.p
->size
+ res
->x
.p
->size
- offset
- 1);
1483 p
= new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1485 for (i
= offset
; i
< e1
->x
.p
->size
-1; ++i
)
1486 if (!EVALUE_IS_ZERO(e1
->x
.p
->arr
[i
]))
1489 /* special case pure power */
1490 if (i
== e1
->x
.p
->size
-1) {
1492 value_clear(p
->arr
[0].d
);
1493 p
->arr
[0] = res
->x
.p
->arr
[0];
1495 for (i
= offset
; i
< e1
->x
.p
->size
-1; ++i
)
1496 evalue_set_si(&p
->arr
[i
], 0, 1);
1497 for (i
= offset
; i
< res
->x
.p
->size
; ++i
) {
1498 value_clear(p
->arr
[i
+e1
->x
.p
->size
-offset
-1].d
);
1499 p
->arr
[i
+e1
->x
.p
->size
-offset
-1] = res
->x
.p
->arr
[i
];
1500 emul(&e1
->x
.p
->arr
[e1
->x
.p
->size
-1],
1501 &p
->arr
[i
+e1
->x
.p
->size
-offset
-1]);
1509 value_set_si(tmp
.d
,0);
1512 evalue_copy(&p
->arr
[0], &e1
->x
.p
->arr
[0]);
1513 for (i
= offset
; i
< e1
->x
.p
->size
; i
++) {
1514 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1515 emul(&res
->x
.p
->arr
[offset
], &tmp
.x
.p
->arr
[i
]);
1518 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1519 for (i
= offset
+1; i
<res
->x
.p
->size
; i
++)
1520 for (j
= offset
; j
<e1
->x
.p
->size
; j
++) {
1523 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1524 emul(&res
->x
.p
->arr
[i
], &ev
);
1525 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-offset
]);
1526 free_evalue_refs(&ev
);
1528 free_evalue_refs(res
);
1532 void emul_partitions(const evalue
*e1
, evalue
*res
)
1537 s
= (struct section
*)
1538 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1539 sizeof(struct section
));
1541 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1542 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1543 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1546 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1547 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1548 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1549 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1555 /* This code is only needed because the partitions
1556 are not true partitions.
1558 for (k
= 0; k
< n
; ++k
) {
1559 if (DomainIncludes(s
[k
].D
, d
))
1561 if (DomainIncludes(d
, s
[k
].D
)) {
1562 Domain_Free(s
[k
].D
);
1563 free_evalue_refs(&s
[k
].E
);
1574 value_init(s
[n
].E
.d
);
1575 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1576 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1580 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1581 value_clear(res
->x
.p
->arr
[2*i
].d
);
1582 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1587 evalue_set_si(res
, 0, 1);
1589 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1590 for (j
= 0; j
< n
; ++j
) {
1591 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1592 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1593 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1594 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1601 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1603 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1604 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1605 * evalues is not treated here */
1607 void emul(const evalue
*e1
, evalue
*res
)
1611 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1612 fprintf(stderr
, "emul: do not proced on evector type !\n");
1616 if (EVALUE_IS_ZERO(*res
))
1619 if (EVALUE_IS_ONE(*e1
))
1622 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1623 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1624 emul_partitions(e1
, res
);
1627 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1628 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1629 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1631 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1632 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1633 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1634 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3) {
1635 free_evalue_refs(&res
->x
.p
->arr
[2]);
1638 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1639 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1642 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1643 emul(e1
, &res
->x
.p
->arr
[i
]);
1645 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1646 switch(e1
->x
.p
->type
) {
1648 switch(res
->x
.p
->type
) {
1650 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1651 /* Product of two polynomials of the same variable */
1656 /* Product of two polynomials of different variables */
1658 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1659 for( i
=0; i
<res
->x
.p
->size
; i
++)
1660 emul(e1
, &res
->x
.p
->arr
[i
]);
1669 /* Product of a polynomial and a periodic or fractional */
1676 switch(res
->x
.p
->type
) {
1678 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1679 /* Product of two periodics of the same parameter and period */
1681 for(i
=0; i
<res
->x
.p
->size
;i
++)
1682 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1687 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1688 /* Product of two periodics of the same parameter and different periods */
1692 value_init(x
); value_init(y
);value_init(z
);
1695 value_set_si(x
,e1
->x
.p
->size
);
1696 value_set_si(y
,res
->x
.p
->size
);
1697 value_assign (z
,*Lcm(x
,y
));
1698 lcm
=(int)mpz_get_si(z
);
1699 newp
= (evalue
*) malloc (sizeof(evalue
));
1700 value_init(newp
->d
);
1701 value_set_si( newp
->d
,0);
1702 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1703 for(i
=0;i
<lcm
;i
++) {
1704 evalue_copy(&newp
->x
.p
->arr
[i
],
1705 &res
->x
.p
->arr
[i
%iy
]);
1708 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1710 value_assign(res
->d
,newp
->d
);
1713 value_clear(x
); value_clear(y
);value_clear(z
);
1717 /* Product of two periodics of different parameters */
1719 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1720 for(i
=0; i
<res
->x
.p
->size
; i
++)
1721 emul(e1
, &(res
->x
.p
->arr
[i
]));
1729 /* Product of a periodic and a polynomial */
1731 for(i
=0; i
<res
->x
.p
->size
; i
++)
1732 emul(e1
, &(res
->x
.p
->arr
[i
]));
1739 switch(res
->x
.p
->type
) {
1741 for(i
=0; i
<res
->x
.p
->size
; i
++)
1742 emul(e1
, &(res
->x
.p
->arr
[i
]));
1749 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1750 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1751 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1754 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1755 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1760 value_set_si(d
.x
.n
, 1);
1761 /* { x }^2 == { x }/2 */
1762 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1763 assert(e1
->x
.p
->size
== 3);
1764 assert(res
->x
.p
->size
== 3);
1766 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1768 eadd(&res
->x
.p
->arr
[1], &tmp
);
1769 emul(&e1
->x
.p
->arr
[2], &tmp
);
1770 emul(&e1
->x
.p
->arr
[1], res
);
1771 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1772 free_evalue_refs(&tmp
);
1777 if(mod_term_smaller(res
, e1
))
1778 for(i
=1; i
<res
->x
.p
->size
; i
++)
1779 emul(e1
, &(res
->x
.p
->arr
[i
]));
1794 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1795 /* Product of two rational numbers */
1799 value_multiply(res
->d
,e1
->d
,res
->d
);
1800 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1801 Gcd(res
->x
.n
, res
->d
,&g
);
1802 if (value_notone_p(g
)) {
1803 value_division(res
->d
,res
->d
,g
);
1804 value_division(res
->x
.n
,res
->x
.n
,g
);
1810 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1811 /* Product of an expression (polynomial or peririodic) and a rational number */
1817 /* Product of a rationel number and an expression (polynomial or peririodic) */
1819 i
= type_offset(res
->x
.p
);
1820 for (; i
<res
->x
.p
->size
; i
++)
1821 emul(e1
, &res
->x
.p
->arr
[i
]);
1831 /* Frees mask content ! */
1832 void emask(evalue
*mask
, evalue
*res
) {
1839 if (EVALUE_IS_ZERO(*res
)) {
1840 free_evalue_refs(mask
);
1844 assert(value_zero_p(mask
->d
));
1845 assert(mask
->x
.p
->type
== partition
);
1846 assert(value_zero_p(res
->d
));
1847 assert(res
->x
.p
->type
== partition
);
1848 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1849 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1850 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1851 pos
= res
->x
.p
->pos
;
1853 s
= (struct section
*)
1854 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1855 sizeof(struct section
));
1859 evalue_set_si(&mone
, -1, 1);
1862 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1863 assert(mask
->x
.p
->size
>= 2);
1864 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1865 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1867 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1869 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1878 value_init(s
[n
].E
.d
);
1879 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1883 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1884 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1887 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1888 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1889 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1890 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1892 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1893 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1899 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1900 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1902 value_init(s
[n
].E
.d
);
1903 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1904 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1910 /* Just ignore; this may have been previously masked off */
1912 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1916 free_evalue_refs(&mone
);
1917 free_evalue_refs(mask
);
1918 free_evalue_refs(res
);
1921 evalue_set_si(res
, 0, 1);
1923 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1924 for (j
= 0; j
< n
; ++j
) {
1925 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1926 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1927 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1934 void evalue_copy(evalue
*dst
, const evalue
*src
)
1936 value_assign(dst
->d
, src
->d
);
1937 if(value_notzero_p(src
->d
)) {
1938 value_init(dst
->x
.n
);
1939 value_assign(dst
->x
.n
, src
->x
.n
);
1941 dst
->x
.p
= ecopy(src
->x
.p
);
1944 evalue
*evalue_dup(evalue
*e
)
1946 evalue
*res
= ALLOC(evalue
);
1948 evalue_copy(res
, e
);
1952 enode
*new_enode(enode_type type
,int size
,int pos
) {
1958 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1961 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1965 for(i
=0; i
<size
; i
++) {
1966 value_init(res
->arr
[i
].d
);
1967 value_set_si(res
->arr
[i
].d
,0);
1968 res
->arr
[i
].x
.p
= 0;
1973 enode
*ecopy(enode
*e
) {
1978 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1979 for(i
=0;i
<e
->size
;++i
) {
1980 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1981 if(value_zero_p(res
->arr
[i
].d
))
1982 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1983 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1984 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1986 value_init(res
->arr
[i
].x
.n
);
1987 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1993 int ecmp(const evalue
*e1
, const evalue
*e2
)
1999 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
2003 value_multiply(m
, e1
->x
.n
, e2
->d
);
2004 value_multiply(m2
, e2
->x
.n
, e1
->d
);
2006 if (value_lt(m
, m2
))
2008 else if (value_gt(m
, m2
))
2018 if (value_notzero_p(e1
->d
))
2020 if (value_notzero_p(e2
->d
))
2026 if (p1
->type
!= p2
->type
)
2027 return p1
->type
- p2
->type
;
2028 if (p1
->pos
!= p2
->pos
)
2029 return p1
->pos
- p2
->pos
;
2030 if (p1
->size
!= p2
->size
)
2031 return p1
->size
- p2
->size
;
2033 for (i
= p1
->size
-1; i
>= 0; --i
)
2034 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
2040 int eequal(const evalue
*e1
, const evalue
*e2
)
2045 if (value_ne(e1
->d
,e2
->d
))
2048 /* e1->d == e2->d */
2049 if (value_notzero_p(e1
->d
)) {
2050 if (value_ne(e1
->x
.n
,e2
->x
.n
))
2053 /* e1->d == e2->d != 0 AND e1->n == e2->n */
2057 /* e1->d == e2->d == 0 */
2060 if (p1
->type
!= p2
->type
) return 0;
2061 if (p1
->size
!= p2
->size
) return 0;
2062 if (p1
->pos
!= p2
->pos
) return 0;
2063 for (i
=0; i
<p1
->size
; i
++)
2064 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
2069 void free_evalue_refs(evalue
*e
) {
2074 if (EVALUE_IS_DOMAIN(*e
)) {
2075 Domain_Free(EVALUE_DOMAIN(*e
));
2078 } else if (value_pos_p(e
->d
)) {
2080 /* 'e' stores a constant */
2082 value_clear(e
->x
.n
);
2085 assert(value_zero_p(e
->d
));
2088 if (!p
) return; /* null pointer */
2089 for (i
=0; i
<p
->size
; i
++) {
2090 free_evalue_refs(&(p
->arr
[i
]));
2094 } /* free_evalue_refs */
2096 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
2097 Vector
* val
, evalue
*res
)
2099 unsigned nparam
= periods
->Size
;
2102 double d
= compute_evalue(e
, val
->p
);
2103 d
*= VALUE_TO_DOUBLE(m
);
2108 value_assign(res
->d
, m
);
2109 value_init(res
->x
.n
);
2110 value_set_double(res
->x
.n
, d
);
2111 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
2114 if (value_one_p(periods
->p
[p
]))
2115 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
2120 value_assign(tmp
, periods
->p
[p
]);
2121 value_set_si(res
->d
, 0);
2122 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
2124 value_decrement(tmp
, tmp
);
2125 value_assign(val
->p
[p
], tmp
);
2126 mod2table_r(e
, periods
, m
, p
+1, val
,
2127 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
2128 } while (value_pos_p(tmp
));
2134 static void rel2table(evalue
*e
, int zero
)
2136 if (value_pos_p(e
->d
)) {
2137 if (value_zero_p(e
->x
.n
) == zero
)
2138 value_set_si(e
->x
.n
, 1);
2140 value_set_si(e
->x
.n
, 0);
2141 value_set_si(e
->d
, 1);
2144 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
2145 rel2table(&e
->x
.p
->arr
[i
], zero
);
2149 void evalue_mod2table(evalue
*e
, int nparam
)
2154 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2157 for (i
=0; i
<p
->size
; i
++) {
2158 evalue_mod2table(&(p
->arr
[i
]), nparam
);
2160 if (p
->type
== relation
) {
2165 evalue_copy(©
, &p
->arr
[0]);
2167 rel2table(&p
->arr
[0], 1);
2168 emul(&p
->arr
[0], &p
->arr
[1]);
2170 rel2table(©
, 0);
2171 emul(©
, &p
->arr
[2]);
2172 eadd(&p
->arr
[2], &p
->arr
[1]);
2173 free_evalue_refs(&p
->arr
[2]);
2174 free_evalue_refs(©
);
2176 free_evalue_refs(&p
->arr
[0]);
2180 } else if (p
->type
== fractional
) {
2181 Vector
*periods
= Vector_Alloc(nparam
);
2182 Vector
*val
= Vector_Alloc(nparam
);
2188 value_set_si(tmp
, 1);
2189 Vector_Set(periods
->p
, 1, nparam
);
2190 Vector_Set(val
->p
, 0, nparam
);
2191 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2194 assert(p
->type
== polynomial
);
2195 assert(p
->size
== 2);
2196 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2197 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
2199 value_lcm(tmp
, ev
->d
, &tmp
);
2201 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2204 evalue_set_si(&res
, 0, 1);
2205 /* Compute the polynomial using Horner's rule */
2206 for (i
=p
->size
-1;i
>1;i
--) {
2207 eadd(&p
->arr
[i
], &res
);
2210 eadd(&p
->arr
[1], &res
);
2212 free_evalue_refs(e
);
2213 free_evalue_refs(&EP
);
2218 Vector_Free(periods
);
2220 } /* evalue_mod2table */
2222 /********************************************************/
2223 /* function in domain */
2224 /* check if the parameters in list_args */
2225 /* verifies the constraints of Domain P */
2226 /********************************************************/
2227 int in_domain(Polyhedron
*P
, Value
*list_args
)
2230 Value v
; /* value of the constraint of a row when
2231 parameters are instantiated*/
2235 for (row
= 0; row
< P
->NbConstraints
; row
++) {
2236 Inner_Product(P
->Constraint
[row
]+1, list_args
, P
->Dimension
, &v
);
2237 value_addto(v
, v
, P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2238 if (value_neg_p(v
) ||
2239 value_zero_p(P
->Constraint
[row
][0]) && value_notzero_p(v
)) {
2246 return in
|| (P
->next
&& in_domain(P
->next
, list_args
));
2249 /****************************************************/
2250 /* function compute enode */
2251 /* compute the value of enode p with parameters */
2252 /* list "list_args */
2253 /* compute the polynomial or the periodic */
2254 /****************************************************/
2256 static double compute_enode(enode
*p
, Value
*list_args
) {
2268 if (p
->type
== polynomial
) {
2270 value_assign(param
,list_args
[p
->pos
-1]);
2272 /* Compute the polynomial using Horner's rule */
2273 for (i
=p
->size
-1;i
>0;i
--) {
2274 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2275 res
*=VALUE_TO_DOUBLE(param
);
2277 res
+=compute_evalue(&p
->arr
[0],list_args
);
2279 else if (p
->type
== fractional
) {
2280 double d
= compute_evalue(&p
->arr
[0], list_args
);
2281 d
-= floor(d
+1e-10);
2283 /* Compute the polynomial using Horner's rule */
2284 for (i
=p
->size
-1;i
>1;i
--) {
2285 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2288 res
+=compute_evalue(&p
->arr
[1],list_args
);
2290 else if (p
->type
== flooring
) {
2291 double d
= compute_evalue(&p
->arr
[0], list_args
);
2294 /* Compute the polynomial using Horner's rule */
2295 for (i
=p
->size
-1;i
>1;i
--) {
2296 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2299 res
+=compute_evalue(&p
->arr
[1],list_args
);
2301 else if (p
->type
== periodic
) {
2302 value_assign(m
,list_args
[p
->pos
-1]);
2304 /* Choose the right element of the periodic */
2305 value_set_si(param
,p
->size
);
2306 value_pmodulus(m
,m
,param
);
2307 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2309 else if (p
->type
== relation
) {
2310 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2311 res
= compute_evalue(&p
->arr
[1], list_args
);
2312 else if (p
->size
> 2)
2313 res
= compute_evalue(&p
->arr
[2], list_args
);
2315 else if (p
->type
== partition
) {
2316 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2317 Value
*vals
= list_args
;
2320 for (i
= 0; i
< dim
; ++i
) {
2321 value_init(vals
[i
]);
2323 value_assign(vals
[i
], list_args
[i
]);
2326 for (i
= 0; i
< p
->size
/2; ++i
)
2327 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2328 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2332 for (i
= 0; i
< dim
; ++i
)
2333 value_clear(vals
[i
]);
2342 } /* compute_enode */
2344 /*************************************************/
2345 /* return the value of Ehrhart Polynomial */
2346 /* It returns a double, because since it is */
2347 /* a recursive function, some intermediate value */
2348 /* might not be integral */
2349 /*************************************************/
2351 double compute_evalue(const evalue
*e
, Value
*list_args
)
2355 if (value_notzero_p(e
->d
)) {
2356 if (value_notone_p(e
->d
))
2357 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2359 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2362 res
= compute_enode(e
->x
.p
,list_args
);
2364 } /* compute_evalue */
2367 /****************************************************/
2368 /* function compute_poly : */
2369 /* Check for the good validity domain */
2370 /* return the number of point in the Polyhedron */
2371 /* in allocated memory */
2372 /* Using the Ehrhart pseudo-polynomial */
2373 /****************************************************/
2374 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2377 /* double d; int i; */
2379 tmp
= (Value
*) malloc (sizeof(Value
));
2380 assert(tmp
!= NULL
);
2382 value_set_si(*tmp
,0);
2385 return(tmp
); /* no ehrhart polynomial */
2386 if(en
->ValidityDomain
) {
2387 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2388 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2393 return(tmp
); /* no Validity Domain */
2395 if(in_domain(en
->ValidityDomain
,list_args
)) {
2397 #ifdef EVAL_EHRHART_DEBUG
2398 Print_Domain(stdout
,en
->ValidityDomain
);
2399 print_evalue(stdout
,&en
->EP
);
2402 /* d = compute_evalue(&en->EP,list_args);
2404 printf("(double)%lf = %d\n", d, i ); */
2405 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2411 value_set_si(*tmp
,0);
2412 return(tmp
); /* no compatible domain with the arguments */
2413 } /* compute_poly */
2415 static evalue
*eval_polynomial(const enode
*p
, int offset
,
2416 evalue
*base
, Value
*values
)
2421 res
= evalue_zero();
2422 for (i
= p
->size
-1; i
> offset
; --i
) {
2423 c
= evalue_eval(&p
->arr
[i
], values
);
2425 free_evalue_refs(c
);
2429 c
= evalue_eval(&p
->arr
[offset
], values
);
2431 free_evalue_refs(c
);
2437 evalue
*evalue_eval(const evalue
*e
, Value
*values
)
2444 if (value_notzero_p(e
->d
)) {
2445 res
= ALLOC(evalue
);
2447 evalue_copy(res
, e
);
2450 switch (e
->x
.p
->type
) {
2452 value_init(param
.x
.n
);
2453 value_assign(param
.x
.n
, values
[e
->x
.p
->pos
-1]);
2454 value_init(param
.d
);
2455 value_set_si(param
.d
, 1);
2457 res
= eval_polynomial(e
->x
.p
, 0, ¶m
, values
);
2458 free_evalue_refs(¶m
);
2461 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2462 mpz_fdiv_r(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2464 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2465 free_evalue_refs(param2
);
2469 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2470 mpz_fdiv_q(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2471 value_set_si(param2
->d
, 1);
2473 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2474 free_evalue_refs(param2
);
2478 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2479 if (value_zero_p(param2
->x
.n
))
2480 res
= evalue_eval(&e
->x
.p
->arr
[1], values
);
2481 else if (e
->x
.p
->size
> 2)
2482 res
= evalue_eval(&e
->x
.p
->arr
[2], values
);
2484 res
= evalue_zero();
2485 free_evalue_refs(param2
);
2489 assert(e
->x
.p
->pos
== EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
);
2490 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2491 if (in_domain(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), values
)) {
2492 res
= evalue_eval(&e
->x
.p
->arr
[2*i
+1], values
);
2496 res
= evalue_zero();
2504 size_t value_size(Value v
) {
2505 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2506 * sizeof(v
[0]._mp_d
[0]);
2509 size_t domain_size(Polyhedron
*D
)
2512 size_t s
= sizeof(*D
);
2514 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2515 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2516 s
+= value_size(D
->Constraint
[i
][j
]);
2519 for (i = 0; i < D->NbRays; ++i)
2520 for (j = 0; j < D->Dimension+2; ++j)
2521 s += value_size(D->Ray[i][j]);
2524 return D
->next
? s
+domain_size(D
->next
) : s
;
2527 size_t enode_size(enode
*p
) {
2528 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2531 if (p
->type
== partition
)
2532 for (i
= 0; i
< p
->size
/2; ++i
) {
2533 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2534 s
+= evalue_size(&p
->arr
[2*i
+1]);
2537 for (i
= 0; i
< p
->size
; ++i
) {
2538 s
+= evalue_size(&p
->arr
[i
]);
2543 size_t evalue_size(evalue
*e
)
2545 size_t s
= sizeof(*e
);
2546 s
+= value_size(e
->d
);
2547 if (value_notzero_p(e
->d
))
2548 s
+= value_size(e
->x
.n
);
2550 s
+= enode_size(e
->x
.p
);
2554 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2556 evalue
*found
= NULL
;
2561 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2564 value_init(offset
.d
);
2565 value_init(offset
.x
.n
);
2566 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2567 value_lcm(m
, offset
.d
, &offset
.d
);
2568 value_set_si(offset
.x
.n
, 1);
2571 evalue_copy(©
, cst
);
2574 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2576 if (eequal(base
, &e
->x
.p
->arr
[0]))
2577 found
= &e
->x
.p
->arr
[0];
2579 value_set_si(offset
.x
.n
, -2);
2582 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2584 if (eequal(base
, &e
->x
.p
->arr
[0]))
2587 free_evalue_refs(cst
);
2588 free_evalue_refs(&offset
);
2591 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2592 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2597 static evalue
*find_relation_pair(evalue
*e
)
2600 evalue
*found
= NULL
;
2602 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2605 if (e
->x
.p
->type
== fractional
) {
2610 poly_denom(&e
->x
.p
->arr
[0], &m
);
2612 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2613 cst
= &cst
->x
.p
->arr
[0])
2616 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2617 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2622 i
= e
->x
.p
->type
== relation
;
2623 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2624 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2629 void evalue_mod2relation(evalue
*e
) {
2632 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2635 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2636 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2637 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2638 value_clear(e
->x
.p
->arr
[2*i
].d
);
2639 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2641 if (2*i
< e
->x
.p
->size
) {
2642 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2643 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2648 if (e
->x
.p
->size
== 0) {
2650 evalue_set_si(e
, 0, 1);
2656 while ((d
= find_relation_pair(e
)) != NULL
) {
2660 value_init(split
.d
);
2661 value_set_si(split
.d
, 0);
2662 split
.x
.p
= new_enode(relation
, 3, 0);
2663 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2664 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2666 ev
= &split
.x
.p
->arr
[0];
2667 value_set_si(ev
->d
, 0);
2668 ev
->x
.p
= new_enode(fractional
, 3, -1);
2669 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2670 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2671 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2677 free_evalue_refs(&split
);
2681 static int evalue_comp(const void * a
, const void * b
)
2683 const evalue
*e1
= *(const evalue
**)a
;
2684 const evalue
*e2
= *(const evalue
**)b
;
2685 return ecmp(e1
, e2
);
2688 void evalue_combine(evalue
*e
)
2695 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2698 NALLOC(evs
, e
->x
.p
->size
/2);
2699 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2700 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2701 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2702 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2703 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2704 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2705 value_clear(p
->arr
[2*k
].d
);
2706 value_clear(p
->arr
[2*k
+1].d
);
2707 p
->arr
[2*k
] = *(evs
[i
]-1);
2708 p
->arr
[2*k
+1] = *(evs
[i
]);
2711 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2714 value_clear((evs
[i
]-1)->d
);
2718 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2719 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2720 free_evalue_refs(evs
[i
]);
2724 for (i
= 2*k
; i
< p
->size
; ++i
)
2725 value_clear(p
->arr
[i
].d
);
2732 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2734 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2736 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2739 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2740 Polyhedron
*D
, *N
, **P
;
2743 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2750 if (D
->NbEq
<= H
->NbEq
) {
2756 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2757 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2758 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2759 reduce_evalue(&tmp
);
2760 if (value_notzero_p(tmp
.d
) ||
2761 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2764 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2765 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2768 free_evalue_refs(&tmp
);
2774 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2776 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2778 value_clear(e
->x
.p
->arr
[2*i
].d
);
2779 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2781 if (2*i
< e
->x
.p
->size
) {
2782 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2783 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2790 H
= DomainConvex(D
, 0);
2791 E
= DomainDifference(H
, D
, 0);
2793 D
= DomainDifference(H
, E
, 0);
2796 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2800 /* Use smallest representative for coefficients in affine form in
2801 * argument of fractional.
2802 * Since any change will make the argument non-standard,
2803 * the containing evalue will have to be reduced again afterward.
2805 static void fractional_minimal_coefficients(enode
*p
)
2811 assert(p
->type
== fractional
);
2813 while (value_zero_p(pp
->d
)) {
2814 assert(pp
->x
.p
->type
== polynomial
);
2815 assert(pp
->x
.p
->size
== 2);
2816 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2817 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2818 if (value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2819 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2820 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2821 pp
= &pp
->x
.p
->arr
[0];
2827 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2832 unsigned dim
= D
->Dimension
;
2833 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2836 assert(p
->type
== fractional
|| p
->type
== flooring
);
2837 value_set_si(T
->p
[1][dim
], 1);
2838 evalue_extract_affine(&p
->arr
[0], T
->p
[0], &T
->p
[0][dim
], d
);
2839 I
= DomainImage(D
, T
, 0);
2840 H
= DomainConvex(I
, 0);
2850 static void replace_by_affine(evalue
*e
, Value offset
)
2857 value_init(inc
.x
.n
);
2858 value_set_si(inc
.d
, 1);
2859 value_oppose(inc
.x
.n
, offset
);
2860 eadd(&inc
, &p
->arr
[0]);
2861 reorder_terms_about(p
, &p
->arr
[0]); /* frees arr[0] */
2865 free_evalue_refs(&inc
);
2868 int evalue_range_reduction_in_domain(evalue
*e
, Polyhedron
*D
)
2877 if (value_notzero_p(e
->d
))
2882 if (p
->type
== relation
) {
2889 fractional_minimal_coefficients(p
->arr
[0].x
.p
);
2890 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
);
2891 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2892 equal
= value_eq(min
, max
);
2893 mpz_cdiv_q(min
, min
, d
);
2894 mpz_fdiv_q(max
, max
, d
);
2896 if (bounded
&& value_gt(min
, max
)) {
2902 evalue_set_si(e
, 0, 1);
2905 free_evalue_refs(&(p
->arr
[1]));
2906 free_evalue_refs(&(p
->arr
[0]));
2912 return r
? r
: evalue_range_reduction_in_domain(e
, D
);
2913 } else if (bounded
&& equal
) {
2916 free_evalue_refs(&(p
->arr
[2]));
2919 free_evalue_refs(&(p
->arr
[0]));
2925 return evalue_range_reduction_in_domain(e
, D
);
2926 } else if (bounded
&& value_eq(min
, max
)) {
2927 /* zero for a single value */
2929 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2930 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2931 value_multiply(min
, min
, d
);
2932 value_subtract(M
->p
[0][D
->Dimension
+1],
2933 M
->p
[0][D
->Dimension
+1], min
);
2934 E
= DomainAddConstraints(D
, M
, 0);
2940 r
= evalue_range_reduction_in_domain(&p
->arr
[1], E
);
2942 r
|= evalue_range_reduction_in_domain(&p
->arr
[2], D
);
2944 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2952 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2955 i
= p
->type
== relation
? 1 :
2956 p
->type
== fractional
? 1 : 0;
2957 for (; i
<p
->size
; i
++)
2958 r
|= evalue_range_reduction_in_domain(&p
->arr
[i
], D
);
2960 if (p
->type
!= fractional
) {
2961 if (r
&& p
->type
== polynomial
) {
2964 value_set_si(f
.d
, 0);
2965 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2966 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2967 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2968 reorder_terms_about(p
, &f
);
2979 fractional_minimal_coefficients(p
);
2980 I
= polynomial_projection(p
, D
, &d
, NULL
);
2981 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2982 mpz_fdiv_q(min
, min
, d
);
2983 mpz_fdiv_q(max
, max
, d
);
2984 value_subtract(d
, max
, min
);
2986 if (bounded
&& value_eq(min
, max
)) {
2987 replace_by_affine(e
, min
);
2989 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2990 /* replace {g}^2 by -(g-min)^2 + (2{g}+1)*(g-min) - {g}
2991 * See pages 199-200 of PhD thesis.
2999 value_set_si(rem
.d
, 0);
3000 rem
.x
.p
= new_enode(fractional
, 3, -1);
3001 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
3002 value_clear(rem
.x
.p
->arr
[1].d
);
3003 value_clear(rem
.x
.p
->arr
[2].d
);
3004 rem
.x
.p
->arr
[1] = p
->arr
[1];
3005 rem
.x
.p
->arr
[2] = p
->arr
[2];
3006 for (i
= 3; i
< p
->size
; ++i
)
3007 p
->arr
[i
-2] = p
->arr
[i
];
3011 value_init(inc
.x
.n
);
3012 value_set_si(inc
.d
, 1);
3013 value_oppose(inc
.x
.n
, min
);
3016 evalue_copy(&t
, &p
->arr
[0]);
3020 value_set_si(f
.d
, 0);
3021 f
.x
.p
= new_enode(fractional
, 3, -1);
3022 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3023 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3024 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
3026 value_init(factor
.d
);
3027 evalue_set_si(&factor
, -1, 1);
3033 value_clear(f
.x
.p
->arr
[1].x
.n
);
3034 value_clear(f
.x
.p
->arr
[2].x
.n
);
3035 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3036 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3040 reorder_terms(&rem
);
3047 free_evalue_refs(&inc
);
3048 free_evalue_refs(&t
);
3049 free_evalue_refs(&f
);
3050 free_evalue_refs(&factor
);
3051 free_evalue_refs(&rem
);
3053 evalue_range_reduction_in_domain(e
, D
);
3057 _reduce_evalue(&p
->arr
[0], 0, 1);
3069 void evalue_range_reduction(evalue
*e
)
3072 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
3075 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3076 if (evalue_range_reduction_in_domain(&e
->x
.p
->arr
[2*i
+1],
3077 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
3078 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3080 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
3081 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
3082 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3083 value_clear(e
->x
.p
->arr
[2*i
].d
);
3085 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
3086 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
3094 Enumeration
* partition2enumeration(evalue
*EP
)
3097 Enumeration
*en
, *res
= NULL
;
3099 if (EVALUE_IS_ZERO(*EP
)) {
3104 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
3105 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
3106 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
3109 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
3110 value_clear(EP
->x
.p
->arr
[2*i
].d
);
3111 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
3119 int evalue_frac2floor_in_domain3(evalue
*e
, Polyhedron
*D
, int shift
)
3128 if (value_notzero_p(e
->d
))
3133 i
= p
->type
== relation
? 1 :
3134 p
->type
== fractional
? 1 : 0;
3135 for (; i
<p
->size
; i
++)
3136 r
|= evalue_frac2floor_in_domain3(&p
->arr
[i
], D
, shift
);
3138 if (p
->type
!= fractional
) {
3139 if (r
&& p
->type
== polynomial
) {
3142 value_set_si(f
.d
, 0);
3143 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
3144 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
3145 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3146 reorder_terms_about(p
, &f
);
3156 I
= polynomial_projection(p
, D
, &d
, NULL
);
3159 Polyhedron_Print(stderr, P_VALUE_FMT, I);
3162 assert(I
->NbEq
== 0); /* Should have been reduced */
3165 for (i
= 0; i
< I
->NbConstraints
; ++i
)
3166 if (value_pos_p(I
->Constraint
[i
][1]))
3169 if (i
< I
->NbConstraints
) {
3171 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
3172 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
3173 if (value_neg_p(min
)) {
3175 mpz_fdiv_q(min
, min
, d
);
3176 value_init(offset
.d
);
3177 value_set_si(offset
.d
, 1);
3178 value_init(offset
.x
.n
);
3179 value_oppose(offset
.x
.n
, min
);
3180 eadd(&offset
, &p
->arr
[0]);
3181 free_evalue_refs(&offset
);
3191 value_set_si(fl
.d
, 0);
3192 fl
.x
.p
= new_enode(flooring
, 3, -1);
3193 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
3194 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
3195 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
3197 eadd(&fl
, &p
->arr
[0]);
3198 reorder_terms_about(p
, &p
->arr
[0]);
3202 free_evalue_refs(&fl
);
3207 int evalue_frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
3209 return evalue_frac2floor_in_domain3(e
, D
, 1);
3212 void evalue_frac2floor2(evalue
*e
, int shift
)
3215 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
3217 if (evalue_frac2floor_in_domain3(e
, NULL
, 0))
3223 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3224 if (evalue_frac2floor_in_domain3(&e
->x
.p
->arr
[2*i
+1],
3225 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), shift
))
3226 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3229 void evalue_frac2floor(evalue
*e
)
3231 evalue_frac2floor2(e
, 1);
3234 /* Add a new variable with lower bound 1 and upper bound specified
3235 * by row. If negative is true, then the new variable has upper
3236 * bound -1 and lower bound specified by row.
3238 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
3239 Vector
*row
, int negative
)
3243 int nparam
= D
->Dimension
- nvar
;
3246 nr
= D
->NbConstraints
+ 2;
3247 nc
= D
->Dimension
+ 2 + 1;
3248 C
= Matrix_Alloc(nr
, nc
);
3249 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
3250 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
3251 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3252 D
->Dimension
+ 1 - nvar
);
3257 nc
= C
->NbColumns
+ 1;
3258 C
= Matrix_Alloc(nr
, nc
);
3259 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
3260 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
3261 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3262 oldC
->NbColumns
- 1 - nvar
);
3265 value_set_si(C
->p
[nr
-2][0], 1);
3267 value_set_si(C
->p
[nr
-2][1 + nvar
], -1);
3269 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
3270 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
3272 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
3273 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
3279 static void floor2frac_r(evalue
*e
, int nvar
)
3286 if (value_notzero_p(e
->d
))
3291 assert(p
->type
== flooring
);
3292 for (i
= 1; i
< p
->size
; i
++)
3293 floor2frac_r(&p
->arr
[i
], nvar
);
3295 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3296 assert(pp
->x
.p
->type
== polynomial
);
3297 pp
->x
.p
->pos
-= nvar
;
3301 value_set_si(f
.d
, 0);
3302 f
.x
.p
= new_enode(fractional
, 3, -1);
3303 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3304 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3305 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3307 eadd(&f
, &p
->arr
[0]);
3308 reorder_terms_about(p
, &p
->arr
[0]);
3312 free_evalue_refs(&f
);
3315 /* Convert flooring back to fractional and shift position
3316 * of the parameters by nvar
3318 static void floor2frac(evalue
*e
, int nvar
)
3320 floor2frac_r(e
, nvar
);
3324 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
3327 int nparam
= D
->Dimension
- nvar
;
3331 D
= Constraints2Polyhedron(C
, 0);
3335 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3337 /* Double check that D was not unbounded. */
3338 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3346 static evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3347 int *signs
, Matrix
*C
, unsigned MaxRays
)
3353 evalue
*factor
= NULL
;
3357 if (EVALUE_IS_ZERO(*e
))
3361 Polyhedron
*DD
= Disjoint_Domain(D
, 0, MaxRays
);
3368 res
= esum_over_domain(e
, nvar
, Q
, signs
, C
, MaxRays
);
3371 for (Q
= DD
; Q
; Q
= DD
) {
3377 t
= esum_over_domain(e
, nvar
, Q
, signs
, C
, MaxRays
);
3384 free_evalue_refs(t
);
3391 if (value_notzero_p(e
->d
)) {
3394 t
= esum_over_domain_cst(nvar
, D
, C
);
3396 if (!EVALUE_IS_ONE(*e
))
3402 switch (e
->x
.p
->type
) {
3404 evalue
*pp
= &e
->x
.p
->arr
[0];
3406 if (pp
->x
.p
->pos
> nvar
) {
3407 /* remainder is independent of the summated vars */
3413 floor2frac(&f
, nvar
);
3415 t
= esum_over_domain_cst(nvar
, D
, C
);
3419 free_evalue_refs(&f
);
3424 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3425 poly_denom(pp
, &row
->p
[1 + nvar
]);
3426 value_set_si(row
->p
[0], 1);
3427 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3428 pp
= &pp
->x
.p
->arr
[0]) {
3430 assert(pp
->x
.p
->type
== polynomial
);
3432 if (pos
>= 1 + nvar
)
3434 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3435 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3436 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3438 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3439 value_division(row
->p
[1 + D
->Dimension
+ 1],
3440 row
->p
[1 + D
->Dimension
+ 1],
3442 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3443 row
->p
[1 + D
->Dimension
+ 1],
3445 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3449 int pos
= e
->x
.p
->pos
;
3452 factor
= ALLOC(evalue
);
3453 value_init(factor
->d
);
3454 value_set_si(factor
->d
, 0);
3455 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3456 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3457 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3461 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3462 negative
= signs
[pos
-1] < 0;
3463 value_set_si(row
->p
[0], 1);
3465 value_set_si(row
->p
[pos
], -1);
3466 value_set_si(row
->p
[1 + nvar
], 1);
3468 value_set_si(row
->p
[pos
], 1);
3469 value_set_si(row
->p
[1 + nvar
], -1);
3477 offset
= type_offset(e
->x
.p
);
3479 res
= esum_over_domain(&e
->x
.p
->arr
[offset
], nvar
, D
, signs
, C
, MaxRays
);
3483 evalue_copy(&cum
, factor
);
3487 for (i
= 1; offset
+i
< e
->x
.p
->size
; ++i
) {
3491 C
= esum_add_constraint(nvar
, D
, C
, row
, negative
);
3497 Vector_Print(stderr, P_VALUE_FMT, row);
3499 Matrix_Print(stderr, P_VALUE_FMT, C);
3501 t
= esum_over_domain(&e
->x
.p
->arr
[offset
+i
], nvar
, D
, signs
, C
, MaxRays
);
3506 if (negative
&& (i
% 2))
3514 free_evalue_refs(t
);
3517 if (factor
&& offset
+i
+1 < e
->x
.p
->size
)
3524 free_evalue_refs(factor
);
3525 free_evalue_refs(&cum
);
3537 static void domain_signs(Polyhedron
*D
, int *signs
)
3541 POL_ENSURE_VERTICES(D
);
3542 for (j
= 0; j
< D
->Dimension
; ++j
) {
3544 for (k
= 0; k
< D
->NbRays
; ++k
) {
3545 signs
[j
] = value_sign(D
->Ray
[k
][1+j
]);
3552 static void shift_floor_in_domain(evalue
*e
, Polyhedron
*D
)
3559 if (value_notzero_p(e
->d
))
3564 for (i
= type_offset(p
); i
< p
->size
; ++i
)
3565 shift_floor_in_domain(&p
->arr
[i
], D
);
3567 if (p
->type
!= flooring
)
3573 I
= polynomial_projection(p
, D
, &d
, NULL
);
3574 assert(I
->NbEq
== 0); /* Should have been reduced */
3576 for (i
= 0; i
< I
->NbConstraints
; ++i
)
3577 if (value_pos_p(I
->Constraint
[i
][1]))
3579 assert(i
< I
->NbConstraints
);
3580 if (i
< I
->NbConstraints
) {
3581 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
3582 mpz_fdiv_q(m
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
3583 if (value_neg_p(m
)) {
3584 /* replace [e] by [e-m]+m such that e-m >= 0 */
3589 value_set_si(f
.d
, 1);
3590 value_oppose(f
.x
.n
, m
);
3591 eadd(&f
, &p
->arr
[0]);
3594 value_set_si(f
.d
, 0);
3595 f
.x
.p
= new_enode(flooring
, 3, -1);
3596 value_clear(f
.x
.p
->arr
[0].d
);
3597 f
.x
.p
->arr
[0] = p
->arr
[0];
3598 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
3599 value_set_si(f
.x
.p
->arr
[1].d
, 1);
3600 value_init(f
.x
.p
->arr
[1].x
.n
);
3601 value_assign(f
.x
.p
->arr
[1].x
.n
, m
);
3602 reorder_terms_about(p
, &f
);
3613 /* Make arguments of all floors non-negative */
3614 static void shift_floor_arguments(evalue
*e
)
3618 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
3621 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3622 shift_floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
3623 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3626 evalue
*evalue_sum(evalue
*e
, int nvar
, unsigned MaxRays
)
3630 evalue
*res
= ALLOC(evalue
);
3634 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3635 evalue_copy(res
, e
);
3639 evalue_split_domains_into_orthants(e
, MaxRays
);
3640 evalue_frac2floor2(e
, 0);
3641 evalue_set_si(res
, 0, 1);
3643 assert(value_zero_p(e
->d
));
3644 assert(e
->x
.p
->type
== partition
);
3645 shift_floor_arguments(e
);
3647 assert(e
->x
.p
->size
>= 2);
3648 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3650 signs
= alloca(sizeof(int) * dim
);
3652 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3654 domain_signs(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), signs
);
3655 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3656 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), signs
, 0,
3659 free_evalue_refs(t
);
3668 evalue
*esum(evalue
*e
, int nvar
)
3670 return evalue_sum(e
, nvar
, 0);
3673 /* Initial silly implementation */
3674 void eor(evalue
*e1
, evalue
*res
)
3680 evalue_set_si(&mone
, -1, 1);
3682 evalue_copy(&E
, res
);
3688 free_evalue_refs(&E
);
3689 free_evalue_refs(&mone
);
3692 /* computes denominator of polynomial evalue
3693 * d should point to a value initialized to 1
3695 void evalue_denom(const evalue
*e
, Value
*d
)
3699 if (value_notzero_p(e
->d
)) {
3700 value_lcm(*d
, e
->d
, d
);
3703 assert(e
->x
.p
->type
== polynomial
||
3704 e
->x
.p
->type
== fractional
||
3705 e
->x
.p
->type
== flooring
);
3706 offset
= type_offset(e
->x
.p
);
3707 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3708 evalue_denom(&e
->x
.p
->arr
[i
], d
);
3711 /* Divides the evalue e by the integer n */
3712 void evalue_div(evalue
* e
, Value n
)
3716 if (value_notzero_p(e
->d
)) {
3719 value_multiply(e
->d
, e
->d
, n
);
3720 Gcd(e
->x
.n
, e
->d
, &gc
);
3721 if (value_notone_p(gc
)) {
3722 value_division(e
->d
, e
->d
, gc
);
3723 value_division(e
->x
.n
, e
->x
.n
, gc
);
3728 if (e
->x
.p
->type
== partition
) {
3729 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3730 evalue_div(&e
->x
.p
->arr
[2*i
+1], n
);
3733 offset
= type_offset(e
->x
.p
);
3734 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3735 evalue_div(&e
->x
.p
->arr
[i
], n
);
3738 void evalue_negate(evalue
*e
)
3742 if (value_notzero_p(e
->d
)) {
3743 value_oppose(e
->x
.n
, e
->x
.n
);
3746 if (e
->x
.p
->type
== partition
) {
3747 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3748 evalue_negate(&e
->x
.p
->arr
[2*i
+1]);
3751 offset
= type_offset(e
->x
.p
);
3752 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3753 evalue_negate(&e
->x
.p
->arr
[i
]);
3756 void evalue_add_constant(evalue
*e
, const Value cst
)
3760 if (value_zero_p(e
->d
)) {
3761 if (e
->x
.p
->type
== partition
) {
3762 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3763 evalue_add_constant(&e
->x
.p
->arr
[2*i
+1], cst
);
3766 if (e
->x
.p
->type
== relation
) {
3767 for (i
= 1; i
< e
->x
.p
->size
; ++i
)
3768 evalue_add_constant(&e
->x
.p
->arr
[i
], cst
);
3772 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)];
3773 } while (value_zero_p(e
->d
));
3775 value_addmul(e
->x
.n
, cst
, e
->d
);
3778 static void evalue_frac2polynomial_r(evalue
*e
, int *signs
, int sign
, int in_frac
)
3783 int sign_odd
= sign
;
3785 if (value_notzero_p(e
->d
)) {
3786 if (in_frac
&& sign
* value_sign(e
->x
.n
) < 0) {
3787 value_set_si(e
->x
.n
, 0);
3788 value_set_si(e
->d
, 1);
3793 if (e
->x
.p
->type
== relation
) {
3794 for (i
= e
->x
.p
->size
-1; i
>= 1; --i
)
3795 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
, sign
, in_frac
);
3799 if (e
->x
.p
->type
== polynomial
)
3800 sign_odd
*= signs
[e
->x
.p
->pos
-1];
3801 offset
= type_offset(e
->x
.p
);
3802 evalue_frac2polynomial_r(&e
->x
.p
->arr
[offset
], signs
, sign
, in_frac
);
3803 in_frac
|= e
->x
.p
->type
== fractional
;
3804 for (i
= e
->x
.p
->size
-1; i
> offset
; --i
)
3805 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
,
3806 (i
- offset
) % 2 ? sign_odd
: sign
, in_frac
);
3808 if (e
->x
.p
->type
!= fractional
)
3811 /* replace { a/m } by (m-1)/m if sign != 0
3812 * and by (m-1)/(2m) if sign == 0
3816 evalue_denom(&e
->x
.p
->arr
[0], &d
);
3817 free_evalue_refs(&e
->x
.p
->arr
[0]);
3818 value_init(e
->x
.p
->arr
[0].d
);
3819 value_init(e
->x
.p
->arr
[0].x
.n
);
3821 value_addto(e
->x
.p
->arr
[0].d
, d
, d
);
3823 value_assign(e
->x
.p
->arr
[0].d
, d
);
3824 value_decrement(e
->x
.p
->arr
[0].x
.n
, d
);
3828 reorder_terms_about(p
, &p
->arr
[0]);
3834 /* Approximate the evalue in fractional representation by a polynomial.
3835 * If sign > 0, the result is an upper bound;
3836 * if sign < 0, the result is a lower bound;
3837 * if sign = 0, the result is an intermediate approximation.
3839 void evalue_frac2polynomial(evalue
*e
, int sign
, unsigned MaxRays
)
3844 if (value_notzero_p(e
->d
))
3846 assert(e
->x
.p
->type
== partition
);
3847 /* make sure all variables in the domains have a fixed sign */
3849 evalue_split_domains_into_orthants(e
, MaxRays
);
3850 if (EVALUE_IS_ZERO(*e
))
3854 assert(e
->x
.p
->size
>= 2);
3855 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3857 signs
= alloca(sizeof(int) * dim
);
3860 for (i
= 0; i
< dim
; ++i
)
3862 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3864 domain_signs(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), signs
);
3865 evalue_frac2polynomial_r(&e
->x
.p
->arr
[2*i
+1], signs
, sign
, 0);
3869 /* Split the domains of e (which is assumed to be a partition)
3870 * such that each resulting domain lies entirely in one orthant.
3872 void evalue_split_domains_into_orthants(evalue
*e
, unsigned MaxRays
)
3875 assert(value_zero_p(e
->d
));
3876 assert(e
->x
.p
->type
== partition
);
3877 assert(e
->x
.p
->size
>= 2);
3878 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3880 for (i
= 0; i
< dim
; ++i
) {
3883 C
= Matrix_Alloc(1, 1 + dim
+ 1);
3884 value_set_si(C
->p
[0][0], 1);
3885 value_init(split
.d
);
3886 value_set_si(split
.d
, 0);
3887 split
.x
.p
= new_enode(partition
, 4, dim
);
3888 value_set_si(C
->p
[0][1+i
], 1);
3889 C2
= Matrix_Copy(C
);
3890 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[0], Constraints2Polyhedron(C2
, MaxRays
));
3892 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
3893 value_set_si(C
->p
[0][1+i
], -1);
3894 value_set_si(C
->p
[0][1+dim
], -1);
3895 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[2], Constraints2Polyhedron(C
, MaxRays
));
3896 evalue_set_si(&split
.x
.p
->arr
[3], 1, 1);
3898 free_evalue_refs(&split
);
3904 static evalue
*find_fractional_with_max_periods(evalue
*e
, Polyhedron
*D
,
3907 Value
*min
, Value
*max
)
3914 if (value_notzero_p(e
->d
))
3917 if (e
->x
.p
->type
== fractional
) {
3922 I
= polynomial_projection(e
->x
.p
, D
, &d
, &T
);
3923 bounded
= line_minmax(I
, min
, max
); /* frees I */
3927 value_set_si(mp
, max_periods
);
3928 mpz_fdiv_q(*min
, *min
, d
);
3929 mpz_fdiv_q(*max
, *max
, d
);
3930 value_assign(T
->p
[1][D
->Dimension
], d
);
3931 value_subtract(d
, *max
, *min
);
3932 if (value_ge(d
, mp
))
3935 f
= evalue_dup(&e
->x
.p
->arr
[0]);
3946 for (i
= type_offset(e
->x
.p
); i
< e
->x
.p
->size
; ++i
)
3947 if ((f
= find_fractional_with_max_periods(&e
->x
.p
->arr
[i
], D
, max_periods
,
3954 static void replace_fract_by_affine(evalue
*e
, evalue
*f
, Value val
)
3958 if (value_notzero_p(e
->d
))
3961 offset
= type_offset(e
->x
.p
);
3962 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3963 replace_fract_by_affine(&e
->x
.p
->arr
[i
], f
, val
);
3965 if (e
->x
.p
->type
!= fractional
)
3968 if (!eequal(&e
->x
.p
->arr
[0], f
))
3971 replace_by_affine(e
, val
);
3974 /* Look for fractional parts that can be removed by splitting the corresponding
3975 * domain into at most max_periods parts.
3976 * We use a very simply strategy that looks for the first fractional part
3977 * that satisfies the condition, performs the split and then continues
3978 * looking for other fractional parts in the split domains until no
3979 * such fractional part can be found anymore.
3981 void evalue_split_periods(evalue
*e
, int max_periods
, unsigned int MaxRays
)
3988 if (EVALUE_IS_ZERO(*e
))
3990 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
3992 "WARNING: evalue_split_periods called on incorrect evalue type\n");
4000 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
4005 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
4007 f
= find_fractional_with_max_periods(&e
->x
.p
->arr
[2*i
+1], D
, max_periods
,
4012 M
= Matrix_Alloc(2, 2+D
->Dimension
);
4014 value_subtract(d
, max
, min
);
4015 n
= VALUE_TO_INT(d
)+1;
4017 value_set_si(M
->p
[0][0], 1);
4018 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
4019 value_multiply(d
, max
, T
->p
[1][D
->Dimension
]);
4020 value_subtract(M
->p
[0][1+D
->Dimension
], M
->p
[0][1+D
->Dimension
], d
);
4021 value_set_si(d
, -1);
4022 value_set_si(M
->p
[1][0], 1);
4023 Vector_Scale(T
->p
[0], M
->p
[1]+1, d
, D
->Dimension
+1);
4024 value_addmul(M
->p
[1][1+D
->Dimension
], max
, T
->p
[1][D
->Dimension
]);
4025 value_addto(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
],
4026 T
->p
[1][D
->Dimension
]);
4027 value_decrement(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
]);
4029 p
= new_enode(partition
, e
->x
.p
->size
+ (n
-1)*2, e
->x
.p
->pos
);
4030 for (j
= 0; j
< 2*i
; ++j
) {
4031 value_clear(p
->arr
[j
].d
);
4032 p
->arr
[j
] = e
->x
.p
->arr
[j
];
4034 for (j
= 2*i
+2; j
< e
->x
.p
->size
; ++j
) {
4035 value_clear(p
->arr
[j
+2*(n
-1)].d
);
4036 p
->arr
[j
+2*(n
-1)] = e
->x
.p
->arr
[j
];
4038 for (j
= n
-1; j
>= 0; --j
) {
4040 value_clear(p
->arr
[2*i
+1].d
);
4041 p
->arr
[2*i
+1] = e
->x
.p
->arr
[2*i
+1];
4043 evalue_copy(&p
->arr
[2*(i
+j
)+1], &e
->x
.p
->arr
[2*i
+1]);
4045 value_subtract(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
],
4046 T
->p
[1][D
->Dimension
]);
4047 value_addto(M
->p
[0][1+D
->Dimension
], M
->p
[0][1+D
->Dimension
],
4048 T
->p
[1][D
->Dimension
]);
4050 replace_fract_by_affine(&p
->arr
[2*(i
+j
)+1], f
, max
);
4051 E
= DomainAddConstraints(D
, M
, MaxRays
);
4052 EVALUE_SET_DOMAIN(p
->arr
[2*(i
+j
)], E
);
4053 if (evalue_range_reduction_in_domain(&p
->arr
[2*(i
+j
)+1], E
))
4054 reduce_evalue(&p
->arr
[2*(i
+j
)+1]);
4055 value_decrement(max
, max
);
4057 value_clear(e
->x
.p
->arr
[2*i
].d
);
4061 free_evalue_refs(f
);
4073 void evalue_extract_affine(const evalue
*e
, Value
*coeff
, Value
*cst
, Value
*d
)
4075 value_set_si(*d
, 1);
4077 for ( ; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[0]) {
4079 assert(e
->x
.p
->type
== polynomial
);
4080 assert(e
->x
.p
->size
== 2);
4081 c
= &e
->x
.p
->arr
[1];
4082 value_multiply(coeff
[e
->x
.p
->pos
-1], *d
, c
->x
.n
);
4083 value_division(coeff
[e
->x
.p
->pos
-1], coeff
[e
->x
.p
->pos
-1], c
->d
);
4085 value_multiply(*cst
, *d
, e
->x
.n
);
4086 value_division(*cst
, *cst
, e
->d
);
4089 /* returns an evalue that corresponds to
4093 static evalue
*term(int param
, Value c
, Value den
)
4095 evalue
*EP
= ALLOC(evalue
);
4097 value_set_si(EP
->d
,0);
4098 EP
->x
.p
= new_enode(polynomial
, 2, param
+ 1);
4099 evalue_set_si(&EP
->x
.p
->arr
[0], 0, 1);
4100 value_init(EP
->x
.p
->arr
[1].x
.n
);
4101 value_assign(EP
->x
.p
->arr
[1].d
, den
);
4102 value_assign(EP
->x
.p
->arr
[1].x
.n
, c
);
4106 evalue
*affine2evalue(Value
*coeff
, Value denom
, int nvar
)
4109 evalue
*E
= ALLOC(evalue
);
4111 evalue_set(E
, coeff
[nvar
], denom
);
4112 for (i
= 0; i
< nvar
; ++i
) {
4114 if (value_zero_p(coeff
[i
]))
4116 t
= term(i
, coeff
[i
], denom
);
4118 free_evalue_refs(t
);
4124 void evalue_substitute(evalue
*e
, evalue
**subs
)
4130 if (value_notzero_p(e
->d
))
4134 assert(p
->type
!= partition
);
4136 for (i
= 0; i
< p
->size
; ++i
)
4137 evalue_substitute(&p
->arr
[i
], subs
);
4139 if (p
->type
== polynomial
)
4144 value_set_si(v
->d
, 0);
4145 v
->x
.p
= new_enode(p
->type
, 3, -1);
4146 value_clear(v
->x
.p
->arr
[0].d
);
4147 v
->x
.p
->arr
[0] = p
->arr
[0];
4148 evalue_set_si(&v
->x
.p
->arr
[1], 0, 1);
4149 evalue_set_si(&v
->x
.p
->arr
[2], 1, 1);
4152 offset
= type_offset(p
);
4154 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
4155 emul(v
, &p
->arr
[i
]);
4156 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
4157 free_evalue_refs(&(p
->arr
[i
]));
4160 if (p
->type
!= polynomial
) {
4161 free_evalue_refs(v
);
4166 *e
= p
->arr
[offset
];
4170 /* evalue e is given in terms of "new" parameter; CP maps the new
4171 * parameters back to the old parameters.
4172 * Transforms e such that it refers back to the old parameters.
4174 void evalue_backsubstitute(evalue
*e
, Matrix
*CP
, unsigned MaxRays
)
4181 unsigned nparam
= CP
->NbColumns
-1;
4184 if (EVALUE_IS_ZERO(*e
))
4187 assert(value_zero_p(e
->d
));
4189 assert(p
->type
== partition
);
4191 inv
= left_inverse(CP
, &eq
);
4192 subs
= ALLOCN(evalue
*, nparam
);
4193 for (i
= 0; i
< nparam
; ++i
)
4194 subs
[i
] = affine2evalue(inv
->p
[i
], inv
->p
[nparam
][inv
->NbColumns
-1],
4197 CEq
= Constraints2Polyhedron(eq
, MaxRays
);
4198 addeliminatedparams_partition(p
, inv
, CEq
, inv
->NbColumns
-1, MaxRays
);
4199 Polyhedron_Free(CEq
);
4201 for (i
= 0; i
< p
->size
/2; ++i
)
4202 evalue_substitute(&p
->arr
[2*i
+1], subs
);
4204 for (i
= 0; i
< nparam
; ++i
) {
4205 free_evalue_refs(subs
[i
]);
4213 evalue
*evalue_polynomial(Vector
*c
, evalue
* X
)
4215 unsigned dim
= c
->Size
-2;
4217 evalue
*EP
= ALLOC(evalue
);
4221 evalue_set(&EC
, c
->p
[dim
], c
->p
[dim
+1]);
4224 evalue_set(EP
, c
->p
[dim
], c
->p
[dim
+1]);
4226 for (i
= dim
-1; i
>= 0; --i
) {
4228 value_assign(EC
.x
.n
, c
->p
[i
]);
4231 free_evalue_refs(&EC
);