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 (evalue
*e1
, evalue
*res
)
1468 evalue_copy(&ev
, e1
);
1470 free_evalue_refs(res
);
1474 static void emul_poly (evalue
*e1
, evalue
*res
)
1476 int i
, j
, o
= type_offset(res
->x
.p
);
1478 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1480 value_set_si(tmp
.d
,0);
1481 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1483 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1484 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1485 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1486 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1489 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1490 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1491 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1494 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1495 emul(&res
->x
.p
->arr
[i
], &ev
);
1496 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1497 free_evalue_refs(&ev
);
1499 free_evalue_refs(res
);
1503 void emul_partitions (evalue
*e1
,evalue
*res
)
1508 s
= (struct section
*)
1509 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1510 sizeof(struct section
));
1512 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1513 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1514 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1517 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1518 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1519 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1520 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1526 /* This code is only needed because the partitions
1527 are not true partitions.
1529 for (k
= 0; k
< n
; ++k
) {
1530 if (DomainIncludes(s
[k
].D
, d
))
1532 if (DomainIncludes(d
, s
[k
].D
)) {
1533 Domain_Free(s
[k
].D
);
1534 free_evalue_refs(&s
[k
].E
);
1545 value_init(s
[n
].E
.d
);
1546 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1547 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1551 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1552 value_clear(res
->x
.p
->arr
[2*i
].d
);
1553 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1558 evalue_set_si(res
, 0, 1);
1560 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1561 for (j
= 0; j
< n
; ++j
) {
1562 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1563 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1564 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1565 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1572 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1574 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1575 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1576 * evalues is not treated here */
1578 void emul (evalue
*e1
, evalue
*res
){
1581 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1582 fprintf(stderr
, "emul: do not proced on evector type !\n");
1586 if (EVALUE_IS_ZERO(*res
))
1589 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1590 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1591 emul_partitions(e1
, res
);
1594 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1595 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1596 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1598 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1599 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1600 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1601 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1602 explicit_complement(res
);
1603 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1604 explicit_complement(e1
);
1605 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1606 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1609 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1610 emul(e1
, &res
->x
.p
->arr
[i
]);
1612 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1613 switch(e1
->x
.p
->type
) {
1615 switch(res
->x
.p
->type
) {
1617 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1618 /* Product of two polynomials of the same variable */
1623 /* Product of two polynomials of different variables */
1625 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1626 for( i
=0; i
<res
->x
.p
->size
; i
++)
1627 emul(e1
, &res
->x
.p
->arr
[i
]);
1636 /* Product of a polynomial and a periodic or fractional */
1643 switch(res
->x
.p
->type
) {
1645 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1646 /* Product of two periodics of the same parameter and period */
1648 for(i
=0; i
<res
->x
.p
->size
;i
++)
1649 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1654 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1655 /* Product of two periodics of the same parameter and different periods */
1659 value_init(x
); value_init(y
);value_init(z
);
1662 value_set_si(x
,e1
->x
.p
->size
);
1663 value_set_si(y
,res
->x
.p
->size
);
1664 value_assign (z
,*Lcm(x
,y
));
1665 lcm
=(int)mpz_get_si(z
);
1666 newp
= (evalue
*) malloc (sizeof(evalue
));
1667 value_init(newp
->d
);
1668 value_set_si( newp
->d
,0);
1669 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1670 for(i
=0;i
<lcm
;i
++) {
1671 evalue_copy(&newp
->x
.p
->arr
[i
],
1672 &res
->x
.p
->arr
[i
%iy
]);
1675 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1677 value_assign(res
->d
,newp
->d
);
1680 value_clear(x
); value_clear(y
);value_clear(z
);
1684 /* Product of two periodics of different parameters */
1686 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1687 for(i
=0; i
<res
->x
.p
->size
; i
++)
1688 emul(e1
, &(res
->x
.p
->arr
[i
]));
1696 /* Product of a periodic and a polynomial */
1698 for(i
=0; i
<res
->x
.p
->size
; i
++)
1699 emul(e1
, &(res
->x
.p
->arr
[i
]));
1706 switch(res
->x
.p
->type
) {
1708 for(i
=0; i
<res
->x
.p
->size
; i
++)
1709 emul(e1
, &(res
->x
.p
->arr
[i
]));
1716 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1717 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1718 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1721 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1722 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1727 value_set_si(d
.x
.n
, 1);
1728 /* { x }^2 == { x }/2 */
1729 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1730 assert(e1
->x
.p
->size
== 3);
1731 assert(res
->x
.p
->size
== 3);
1733 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1735 eadd(&res
->x
.p
->arr
[1], &tmp
);
1736 emul(&e1
->x
.p
->arr
[2], &tmp
);
1737 emul(&e1
->x
.p
->arr
[1], res
);
1738 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1739 free_evalue_refs(&tmp
);
1744 if(mod_term_smaller(res
, e1
))
1745 for(i
=1; i
<res
->x
.p
->size
; i
++)
1746 emul(e1
, &(res
->x
.p
->arr
[i
]));
1761 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1762 /* Product of two rational numbers */
1766 value_multiply(res
->d
,e1
->d
,res
->d
);
1767 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1768 Gcd(res
->x
.n
, res
->d
,&g
);
1769 if (value_notone_p(g
)) {
1770 value_division(res
->d
,res
->d
,g
);
1771 value_division(res
->x
.n
,res
->x
.n
,g
);
1777 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1778 /* Product of an expression (polynomial or peririodic) and a rational number */
1784 /* Product of a rationel number and an expression (polynomial or peririodic) */
1786 i
= type_offset(res
->x
.p
);
1787 for (; i
<res
->x
.p
->size
; i
++)
1788 emul(e1
, &res
->x
.p
->arr
[i
]);
1798 /* Frees mask content ! */
1799 void emask(evalue
*mask
, evalue
*res
) {
1806 if (EVALUE_IS_ZERO(*res
)) {
1807 free_evalue_refs(mask
);
1811 assert(value_zero_p(mask
->d
));
1812 assert(mask
->x
.p
->type
== partition
);
1813 assert(value_zero_p(res
->d
));
1814 assert(res
->x
.p
->type
== partition
);
1815 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1816 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1817 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1818 pos
= res
->x
.p
->pos
;
1820 s
= (struct section
*)
1821 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1822 sizeof(struct section
));
1826 evalue_set_si(&mone
, -1, 1);
1829 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1830 assert(mask
->x
.p
->size
>= 2);
1831 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1832 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1834 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1836 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1845 value_init(s
[n
].E
.d
);
1846 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1850 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1851 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1854 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1855 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1856 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1857 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1859 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1860 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1866 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1867 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1869 value_init(s
[n
].E
.d
);
1870 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1871 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1877 /* Just ignore; this may have been previously masked off */
1879 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1883 free_evalue_refs(&mone
);
1884 free_evalue_refs(mask
);
1885 free_evalue_refs(res
);
1888 evalue_set_si(res
, 0, 1);
1890 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1891 for (j
= 0; j
< n
; ++j
) {
1892 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1893 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1894 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1901 void evalue_copy(evalue
*dst
, const evalue
*src
)
1903 value_assign(dst
->d
, src
->d
);
1904 if(value_notzero_p(src
->d
)) {
1905 value_init(dst
->x
.n
);
1906 value_assign(dst
->x
.n
, src
->x
.n
);
1908 dst
->x
.p
= ecopy(src
->x
.p
);
1911 enode
*new_enode(enode_type type
,int size
,int pos
) {
1917 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1920 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1924 for(i
=0; i
<size
; i
++) {
1925 value_init(res
->arr
[i
].d
);
1926 value_set_si(res
->arr
[i
].d
,0);
1927 res
->arr
[i
].x
.p
= 0;
1932 enode
*ecopy(enode
*e
) {
1937 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1938 for(i
=0;i
<e
->size
;++i
) {
1939 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1940 if(value_zero_p(res
->arr
[i
].d
))
1941 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1942 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1943 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1945 value_init(res
->arr
[i
].x
.n
);
1946 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1952 int ecmp(const evalue
*e1
, const evalue
*e2
)
1958 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1962 value_multiply(m
, e1
->x
.n
, e2
->d
);
1963 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1965 if (value_lt(m
, m2
))
1967 else if (value_gt(m
, m2
))
1977 if (value_notzero_p(e1
->d
))
1979 if (value_notzero_p(e2
->d
))
1985 if (p1
->type
!= p2
->type
)
1986 return p1
->type
- p2
->type
;
1987 if (p1
->pos
!= p2
->pos
)
1988 return p1
->pos
- p2
->pos
;
1989 if (p1
->size
!= p2
->size
)
1990 return p1
->size
- p2
->size
;
1992 for (i
= p1
->size
-1; i
>= 0; --i
)
1993 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1999 int eequal(const evalue
*e1
, const evalue
*e2
)
2004 if (value_ne(e1
->d
,e2
->d
))
2007 /* e1->d == e2->d */
2008 if (value_notzero_p(e1
->d
)) {
2009 if (value_ne(e1
->x
.n
,e2
->x
.n
))
2012 /* e1->d == e2->d != 0 AND e1->n == e2->n */
2016 /* e1->d == e2->d == 0 */
2019 if (p1
->type
!= p2
->type
) return 0;
2020 if (p1
->size
!= p2
->size
) return 0;
2021 if (p1
->pos
!= p2
->pos
) return 0;
2022 for (i
=0; i
<p1
->size
; i
++)
2023 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
2028 void free_evalue_refs(evalue
*e
) {
2033 if (EVALUE_IS_DOMAIN(*e
)) {
2034 Domain_Free(EVALUE_DOMAIN(*e
));
2037 } else if (value_pos_p(e
->d
)) {
2039 /* 'e' stores a constant */
2041 value_clear(e
->x
.n
);
2044 assert(value_zero_p(e
->d
));
2047 if (!p
) return; /* null pointer */
2048 for (i
=0; i
<p
->size
; i
++) {
2049 free_evalue_refs(&(p
->arr
[i
]));
2053 } /* free_evalue_refs */
2055 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
2056 Vector
* val
, evalue
*res
)
2058 unsigned nparam
= periods
->Size
;
2061 double d
= compute_evalue(e
, val
->p
);
2062 d
*= VALUE_TO_DOUBLE(m
);
2067 value_assign(res
->d
, m
);
2068 value_init(res
->x
.n
);
2069 value_set_double(res
->x
.n
, d
);
2070 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
2073 if (value_one_p(periods
->p
[p
]))
2074 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
2079 value_assign(tmp
, periods
->p
[p
]);
2080 value_set_si(res
->d
, 0);
2081 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
2083 value_decrement(tmp
, tmp
);
2084 value_assign(val
->p
[p
], tmp
);
2085 mod2table_r(e
, periods
, m
, p
+1, val
,
2086 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
2087 } while (value_pos_p(tmp
));
2093 static void rel2table(evalue
*e
, int zero
)
2095 if (value_pos_p(e
->d
)) {
2096 if (value_zero_p(e
->x
.n
) == zero
)
2097 value_set_si(e
->x
.n
, 1);
2099 value_set_si(e
->x
.n
, 0);
2100 value_set_si(e
->d
, 1);
2103 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
2104 rel2table(&e
->x
.p
->arr
[i
], zero
);
2108 void evalue_mod2table(evalue
*e
, int nparam
)
2113 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2116 for (i
=0; i
<p
->size
; i
++) {
2117 evalue_mod2table(&(p
->arr
[i
]), nparam
);
2119 if (p
->type
== relation
) {
2124 evalue_copy(©
, &p
->arr
[0]);
2126 rel2table(&p
->arr
[0], 1);
2127 emul(&p
->arr
[0], &p
->arr
[1]);
2129 rel2table(©
, 0);
2130 emul(©
, &p
->arr
[2]);
2131 eadd(&p
->arr
[2], &p
->arr
[1]);
2132 free_evalue_refs(&p
->arr
[2]);
2133 free_evalue_refs(©
);
2135 free_evalue_refs(&p
->arr
[0]);
2139 } else if (p
->type
== fractional
) {
2140 Vector
*periods
= Vector_Alloc(nparam
);
2141 Vector
*val
= Vector_Alloc(nparam
);
2147 value_set_si(tmp
, 1);
2148 Vector_Set(periods
->p
, 1, nparam
);
2149 Vector_Set(val
->p
, 0, nparam
);
2150 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2153 assert(p
->type
== polynomial
);
2154 assert(p
->size
== 2);
2155 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2156 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
2158 value_lcm(tmp
, ev
->d
, &tmp
);
2160 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2163 evalue_set_si(&res
, 0, 1);
2164 /* Compute the polynomial using Horner's rule */
2165 for (i
=p
->size
-1;i
>1;i
--) {
2166 eadd(&p
->arr
[i
], &res
);
2169 eadd(&p
->arr
[1], &res
);
2171 free_evalue_refs(e
);
2172 free_evalue_refs(&EP
);
2177 Vector_Free(periods
);
2179 } /* evalue_mod2table */
2181 /********************************************************/
2182 /* function in domain */
2183 /* check if the parameters in list_args */
2184 /* verifies the constraints of Domain P */
2185 /********************************************************/
2186 int in_domain(Polyhedron
*P
, Value
*list_args
)
2189 Value v
; /* value of the constraint of a row when
2190 parameters are instantiated*/
2194 for (row
= 0; row
< P
->NbConstraints
; row
++) {
2195 Inner_Product(P
->Constraint
[row
]+1, list_args
, P
->Dimension
, &v
);
2196 value_addto(v
, v
, P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2197 if (value_neg_p(v
) ||
2198 value_zero_p(P
->Constraint
[row
][0]) && value_notzero_p(v
)) {
2205 return in
|| (P
->next
&& in_domain(P
->next
, list_args
));
2208 /****************************************************/
2209 /* function compute enode */
2210 /* compute the value of enode p with parameters */
2211 /* list "list_args */
2212 /* compute the polynomial or the periodic */
2213 /****************************************************/
2215 static double compute_enode(enode
*p
, Value
*list_args
) {
2227 if (p
->type
== polynomial
) {
2229 value_assign(param
,list_args
[p
->pos
-1]);
2231 /* Compute the polynomial using Horner's rule */
2232 for (i
=p
->size
-1;i
>0;i
--) {
2233 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2234 res
*=VALUE_TO_DOUBLE(param
);
2236 res
+=compute_evalue(&p
->arr
[0],list_args
);
2238 else if (p
->type
== fractional
) {
2239 double d
= compute_evalue(&p
->arr
[0], list_args
);
2240 d
-= floor(d
+1e-10);
2242 /* Compute the polynomial using Horner's rule */
2243 for (i
=p
->size
-1;i
>1;i
--) {
2244 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2247 res
+=compute_evalue(&p
->arr
[1],list_args
);
2249 else if (p
->type
== flooring
) {
2250 double d
= compute_evalue(&p
->arr
[0], list_args
);
2253 /* Compute the polynomial using Horner's rule */
2254 for (i
=p
->size
-1;i
>1;i
--) {
2255 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2258 res
+=compute_evalue(&p
->arr
[1],list_args
);
2260 else if (p
->type
== periodic
) {
2261 value_assign(m
,list_args
[p
->pos
-1]);
2263 /* Choose the right element of the periodic */
2264 value_set_si(param
,p
->size
);
2265 value_pmodulus(m
,m
,param
);
2266 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2268 else if (p
->type
== relation
) {
2269 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2270 res
= compute_evalue(&p
->arr
[1], list_args
);
2271 else if (p
->size
> 2)
2272 res
= compute_evalue(&p
->arr
[2], list_args
);
2274 else if (p
->type
== partition
) {
2275 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2276 Value
*vals
= list_args
;
2279 for (i
= 0; i
< dim
; ++i
) {
2280 value_init(vals
[i
]);
2282 value_assign(vals
[i
], list_args
[i
]);
2285 for (i
= 0; i
< p
->size
/2; ++i
)
2286 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2287 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2291 for (i
= 0; i
< dim
; ++i
)
2292 value_clear(vals
[i
]);
2301 } /* compute_enode */
2303 /*************************************************/
2304 /* return the value of Ehrhart Polynomial */
2305 /* It returns a double, because since it is */
2306 /* a recursive function, some intermediate value */
2307 /* might not be integral */
2308 /*************************************************/
2310 double compute_evalue(const evalue
*e
, Value
*list_args
)
2314 if (value_notzero_p(e
->d
)) {
2315 if (value_notone_p(e
->d
))
2316 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2318 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2321 res
= compute_enode(e
->x
.p
,list_args
);
2323 } /* compute_evalue */
2326 /****************************************************/
2327 /* function compute_poly : */
2328 /* Check for the good validity domain */
2329 /* return the number of point in the Polyhedron */
2330 /* in allocated memory */
2331 /* Using the Ehrhart pseudo-polynomial */
2332 /****************************************************/
2333 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2336 /* double d; int i; */
2338 tmp
= (Value
*) malloc (sizeof(Value
));
2339 assert(tmp
!= NULL
);
2341 value_set_si(*tmp
,0);
2344 return(tmp
); /* no ehrhart polynomial */
2345 if(en
->ValidityDomain
) {
2346 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2347 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2352 return(tmp
); /* no Validity Domain */
2354 if(in_domain(en
->ValidityDomain
,list_args
)) {
2356 #ifdef EVAL_EHRHART_DEBUG
2357 Print_Domain(stdout
,en
->ValidityDomain
);
2358 print_evalue(stdout
,&en
->EP
);
2361 /* d = compute_evalue(&en->EP,list_args);
2363 printf("(double)%lf = %d\n", d, i ); */
2364 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2370 value_set_si(*tmp
,0);
2371 return(tmp
); /* no compatible domain with the arguments */
2372 } /* compute_poly */
2374 static evalue
*eval_polynomial(const enode
*p
, int offset
,
2375 evalue
*base
, Value
*values
)
2380 res
= evalue_zero();
2381 for (i
= p
->size
-1; i
> offset
; --i
) {
2382 c
= evalue_eval(&p
->arr
[i
], values
);
2384 free_evalue_refs(c
);
2388 c
= evalue_eval(&p
->arr
[offset
], values
);
2390 free_evalue_refs(c
);
2396 evalue
*evalue_eval(const evalue
*e
, Value
*values
)
2403 if (value_notzero_p(e
->d
)) {
2404 res
= ALLOC(evalue
);
2406 evalue_copy(res
, e
);
2409 switch (e
->x
.p
->type
) {
2411 value_init(param
.x
.n
);
2412 value_assign(param
.x
.n
, values
[e
->x
.p
->pos
-1]);
2413 value_init(param
.d
);
2414 value_set_si(param
.d
, 1);
2416 res
= eval_polynomial(e
->x
.p
, 0, ¶m
, values
);
2417 free_evalue_refs(¶m
);
2420 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2421 mpz_fdiv_r(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2423 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2424 free_evalue_refs(param2
);
2428 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2429 mpz_fdiv_q(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2430 value_set_si(param2
->d
, 1);
2432 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2433 free_evalue_refs(param2
);
2437 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2438 if (value_zero_p(param2
->x
.n
))
2439 res
= evalue_eval(&e
->x
.p
->arr
[1], values
);
2440 else if (e
->x
.p
->size
> 2)
2441 res
= evalue_eval(&e
->x
.p
->arr
[2], values
);
2443 res
= evalue_zero();
2444 free_evalue_refs(param2
);
2448 assert(e
->x
.p
->pos
== EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
);
2449 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2450 if (in_domain(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), values
)) {
2451 res
= evalue_eval(&e
->x
.p
->arr
[2*i
+1], values
);
2455 res
= evalue_zero();
2463 size_t value_size(Value v
) {
2464 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2465 * sizeof(v
[0]._mp_d
[0]);
2468 size_t domain_size(Polyhedron
*D
)
2471 size_t s
= sizeof(*D
);
2473 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2474 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2475 s
+= value_size(D
->Constraint
[i
][j
]);
2478 for (i = 0; i < D->NbRays; ++i)
2479 for (j = 0; j < D->Dimension+2; ++j)
2480 s += value_size(D->Ray[i][j]);
2483 return D
->next
? s
+domain_size(D
->next
) : s
;
2486 size_t enode_size(enode
*p
) {
2487 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2490 if (p
->type
== partition
)
2491 for (i
= 0; i
< p
->size
/2; ++i
) {
2492 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2493 s
+= evalue_size(&p
->arr
[2*i
+1]);
2496 for (i
= 0; i
< p
->size
; ++i
) {
2497 s
+= evalue_size(&p
->arr
[i
]);
2502 size_t evalue_size(evalue
*e
)
2504 size_t s
= sizeof(*e
);
2505 s
+= value_size(e
->d
);
2506 if (value_notzero_p(e
->d
))
2507 s
+= value_size(e
->x
.n
);
2509 s
+= enode_size(e
->x
.p
);
2513 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2515 evalue
*found
= NULL
;
2520 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2523 value_init(offset
.d
);
2524 value_init(offset
.x
.n
);
2525 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2526 value_lcm(m
, offset
.d
, &offset
.d
);
2527 value_set_si(offset
.x
.n
, 1);
2530 evalue_copy(©
, cst
);
2533 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2535 if (eequal(base
, &e
->x
.p
->arr
[0]))
2536 found
= &e
->x
.p
->arr
[0];
2538 value_set_si(offset
.x
.n
, -2);
2541 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2543 if (eequal(base
, &e
->x
.p
->arr
[0]))
2546 free_evalue_refs(cst
);
2547 free_evalue_refs(&offset
);
2550 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2551 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2556 static evalue
*find_relation_pair(evalue
*e
)
2559 evalue
*found
= NULL
;
2561 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2564 if (e
->x
.p
->type
== fractional
) {
2569 poly_denom(&e
->x
.p
->arr
[0], &m
);
2571 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2572 cst
= &cst
->x
.p
->arr
[0])
2575 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2576 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2581 i
= e
->x
.p
->type
== relation
;
2582 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2583 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2588 void evalue_mod2relation(evalue
*e
) {
2591 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2594 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2595 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2596 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2597 value_clear(e
->x
.p
->arr
[2*i
].d
);
2598 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2600 if (2*i
< e
->x
.p
->size
) {
2601 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2602 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2607 if (e
->x
.p
->size
== 0) {
2609 evalue_set_si(e
, 0, 1);
2615 while ((d
= find_relation_pair(e
)) != NULL
) {
2619 value_init(split
.d
);
2620 value_set_si(split
.d
, 0);
2621 split
.x
.p
= new_enode(relation
, 3, 0);
2622 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2623 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2625 ev
= &split
.x
.p
->arr
[0];
2626 value_set_si(ev
->d
, 0);
2627 ev
->x
.p
= new_enode(fractional
, 3, -1);
2628 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2629 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2630 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2636 free_evalue_refs(&split
);
2640 static int evalue_comp(const void * a
, const void * b
)
2642 const evalue
*e1
= *(const evalue
**)a
;
2643 const evalue
*e2
= *(const evalue
**)b
;
2644 return ecmp(e1
, e2
);
2647 void evalue_combine(evalue
*e
)
2654 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2657 NALLOC(evs
, e
->x
.p
->size
/2);
2658 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2659 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2660 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2661 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2662 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2663 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2664 value_clear(p
->arr
[2*k
].d
);
2665 value_clear(p
->arr
[2*k
+1].d
);
2666 p
->arr
[2*k
] = *(evs
[i
]-1);
2667 p
->arr
[2*k
+1] = *(evs
[i
]);
2670 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2673 value_clear((evs
[i
]-1)->d
);
2677 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2678 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2679 free_evalue_refs(evs
[i
]);
2683 for (i
= 2*k
; i
< p
->size
; ++i
)
2684 value_clear(p
->arr
[i
].d
);
2691 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2693 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2695 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2698 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2699 Polyhedron
*D
, *N
, **P
;
2702 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2709 if (D
->NbEq
<= H
->NbEq
) {
2715 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2716 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2717 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2718 reduce_evalue(&tmp
);
2719 if (value_notzero_p(tmp
.d
) ||
2720 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2723 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2724 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2727 free_evalue_refs(&tmp
);
2733 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2735 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2737 value_clear(e
->x
.p
->arr
[2*i
].d
);
2738 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2740 if (2*i
< e
->x
.p
->size
) {
2741 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2742 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2749 H
= DomainConvex(D
, 0);
2750 E
= DomainDifference(H
, D
, 0);
2752 D
= DomainDifference(H
, E
, 0);
2755 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2759 /* Use smallest representative for coefficients in affine form in
2760 * argument of fractional.
2761 * Since any change will make the argument non-standard,
2762 * the containing evalue will have to be reduced again afterward.
2764 static void fractional_minimal_coefficients(enode
*p
)
2770 assert(p
->type
== fractional
);
2772 while (value_zero_p(pp
->d
)) {
2773 assert(pp
->x
.p
->type
== polynomial
);
2774 assert(pp
->x
.p
->size
== 2);
2775 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2776 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2777 if (value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2778 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2779 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2780 pp
= &pp
->x
.p
->arr
[0];
2786 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2791 unsigned dim
= D
->Dimension
;
2792 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2795 assert(p
->type
== fractional
);
2797 value_set_si(T
->p
[1][dim
], 1);
2799 while (value_zero_p(pp
->d
)) {
2800 assert(pp
->x
.p
->type
== polynomial
);
2801 assert(pp
->x
.p
->size
== 2);
2802 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2803 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2804 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2805 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2806 pp
= &pp
->x
.p
->arr
[0];
2808 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2809 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2810 I
= DomainImage(D
, T
, 0);
2811 H
= DomainConvex(I
, 0);
2821 int evalue_range_reduction_in_domain(evalue
*e
, Polyhedron
*D
)
2830 if (value_notzero_p(e
->d
))
2835 if (p
->type
== relation
) {
2842 fractional_minimal_coefficients(p
->arr
[0].x
.p
);
2843 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
);
2844 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2845 equal
= value_eq(min
, max
);
2846 mpz_cdiv_q(min
, min
, d
);
2847 mpz_fdiv_q(max
, max
, d
);
2849 if (bounded
&& value_gt(min
, max
)) {
2855 evalue_set_si(e
, 0, 1);
2858 free_evalue_refs(&(p
->arr
[1]));
2859 free_evalue_refs(&(p
->arr
[0]));
2865 return r
? r
: evalue_range_reduction_in_domain(e
, D
);
2866 } else if (bounded
&& equal
) {
2869 free_evalue_refs(&(p
->arr
[2]));
2872 free_evalue_refs(&(p
->arr
[0]));
2878 return evalue_range_reduction_in_domain(e
, D
);
2879 } else if (bounded
&& value_eq(min
, max
)) {
2880 /* zero for a single value */
2882 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2883 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2884 value_multiply(min
, min
, d
);
2885 value_subtract(M
->p
[0][D
->Dimension
+1],
2886 M
->p
[0][D
->Dimension
+1], min
);
2887 E
= DomainAddConstraints(D
, M
, 0);
2893 r
= evalue_range_reduction_in_domain(&p
->arr
[1], E
);
2895 r
|= evalue_range_reduction_in_domain(&p
->arr
[2], D
);
2897 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2905 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2908 i
= p
->type
== relation
? 1 :
2909 p
->type
== fractional
? 1 : 0;
2910 for (; i
<p
->size
; i
++)
2911 r
|= evalue_range_reduction_in_domain(&p
->arr
[i
], D
);
2913 if (p
->type
!= fractional
) {
2914 if (r
&& p
->type
== polynomial
) {
2917 value_set_si(f
.d
, 0);
2918 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2919 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2920 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2921 reorder_terms_about(p
, &f
);
2932 fractional_minimal_coefficients(p
);
2933 I
= polynomial_projection(p
, D
, &d
, NULL
);
2934 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2935 mpz_fdiv_q(min
, min
, d
);
2936 mpz_fdiv_q(max
, max
, d
);
2937 value_subtract(d
, max
, min
);
2939 if (bounded
&& value_eq(min
, max
)) {
2942 value_init(inc
.x
.n
);
2943 value_set_si(inc
.d
, 1);
2944 value_oppose(inc
.x
.n
, min
);
2945 eadd(&inc
, &p
->arr
[0]);
2946 reorder_terms_about(p
, &p
->arr
[0]); /* frees arr[0] */
2950 free_evalue_refs(&inc
);
2952 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2953 /* replace {g}^2 by -(g-min)^2 + (2{g}+1)*(g-min) - {g}
2954 * See pages 199-200 of PhD thesis.
2962 value_set_si(rem
.d
, 0);
2963 rem
.x
.p
= new_enode(fractional
, 3, -1);
2964 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2965 value_clear(rem
.x
.p
->arr
[1].d
);
2966 value_clear(rem
.x
.p
->arr
[2].d
);
2967 rem
.x
.p
->arr
[1] = p
->arr
[1];
2968 rem
.x
.p
->arr
[2] = p
->arr
[2];
2969 for (i
= 3; i
< p
->size
; ++i
)
2970 p
->arr
[i
-2] = p
->arr
[i
];
2974 value_init(inc
.x
.n
);
2975 value_set_si(inc
.d
, 1);
2976 value_oppose(inc
.x
.n
, min
);
2979 evalue_copy(&t
, &p
->arr
[0]);
2983 value_set_si(f
.d
, 0);
2984 f
.x
.p
= new_enode(fractional
, 3, -1);
2985 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2986 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2987 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2989 value_init(factor
.d
);
2990 evalue_set_si(&factor
, -1, 1);
2996 value_clear(f
.x
.p
->arr
[1].x
.n
);
2997 value_clear(f
.x
.p
->arr
[2].x
.n
);
2998 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2999 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3003 reorder_terms(&rem
);
3010 free_evalue_refs(&inc
);
3011 free_evalue_refs(&t
);
3012 free_evalue_refs(&f
);
3013 free_evalue_refs(&factor
);
3014 free_evalue_refs(&rem
);
3016 evalue_range_reduction_in_domain(e
, D
);
3020 _reduce_evalue(&p
->arr
[0], 0, 1);
3032 void evalue_range_reduction(evalue
*e
)
3035 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
3038 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3039 if (evalue_range_reduction_in_domain(&e
->x
.p
->arr
[2*i
+1],
3040 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
3041 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3043 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
3044 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
3045 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3046 value_clear(e
->x
.p
->arr
[2*i
].d
);
3048 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
3049 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
3057 Enumeration
* partition2enumeration(evalue
*EP
)
3060 Enumeration
*en
, *res
= NULL
;
3062 if (EVALUE_IS_ZERO(*EP
)) {
3067 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
3068 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
3069 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
3072 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
3073 value_clear(EP
->x
.p
->arr
[2*i
].d
);
3074 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
3082 int evalue_frac2floor_in_domain3(evalue
*e
, Polyhedron
*D
, int shift
)
3091 if (value_notzero_p(e
->d
))
3096 i
= p
->type
== relation
? 1 :
3097 p
->type
== fractional
? 1 : 0;
3098 for (; i
<p
->size
; i
++)
3099 r
|= evalue_frac2floor_in_domain3(&p
->arr
[i
], D
, shift
);
3101 if (p
->type
!= fractional
) {
3102 if (r
&& p
->type
== polynomial
) {
3105 value_set_si(f
.d
, 0);
3106 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
3107 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
3108 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3109 reorder_terms_about(p
, &f
);
3119 I
= polynomial_projection(p
, D
, &d
, NULL
);
3122 Polyhedron_Print(stderr, P_VALUE_FMT, I);
3125 assert(I
->NbEq
== 0); /* Should have been reduced */
3128 for (i
= 0; i
< I
->NbConstraints
; ++i
)
3129 if (value_pos_p(I
->Constraint
[i
][1]))
3132 if (i
< I
->NbConstraints
) {
3134 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
3135 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
3136 if (value_neg_p(min
)) {
3138 mpz_fdiv_q(min
, min
, d
);
3139 value_init(offset
.d
);
3140 value_set_si(offset
.d
, 1);
3141 value_init(offset
.x
.n
);
3142 value_oppose(offset
.x
.n
, min
);
3143 eadd(&offset
, &p
->arr
[0]);
3144 free_evalue_refs(&offset
);
3154 value_set_si(fl
.d
, 0);
3155 fl
.x
.p
= new_enode(flooring
, 3, -1);
3156 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
3157 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
3158 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
3160 eadd(&fl
, &p
->arr
[0]);
3161 reorder_terms_about(p
, &p
->arr
[0]);
3165 free_evalue_refs(&fl
);
3170 int evalue_frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
3172 return evalue_frac2floor_in_domain3(e
, D
, 1);
3175 void evalue_frac2floor2(evalue
*e
, int shift
)
3178 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
3180 if (evalue_frac2floor_in_domain3(e
, NULL
, 0))
3186 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3187 if (evalue_frac2floor_in_domain3(&e
->x
.p
->arr
[2*i
+1],
3188 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), shift
))
3189 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3192 void evalue_frac2floor(evalue
*e
)
3194 evalue_frac2floor2(e
, 1);
3197 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
3202 int nparam
= D
->Dimension
- nvar
;
3205 nr
= D
->NbConstraints
+ 2;
3206 nc
= D
->Dimension
+ 2 + 1;
3207 C
= Matrix_Alloc(nr
, nc
);
3208 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
3209 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
3210 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3211 D
->Dimension
+ 1 - nvar
);
3216 nc
= C
->NbColumns
+ 1;
3217 C
= Matrix_Alloc(nr
, nc
);
3218 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
3219 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
3220 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3221 oldC
->NbColumns
- 1 - nvar
);
3224 value_set_si(C
->p
[nr
-2][0], 1);
3225 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
3226 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
3228 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
3229 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
3235 static void floor2frac_r(evalue
*e
, int nvar
)
3242 if (value_notzero_p(e
->d
))
3247 assert(p
->type
== flooring
);
3248 for (i
= 1; i
< p
->size
; i
++)
3249 floor2frac_r(&p
->arr
[i
], nvar
);
3251 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3252 assert(pp
->x
.p
->type
== polynomial
);
3253 pp
->x
.p
->pos
-= nvar
;
3257 value_set_si(f
.d
, 0);
3258 f
.x
.p
= new_enode(fractional
, 3, -1);
3259 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3260 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3261 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3263 eadd(&f
, &p
->arr
[0]);
3264 reorder_terms_about(p
, &p
->arr
[0]);
3268 free_evalue_refs(&f
);
3271 /* Convert flooring back to fractional and shift position
3272 * of the parameters by nvar
3274 static void floor2frac(evalue
*e
, int nvar
)
3276 floor2frac_r(e
, nvar
);
3280 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
3283 int nparam
= D
->Dimension
- nvar
;
3287 D
= Constraints2Polyhedron(C
, 0);
3291 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3293 /* Double check that D was not unbounded. */
3294 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3302 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3309 evalue
*factor
= NULL
;
3312 if (EVALUE_IS_ZERO(*e
))
3316 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
3323 res
= esum_over_domain(e
, nvar
, Q
, C
);
3326 for (Q
= DD
; Q
; Q
= DD
) {
3332 t
= esum_over_domain(e
, nvar
, Q
, C
);
3339 free_evalue_refs(t
);
3346 if (value_notzero_p(e
->d
)) {
3349 t
= esum_over_domain_cst(nvar
, D
, C
);
3351 if (!EVALUE_IS_ONE(*e
))
3357 switch (e
->x
.p
->type
) {
3359 evalue
*pp
= &e
->x
.p
->arr
[0];
3361 if (pp
->x
.p
->pos
> nvar
) {
3362 /* remainder is independent of the summated vars */
3368 floor2frac(&f
, nvar
);
3370 t
= esum_over_domain_cst(nvar
, D
, C
);
3374 free_evalue_refs(&f
);
3379 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3380 poly_denom(pp
, &row
->p
[1 + nvar
]);
3381 value_set_si(row
->p
[0], 1);
3382 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3383 pp
= &pp
->x
.p
->arr
[0]) {
3385 assert(pp
->x
.p
->type
== polynomial
);
3387 if (pos
>= 1 + nvar
)
3389 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3390 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3391 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3393 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3394 value_division(row
->p
[1 + D
->Dimension
+ 1],
3395 row
->p
[1 + D
->Dimension
+ 1],
3397 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3398 row
->p
[1 + D
->Dimension
+ 1],
3400 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3404 int pos
= e
->x
.p
->pos
;
3407 factor
= ALLOC(evalue
);
3408 value_init(factor
->d
);
3409 value_set_si(factor
->d
, 0);
3410 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3411 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3412 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3416 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3417 for (i
= 0; i
< D
->NbRays
; ++i
)
3418 if (value_notzero_p(D
->Ray
[i
][pos
]))
3420 assert(i
< D
->NbRays
);
3421 if (value_neg_p(D
->Ray
[i
][pos
])) {
3422 factor
= ALLOC(evalue
);
3423 value_init(factor
->d
);
3424 evalue_set_si(factor
, -1, 1);
3426 value_set_si(row
->p
[0], 1);
3427 value_set_si(row
->p
[pos
], 1);
3428 value_set_si(row
->p
[1 + nvar
], -1);
3435 i
= type_offset(e
->x
.p
);
3437 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3442 evalue_copy(&cum
, factor
);
3446 for (; i
< e
->x
.p
->size
; ++i
) {
3450 C
= esum_add_constraint(nvar
, D
, C
, row
);
3456 Vector_Print(stderr, P_VALUE_FMT, row);
3458 Matrix_Print(stderr, P_VALUE_FMT, C);
3460 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3469 free_evalue_refs(t
);
3472 if (factor
&& i
+1 < e
->x
.p
->size
)
3479 free_evalue_refs(factor
);
3480 free_evalue_refs(&cum
);
3492 evalue
*esum(evalue
*e
, int nvar
)
3495 evalue
*res
= ALLOC(evalue
);
3499 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3500 evalue_copy(res
, e
);
3504 evalue_set_si(res
, 0, 1);
3506 assert(value_zero_p(e
->d
));
3507 assert(e
->x
.p
->type
== partition
);
3509 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3511 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3512 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3514 free_evalue_refs(t
);
3523 /* Initial silly implementation */
3524 void eor(evalue
*e1
, evalue
*res
)
3530 evalue_set_si(&mone
, -1, 1);
3532 evalue_copy(&E
, res
);
3538 free_evalue_refs(&E
);
3539 free_evalue_refs(&mone
);
3542 /* computes denominator of polynomial evalue
3543 * d should point to a value initialized to 1
3545 void evalue_denom(const evalue
*e
, Value
*d
)
3549 if (value_notzero_p(e
->d
)) {
3550 value_lcm(*d
, e
->d
, d
);
3553 assert(e
->x
.p
->type
== polynomial
||
3554 e
->x
.p
->type
== fractional
||
3555 e
->x
.p
->type
== flooring
);
3556 offset
= type_offset(e
->x
.p
);
3557 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3558 evalue_denom(&e
->x
.p
->arr
[i
], d
);
3561 /* Divides the evalue e by the integer n */
3562 void evalue_div(evalue
* e
, Value n
)
3566 if (value_notzero_p(e
->d
)) {
3569 value_multiply(e
->d
, e
->d
, n
);
3570 Gcd(e
->x
.n
, e
->d
, &gc
);
3571 if (value_notone_p(gc
)) {
3572 value_division(e
->d
, e
->d
, gc
);
3573 value_division(e
->x
.n
, e
->x
.n
, gc
);
3578 if (e
->x
.p
->type
== partition
) {
3579 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3580 evalue_div(&e
->x
.p
->arr
[2*i
+1], n
);
3583 offset
= type_offset(e
->x
.p
);
3584 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3585 evalue_div(&e
->x
.p
->arr
[i
], n
);
3588 static void evalue_frac2polynomial_r(evalue
*e
, int *signs
, int sign
, int in_frac
)
3593 int sign_odd
= sign
;
3595 if (value_notzero_p(e
->d
)) {
3596 if (in_frac
&& sign
* value_sign(e
->x
.n
) < 0) {
3597 value_set_si(e
->x
.n
, 0);
3598 value_set_si(e
->d
, 1);
3603 if (e
->x
.p
->type
== relation
) {
3604 for (i
= e
->x
.p
->size
-1; i
>= 1; --i
)
3605 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
, sign
, in_frac
);
3609 if (e
->x
.p
->type
== polynomial
)
3610 sign_odd
*= signs
[e
->x
.p
->pos
-1];
3611 offset
= type_offset(e
->x
.p
);
3612 evalue_frac2polynomial_r(&e
->x
.p
->arr
[offset
], signs
, sign
, in_frac
);
3613 in_frac
|= e
->x
.p
->type
== fractional
;
3614 for (i
= e
->x
.p
->size
-1; i
> offset
; --i
)
3615 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
,
3616 (i
- offset
) % 2 ? sign_odd
: sign
, in_frac
);
3618 if (e
->x
.p
->type
!= fractional
)
3621 /* replace { a/m } by (m-1)/m if sign != 0
3622 * and by (m-1)/(2m) if sign == 0
3626 evalue_denom(&e
->x
.p
->arr
[0], &d
);
3627 free_evalue_refs(&e
->x
.p
->arr
[0]);
3628 value_init(e
->x
.p
->arr
[0].d
);
3629 value_init(e
->x
.p
->arr
[0].x
.n
);
3631 value_addto(e
->x
.p
->arr
[0].d
, d
, d
);
3633 value_assign(e
->x
.p
->arr
[0].d
, d
);
3634 value_decrement(e
->x
.p
->arr
[0].x
.n
, d
);
3638 reorder_terms_about(p
, &p
->arr
[0]);
3644 /* Approximate the evalue in fractional representation by a polynomial.
3645 * If sign > 0, the result is an upper bound;
3646 * if sign < 0, the result is a lower bound;
3647 * if sign = 0, the result is an intermediate approximation.
3649 void evalue_frac2polynomial(evalue
*e
, int sign
, unsigned MaxRays
)
3654 if (value_notzero_p(e
->d
))
3656 assert(e
->x
.p
->type
== partition
);
3657 /* make sure all variables in the domains have a fixed sign */
3659 evalue_split_domains_into_orthants(e
, MaxRays
);
3661 assert(e
->x
.p
->size
>= 2);
3662 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3664 signs
= alloca(sizeof(int) * dim
);
3666 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3667 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
3668 POL_ENSURE_VERTICES(D
);
3669 for (j
= 0; j
< dim
; ++j
) {
3673 for (k
= 0; k
< D
->NbRays
; ++k
) {
3674 signs
[j
] = value_sign(D
->Ray
[k
][1+j
]);
3679 evalue_frac2polynomial_r(&e
->x
.p
->arr
[2*i
+1], signs
, sign
, 0);
3683 /* Split the domains of e (which is assumed to be a partition)
3684 * such that each resulting domain lies entirely in one orthant.
3686 void evalue_split_domains_into_orthants(evalue
*e
, unsigned MaxRays
)
3689 assert(value_zero_p(e
->d
));
3690 assert(e
->x
.p
->type
== partition
);
3691 assert(e
->x
.p
->size
>= 2);
3692 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3694 for (i
= 0; i
< dim
; ++i
) {
3697 C
= Matrix_Alloc(1, 1 + dim
+ 1);
3698 value_set_si(C
->p
[0][0], 1);
3699 value_init(split
.d
);
3700 value_set_si(split
.d
, 0);
3701 split
.x
.p
= new_enode(partition
, 4, dim
);
3702 value_set_si(C
->p
[0][1+i
], 1);
3703 C2
= Matrix_Copy(C
);
3704 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[0], Constraints2Polyhedron(C2
, MaxRays
));
3706 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
3707 value_set_si(C
->p
[0][1+i
], -1);
3708 value_set_si(C
->p
[0][1+dim
], -1);
3709 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[2], Constraints2Polyhedron(C
, MaxRays
));
3710 evalue_set_si(&split
.x
.p
->arr
[3], 1, 1);
3712 free_evalue_refs(&split
);
3717 static Matrix
*find_fractional_with_max_periods(evalue
*e
, Polyhedron
*D
,
3719 Value
*min
, Value
*max
)
3725 if (value_notzero_p(e
->d
))
3728 if (e
->x
.p
->type
== fractional
) {
3733 I
= polynomial_projection(e
->x
.p
, D
, &d
, &T
);
3734 bounded
= line_minmax(I
, min
, max
); /* frees I */
3738 value_set_si(mp
, max_periods
);
3739 mpz_fdiv_q(*min
, *min
, d
);
3740 mpz_fdiv_q(*max
, *max
, d
);
3741 value_assign(T
->p
[1][D
->Dimension
], d
);
3742 value_subtract(d
, *max
, *min
);
3743 if (value_ge(d
, mp
)) {
3757 for (i
= type_offset(e
->x
.p
); i
< e
->x
.p
->size
; ++i
)
3758 if ((T
= find_fractional_with_max_periods(&e
->x
.p
->arr
[i
], D
, max_periods
,
3765 /* Look for fractional parts that can be removed by splitting the corresponding
3766 * domain into at most max_periods parts.
3767 * We use a very simply strategy that looks for the first fractional part
3768 * that satisfies the condition, performs the split and then continues
3769 * looking for other fractional parts in the split domains until no
3770 * such fractional part can be found anymore.
3772 void evalue_split_periods(evalue
*e
, int max_periods
, unsigned int MaxRays
)
3779 if (EVALUE_IS_ZERO(*e
))
3781 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
3783 "WARNING: evalue_split_periods called on incorrect evalue type\n");
3791 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3795 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
3797 T
= find_fractional_with_max_periods(&e
->x
.p
->arr
[2*i
+1], D
, max_periods
,
3802 M
= Matrix_Alloc(2, 2+D
->Dimension
);
3804 value_subtract(d
, max
, min
);
3805 n
= VALUE_TO_INT(d
)+1;
3807 value_set_si(M
->p
[0][0], 1);
3808 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
3809 value_multiply(d
, max
, T
->p
[1][D
->Dimension
]);
3810 value_subtract(M
->p
[0][1+D
->Dimension
], M
->p
[0][1+D
->Dimension
], d
);
3811 value_set_si(d
, -1);
3812 value_set_si(M
->p
[1][0], 1);
3813 Vector_Scale(T
->p
[0], M
->p
[1]+1, d
, D
->Dimension
+1);
3814 value_addmul(M
->p
[1][1+D
->Dimension
], max
, T
->p
[1][D
->Dimension
]);
3815 value_addto(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
],
3816 T
->p
[1][D
->Dimension
]);
3817 value_decrement(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
]);
3819 p
= new_enode(partition
, e
->x
.p
->size
+ (n
-1)*2, e
->x
.p
->pos
);
3820 for (j
= 0; j
< 2*i
; ++j
) {
3821 value_clear(p
->arr
[j
].d
);
3822 p
->arr
[j
] = e
->x
.p
->arr
[j
];
3824 for (j
= 2*i
+2; j
< e
->x
.p
->size
; ++j
) {
3825 value_clear(p
->arr
[j
+2*(n
-1)].d
);
3826 p
->arr
[j
+2*(n
-1)] = e
->x
.p
->arr
[j
];
3828 for (j
= n
-1; j
>= 0; --j
) {
3830 value_clear(p
->arr
[2*i
+1].d
);
3831 p
->arr
[2*i
+1] = e
->x
.p
->arr
[2*i
+1];
3833 evalue_copy(&p
->arr
[2*(i
+j
)+1], &e
->x
.p
->arr
[2*i
+1]);
3835 value_subtract(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
],
3836 T
->p
[1][D
->Dimension
]);
3837 value_addto(M
->p
[0][1+D
->Dimension
], M
->p
[0][1+D
->Dimension
],
3838 T
->p
[1][D
->Dimension
]);
3840 E
= DomainAddConstraints(D
, M
, MaxRays
);
3841 EVALUE_SET_DOMAIN(p
->arr
[2*(i
+j
)], E
);
3842 if (evalue_range_reduction_in_domain(&p
->arr
[2*(i
+j
)+1], E
))
3843 reduce_evalue(&p
->arr
[2*(i
+j
)+1]);
3845 value_clear(e
->x
.p
->arr
[2*i
].d
);
3859 void evalue_extract_affine(const evalue
*e
, Value
*coeff
, Value
*cst
, Value
*d
)
3861 value_set_si(*d
, 1);
3863 for ( ; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[0]) {
3865 assert(e
->x
.p
->type
== polynomial
);
3866 assert(e
->x
.p
->size
== 2);
3867 c
= &e
->x
.p
->arr
[1];
3868 value_multiply(coeff
[e
->x
.p
->pos
-1], *d
, c
->x
.n
);
3869 value_division(coeff
[e
->x
.p
->pos
-1], coeff
[e
->x
.p
->pos
-1], c
->d
);
3871 value_multiply(*cst
, *d
, e
->x
.n
);
3872 value_division(*cst
, *cst
, e
->d
);
3875 /* returns an evalue that corresponds to
3879 static evalue
*term(int param
, Value c
, Value den
)
3881 evalue
*EP
= ALLOC(evalue
);
3883 value_set_si(EP
->d
,0);
3884 EP
->x
.p
= new_enode(polynomial
, 2, param
+ 1);
3885 evalue_set_si(&EP
->x
.p
->arr
[0], 0, 1);
3886 value_init(EP
->x
.p
->arr
[1].x
.n
);
3887 value_assign(EP
->x
.p
->arr
[1].d
, den
);
3888 value_assign(EP
->x
.p
->arr
[1].x
.n
, c
);
3892 evalue
*affine2evalue(Value
*coeff
, Value denom
, int nvar
)
3895 evalue
*E
= ALLOC(evalue
);
3897 evalue_set(E
, coeff
[nvar
], denom
);
3898 for (i
= 0; i
< nvar
; ++i
) {
3899 evalue
*t
= term(i
, coeff
[i
], denom
);
3901 free_evalue_refs(t
);
3907 void evalue_substitute(evalue
*e
, evalue
**subs
)
3913 if (value_notzero_p(e
->d
))
3917 assert(p
->type
!= partition
);
3919 for (i
= 0; i
< p
->size
; ++i
)
3920 evalue_substitute(&p
->arr
[i
], subs
);
3922 if (p
->type
== polynomial
)
3927 value_set_si(v
->d
, 0);
3928 v
->x
.p
= new_enode(p
->type
, 3, -1);
3929 value_clear(v
->x
.p
->arr
[0].d
);
3930 v
->x
.p
->arr
[0] = p
->arr
[0];
3931 evalue_set_si(&v
->x
.p
->arr
[1], 0, 1);
3932 evalue_set_si(&v
->x
.p
->arr
[2], 1, 1);
3935 offset
= type_offset(p
);
3937 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
3938 emul(v
, &p
->arr
[i
]);
3939 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
3940 free_evalue_refs(&(p
->arr
[i
]));
3943 if (p
->type
!= polynomial
) {
3944 free_evalue_refs(v
);
3949 *e
= p
->arr
[offset
];
3953 /* evalue e is given in terms of "new" parameter; CP maps the new
3954 * parameters back to the old parameters.
3955 * Transforms e such that it refers back to the old parameters.
3957 void evalue_backsubstitute(evalue
*e
, Matrix
*CP
, unsigned MaxRays
)
3964 unsigned nparam
= CP
->NbColumns
-1;
3967 if (EVALUE_IS_ZERO(*e
))
3970 assert(value_zero_p(e
->d
));
3972 assert(p
->type
== partition
);
3974 inv
= left_inverse(CP
, &eq
);
3975 subs
= ALLOCN(evalue
*, nparam
);
3976 for (i
= 0; i
< nparam
; ++i
)
3977 subs
[i
] = affine2evalue(inv
->p
[i
], inv
->p
[nparam
][inv
->NbColumns
-1],
3980 CEq
= Constraints2Polyhedron(eq
, MaxRays
);
3981 addeliminatedparams_partition(p
, inv
, CEq
, inv
->NbColumns
-1, MaxRays
);
3982 Polyhedron_Free(CEq
);
3984 for (i
= 0; i
< p
->size
/2; ++i
)
3985 evalue_substitute(&p
->arr
[2*i
+1], subs
);
3987 for (i
= 0; i
< nparam
; ++i
) {
3988 free_evalue_refs(subs
[i
]);