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))
26 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
28 #define NALLOC(p,n) p = (void *)malloc((n) * sizeof(*p))
31 void evalue_set_si(evalue
*ev
, int n
, int d
) {
32 value_set_si(ev
->d
, d
);
34 value_set_si(ev
->x
.n
, n
);
37 void evalue_set(evalue
*ev
, Value n
, Value d
) {
38 value_assign(ev
->d
, d
);
40 value_assign(ev
->x
.n
, n
);
45 evalue
*EP
= ALLOC(evalue
);
47 evalue_set_si(EP
, 0, 1);
51 void aep_evalue(evalue
*e
, int *ref
) {
56 if (value_notzero_p(e
->d
))
57 return; /* a rational number, its already reduced */
59 return; /* hum... an overflow probably occured */
61 /* First check the components of p */
62 for (i
=0;i
<p
->size
;i
++)
63 aep_evalue(&p
->arr
[i
],ref
);
70 p
->pos
= ref
[p
->pos
-1]+1;
76 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
82 if (value_notzero_p(e
->d
))
83 return; /* a rational number, its already reduced */
85 return; /* hum... an overflow probably occured */
88 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
89 for(i
=0;i
<CT
->NbRows
-1;i
++)
90 for(j
=0;j
<CT
->NbColumns
;j
++)
91 if(value_notzero_p(CT
->p
[i
][j
])) {
96 /* Transform the references in e, using ref */
100 } /* addeliminatedparams_evalue */
102 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
103 unsigned MaxRays
, unsigned nparam
)
108 if (CT
->NbRows
== CT
->NbColumns
)
111 if (EVALUE_IS_ZERO(*e
))
114 if (value_notzero_p(e
->d
)) {
117 value_set_si(res
.d
, 0);
118 res
.x
.p
= new_enode(partition
, 2, nparam
);
119 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
120 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
121 value_clear(res
.x
.p
->arr
[1].d
);
122 res
.x
.p
->arr
[1] = *e
;
129 assert(p
->type
== partition
);
132 for (i
=0; i
<p
->size
/2; i
++) {
133 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
134 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
137 T
= DomainIntersection(D
, CEq
, MaxRays
);
139 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
140 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
144 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
152 assert(value_notzero_p(e1
->d
));
153 assert(value_notzero_p(e2
->d
));
154 value_multiply(m
, e1
->x
.n
, e2
->d
);
155 value_multiply(m2
, e2
->x
.n
, e1
->d
);
158 else if (value_gt(m
, m2
))
168 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
170 if (value_notzero_p(e1
->d
)) {
172 if (value_zero_p(e2
->d
))
174 r
= mod_rational_smaller(e1
, e2
);
175 return r
== -1 ? 0 : r
;
177 if (value_notzero_p(e2
->d
))
179 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
181 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
184 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
186 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
191 static int mod_term_smaller(const evalue
*e1
, const evalue
*e2
)
193 assert(value_zero_p(e1
->d
));
194 assert(value_zero_p(e2
->d
));
195 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
196 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
197 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
200 static void check_order(const evalue
*e
)
205 if (value_notzero_p(e
->d
))
208 switch (e
->x
.p
->type
) {
210 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
211 check_order(&e
->x
.p
->arr
[2*i
+1]);
214 for (i
= 1; i
< e
->x
.p
->size
; ++i
) {
216 if (value_notzero_p(a
->d
))
218 switch (a
->x
.p
->type
) {
220 assert(mod_term_smaller(&e
->x
.p
->arr
[0], &a
->x
.p
->arr
[0]));
229 for (i
= 0; i
< e
->x
.p
->size
; ++i
) {
231 if (value_notzero_p(a
->d
))
233 switch (a
->x
.p
->type
) {
235 assert(e
->x
.p
->pos
< a
->x
.p
->pos
);
246 for (i
= 1; i
< e
->x
.p
->size
; ++i
) {
248 if (value_notzero_p(a
->d
))
250 switch (a
->x
.p
->type
) {
261 /* Negative pos means inequality */
262 /* s is negative of substitution if m is not zero */
271 struct fixed_param
*fixed
;
276 static int relations_depth(evalue
*e
)
281 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
282 e
= &e
->x
.p
->arr
[1], ++d
);
286 static void poly_denom_not_constant(evalue
**pp
, Value
*d
)
291 while (value_zero_p(p
->d
)) {
292 assert(p
->x
.p
->type
== polynomial
);
293 assert(p
->x
.p
->size
== 2);
294 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
295 value_lcm(*d
, p
->x
.p
->arr
[1].d
, d
);
301 static void poly_denom(evalue
*p
, Value
*d
)
303 poly_denom_not_constant(&p
, d
);
304 value_lcm(*d
, p
->d
, d
);
307 static void realloc_substitution(struct subst
*s
, int d
)
309 struct fixed_param
*n
;
312 for (i
= 0; i
< s
->n
; ++i
)
319 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
325 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
328 /* May have been reduced already */
329 if (value_notzero_p(m
->d
))
332 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
333 assert(m
->x
.p
->size
== 3);
335 /* fractional was inverted during reduction
336 * invert it back and move constant in
338 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
339 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
340 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
341 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
342 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
343 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
344 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
345 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
346 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
347 value_set_si(m
->x
.p
->arr
[1].d
, 1);
350 /* Oops. Nested identical relations. */
351 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
354 if (s
->n
>= s
->max
) {
355 int d
= relations_depth(r
);
356 realloc_substitution(s
, d
);
360 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
361 assert(p
->x
.p
->size
== 2);
364 assert(value_pos_p(f
->x
.n
));
366 value_init(s
->fixed
[s
->n
].m
);
367 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
368 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
369 value_init(s
->fixed
[s
->n
].d
);
370 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
371 value_init(s
->fixed
[s
->n
].s
.d
);
372 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
378 static int type_offset(enode
*p
)
380 return p
->type
== fractional
? 1 :
381 p
->type
== flooring
? 1 : 0;
384 static void reorder_terms_about(enode
*p
, evalue
*v
)
387 int offset
= type_offset(p
);
389 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
391 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
392 free_evalue_refs(&(p
->arr
[i
]));
398 static void reorder_terms(evalue
*e
)
403 assert(value_zero_p(e
->d
));
405 assert(p
->type
= fractional
); /* for now */
408 value_set_si(f
.d
, 0);
409 f
.x
.p
= new_enode(fractional
, 3, -1);
410 value_clear(f
.x
.p
->arr
[0].d
);
411 f
.x
.p
->arr
[0] = p
->arr
[0];
412 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
413 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
414 reorder_terms_about(p
, &f
);
420 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
426 if (value_notzero_p(e
->d
)) {
428 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
429 return; /* a rational number, its already reduced */
433 return; /* hum... an overflow probably occured */
435 /* First reduce the components of p */
436 add
= p
->type
== relation
;
437 for (i
=0; i
<p
->size
; i
++) {
439 add
= add_modulo_substitution(s
, e
);
441 if (i
== 0 && p
->type
==fractional
)
442 _reduce_evalue(&p
->arr
[i
], s
, 1);
444 _reduce_evalue(&p
->arr
[i
], s
, fract
);
446 if (add
&& i
== p
->size
-1) {
448 value_clear(s
->fixed
[s
->n
].m
);
449 value_clear(s
->fixed
[s
->n
].d
);
450 free_evalue_refs(&s
->fixed
[s
->n
].s
);
451 } else if (add
&& i
== 1)
452 s
->fixed
[s
->n
-1].pos
*= -1;
455 if (p
->type
==periodic
) {
457 /* Try to reduce the period */
458 for (i
=1; i
<=(p
->size
)/2; i
++) {
459 if ((p
->size
% i
)==0) {
461 /* Can we reduce the size to i ? */
463 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
464 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
467 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
471 you_lose
: /* OK, lets not do it */
476 /* Try to reduce its strength */
479 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
483 else if (p
->type
==polynomial
) {
484 for (k
= 0; s
&& k
< s
->n
; ++k
) {
485 if (s
->fixed
[k
].pos
== p
->pos
) {
486 int divide
= value_notone_p(s
->fixed
[k
].d
);
489 if (value_notzero_p(s
->fixed
[k
].m
)) {
492 assert(p
->size
== 2);
493 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
495 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
502 value_assign(d
.d
, s
->fixed
[k
].d
);
504 if (value_notzero_p(s
->fixed
[k
].m
))
505 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
507 value_set_si(d
.x
.n
, 1);
510 for (i
=p
->size
-1;i
>=1;i
--) {
511 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
513 emul(&d
, &p
->arr
[i
]);
514 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
515 free_evalue_refs(&(p
->arr
[i
]));
518 _reduce_evalue(&p
->arr
[0], s
, fract
);
521 free_evalue_refs(&d
);
527 /* Try to reduce the degree */
528 for (i
=p
->size
-1;i
>=1;i
--) {
529 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
531 /* Zero coefficient */
532 free_evalue_refs(&(p
->arr
[i
]));
537 /* Try to reduce its strength */
540 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
544 else if (p
->type
==fractional
) {
548 if (value_notzero_p(p
->arr
[0].d
)) {
550 value_assign(v
.d
, p
->arr
[0].d
);
552 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
557 evalue
*pp
= &p
->arr
[0];
558 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
559 assert(pp
->x
.p
->size
== 2);
561 /* search for exact duplicate among the modulo inequalities */
563 f
= &pp
->x
.p
->arr
[1];
564 for (k
= 0; s
&& k
< s
->n
; ++k
) {
565 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
566 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
567 value_eq(s
->fixed
[k
].m
, f
->d
) &&
568 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
575 /* replace { E/m } by { (E-1)/m } + 1/m */
580 evalue_set_si(&extra
, 1, 1);
581 value_assign(extra
.d
, g
);
582 eadd(&extra
, &v
.x
.p
->arr
[1]);
583 free_evalue_refs(&extra
);
585 /* We've been going in circles; stop now */
586 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
587 free_evalue_refs(&v
);
589 evalue_set_si(&v
, 0, 1);
594 value_set_si(v
.d
, 0);
595 v
.x
.p
= new_enode(fractional
, 3, -1);
596 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
597 value_assign(v
.x
.p
->arr
[1].d
, g
);
598 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
599 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
602 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
605 value_division(f
->d
, g
, f
->d
);
606 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
607 value_assign(f
->d
, g
);
608 value_decrement(f
->x
.n
, f
->x
.n
);
609 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
611 Gcd(f
->d
, f
->x
.n
, &g
);
612 value_division(f
->d
, f
->d
, g
);
613 value_division(f
->x
.n
, f
->x
.n
, g
);
622 /* reduction may have made this fractional arg smaller */
623 i
= reorder
? p
->size
: 1;
624 for ( ; i
< p
->size
; ++i
)
625 if (value_zero_p(p
->arr
[i
].d
) &&
626 p
->arr
[i
].x
.p
->type
== fractional
&&
627 !mod_term_smaller(e
, &p
->arr
[i
]))
631 value_set_si(v
.d
, 0);
632 v
.x
.p
= new_enode(fractional
, 3, -1);
633 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
634 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
635 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
643 evalue
*pp
= &p
->arr
[0];
646 poly_denom_not_constant(&pp
, &m
);
647 mpz_fdiv_r(r
, m
, pp
->d
);
648 if (value_notzero_p(r
)) {
650 value_set_si(v
.d
, 0);
651 v
.x
.p
= new_enode(fractional
, 3, -1);
653 value_multiply(r
, m
, pp
->x
.n
);
654 value_multiply(v
.x
.p
->arr
[1].d
, m
, pp
->d
);
655 value_init(v
.x
.p
->arr
[1].x
.n
);
656 mpz_fdiv_r(v
.x
.p
->arr
[1].x
.n
, r
, pp
->d
);
657 mpz_fdiv_q(r
, r
, pp
->d
);
659 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
660 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
662 while (value_zero_p(pp
->d
))
663 pp
= &pp
->x
.p
->arr
[0];
665 value_assign(pp
->d
, m
);
666 value_assign(pp
->x
.n
, r
);
668 Gcd(pp
->d
, pp
->x
.n
, &r
);
669 value_division(pp
->d
, pp
->d
, r
);
670 value_division(pp
->x
.n
, pp
->x
.n
, r
);
683 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
684 pp
= &pp
->x
.p
->arr
[0]) {
685 f
= &pp
->x
.p
->arr
[1];
686 assert(value_pos_p(f
->d
));
687 mpz_mul_ui(twice
, f
->x
.n
, 2);
688 if (value_lt(twice
, f
->d
))
690 if (value_eq(twice
, f
->d
))
698 value_set_si(v
.d
, 0);
699 v
.x
.p
= new_enode(fractional
, 3, -1);
700 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
701 poly_denom(&p
->arr
[0], &twice
);
702 value_assign(v
.x
.p
->arr
[1].d
, twice
);
703 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
704 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
705 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
707 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
708 pp
= &pp
->x
.p
->arr
[0]) {
709 f
= &pp
->x
.p
->arr
[1];
710 value_oppose(f
->x
.n
, f
->x
.n
);
711 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
713 value_division(pp
->d
, twice
, pp
->d
);
714 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
715 value_assign(pp
->d
, twice
);
716 value_oppose(pp
->x
.n
, pp
->x
.n
);
717 value_decrement(pp
->x
.n
, pp
->x
.n
);
718 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
720 /* Maybe we should do this during reduction of
723 Gcd(pp
->d
, pp
->x
.n
, &twice
);
724 value_division(pp
->d
, pp
->d
, twice
);
725 value_division(pp
->x
.n
, pp
->x
.n
, twice
);
735 reorder_terms_about(p
, &v
);
736 _reduce_evalue(&p
->arr
[1], s
, fract
);
739 /* Try to reduce the degree */
740 for (i
=p
->size
-1;i
>=2;i
--) {
741 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
743 /* Zero coefficient */
744 free_evalue_refs(&(p
->arr
[i
]));
749 /* Try to reduce its strength */
752 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
753 free_evalue_refs(&(p
->arr
[0]));
757 else if (p
->type
== flooring
) {
758 /* Try to reduce the degree */
759 for (i
=p
->size
-1;i
>=2;i
--) {
760 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
762 /* Zero coefficient */
763 free_evalue_refs(&(p
->arr
[i
]));
768 /* Try to reduce its strength */
771 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
772 free_evalue_refs(&(p
->arr
[0]));
776 else if (p
->type
== relation
) {
777 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
778 free_evalue_refs(&(p
->arr
[2]));
779 free_evalue_refs(&(p
->arr
[0]));
786 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
787 free_evalue_refs(&(p
->arr
[2]));
790 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
791 free_evalue_refs(&(p
->arr
[1]));
792 free_evalue_refs(&(p
->arr
[0]));
793 evalue_set_si(e
, 0, 1);
800 /* Relation was reduced by means of an identical
801 * inequality => remove
803 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
806 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
807 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
809 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
811 free_evalue_refs(&(p
->arr
[2]));
815 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
817 evalue_set_si(e
, 0, 1);
818 free_evalue_refs(&(p
->arr
[1]));
820 free_evalue_refs(&(p
->arr
[0]));
826 } /* reduce_evalue */
828 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
833 for (k
= 0; k
< dim
; ++k
)
834 if (value_notzero_p(row
[k
+1]))
837 Vector_Normalize_Positive(row
+1, dim
+1, k
);
838 assert(s
->n
< s
->max
);
839 value_init(s
->fixed
[s
->n
].d
);
840 value_init(s
->fixed
[s
->n
].m
);
841 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
842 s
->fixed
[s
->n
].pos
= k
+1;
843 value_set_si(s
->fixed
[s
->n
].m
, 0);
844 r
= &s
->fixed
[s
->n
].s
;
846 for (l
= k
+1; l
< dim
; ++l
)
847 if (value_notzero_p(row
[l
+1])) {
848 value_set_si(r
->d
, 0);
849 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
850 value_init(r
->x
.p
->arr
[1].x
.n
);
851 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
852 value_set_si(r
->x
.p
->arr
[1].d
, 1);
856 value_oppose(r
->x
.n
, row
[dim
+1]);
857 value_set_si(r
->d
, 1);
861 static void _reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
, struct subst
*s
)
864 Polyhedron
*orig
= D
;
869 D
= DomainConvex(D
, 0);
870 if (!D
->next
&& D
->NbEq
) {
874 realloc_substitution(s
, dim
);
876 int d
= relations_depth(e
);
878 NALLOC(s
->fixed
, s
->max
);
881 for (j
= 0; j
< D
->NbEq
; ++j
)
882 add_substitution(s
, D
->Constraint
[j
], dim
);
886 _reduce_evalue(e
, s
, 0);
889 for (j
= 0; j
< s
->n
; ++j
) {
890 value_clear(s
->fixed
[j
].d
);
891 value_clear(s
->fixed
[j
].m
);
892 free_evalue_refs(&s
->fixed
[j
].s
);
897 void reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
)
899 struct subst s
= { NULL
, 0, 0 };
901 if (EVALUE_IS_ZERO(*e
))
905 evalue_set_si(e
, 0, 1);
908 _reduce_evalue_in_domain(e
, D
, &s
);
913 void reduce_evalue (evalue
*e
) {
914 struct subst s
= { NULL
, 0, 0 };
916 if (value_notzero_p(e
->d
))
917 return; /* a rational number, its already reduced */
919 if (e
->x
.p
->type
== partition
) {
922 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
923 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
925 /* This shouldn't really happen;
926 * Empty domains should not be added.
928 POL_ENSURE_VERTICES(D
);
930 _reduce_evalue_in_domain(&e
->x
.p
->arr
[2*i
+1], D
, &s
);
932 if (emptyQ(D
) || EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
933 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
934 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
935 value_clear(e
->x
.p
->arr
[2*i
].d
);
937 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
938 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
942 if (e
->x
.p
->size
== 0) {
944 evalue_set_si(e
, 0, 1);
947 _reduce_evalue(e
, &s
, 0);
952 void print_evalue(FILE *DST
, const evalue
*e
, char **pname
)
954 if(value_notzero_p(e
->d
)) {
955 if(value_notone_p(e
->d
)) {
956 value_print(DST
,VALUE_FMT
,e
->x
.n
);
958 value_print(DST
,VALUE_FMT
,e
->d
);
961 value_print(DST
,VALUE_FMT
,e
->x
.n
);
965 print_enode(DST
,e
->x
.p
,pname
);
969 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
974 fprintf(DST
, "NULL");
980 for (i
=0; i
<p
->size
; i
++) {
981 print_evalue(DST
, &p
->arr
[i
], pname
);
985 fprintf(DST
, " }\n");
989 for (i
=p
->size
-1; i
>=0; i
--) {
990 print_evalue(DST
, &p
->arr
[i
], pname
);
991 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
993 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
995 fprintf(DST
, " )\n");
999 for (i
=0; i
<p
->size
; i
++) {
1000 print_evalue(DST
, &p
->arr
[i
], pname
);
1001 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
1003 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
1008 for (i
=p
->size
-1; i
>=1; i
--) {
1009 print_evalue(DST
, &p
->arr
[i
], pname
);
1011 fprintf(DST
, " * ");
1012 fprintf(DST
, p
->type
== flooring
? "[" : "{");
1013 print_evalue(DST
, &p
->arr
[0], pname
);
1014 fprintf(DST
, p
->type
== flooring
? "]" : "}");
1016 fprintf(DST
, "^%d + ", i
-1);
1018 fprintf(DST
, " + ");
1021 fprintf(DST
, " )\n");
1025 print_evalue(DST
, &p
->arr
[0], pname
);
1026 fprintf(DST
, "= 0 ] * \n");
1027 print_evalue(DST
, &p
->arr
[1], pname
);
1029 fprintf(DST
, " +\n [ ");
1030 print_evalue(DST
, &p
->arr
[0], pname
);
1031 fprintf(DST
, "!= 0 ] * \n");
1032 print_evalue(DST
, &p
->arr
[2], pname
);
1036 char **names
= pname
;
1037 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
1038 if (!pname
|| p
->pos
< maxdim
) {
1039 NALLOC(names
, maxdim
);
1040 for (i
= 0; i
< p
->pos
; ++i
) {
1042 names
[i
] = pname
[i
];
1044 NALLOC(names
[i
], 10);
1045 snprintf(names
[i
], 10, "%c", 'P'+i
);
1048 for ( ; i
< maxdim
; ++i
) {
1049 NALLOC(names
[i
], 10);
1050 snprintf(names
[i
], 10, "_p%d", i
);
1054 for (i
=0; i
<p
->size
/2; i
++) {
1055 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
1056 print_evalue(DST
, &p
->arr
[2*i
+1], names
);
1059 if (!pname
|| p
->pos
< maxdim
) {
1060 for (i
= pname
? p
->pos
: 0; i
< maxdim
; ++i
)
1073 static void eadd_rev(const evalue
*e1
, evalue
*res
)
1077 evalue_copy(&ev
, e1
);
1079 free_evalue_refs(res
);
1083 static void eadd_rev_cst(const evalue
*e1
, evalue
*res
)
1087 evalue_copy(&ev
, e1
);
1088 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
1089 free_evalue_refs(res
);
1093 static int is_zero_on(evalue
*e
, Polyhedron
*D
)
1098 tmp
.x
.p
= new_enode(partition
, 2, D
->Dimension
);
1099 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Domain_Copy(D
));
1100 evalue_copy(&tmp
.x
.p
->arr
[1], e
);
1101 reduce_evalue(&tmp
);
1102 is_zero
= EVALUE_IS_ZERO(tmp
);
1103 free_evalue_refs(&tmp
);
1107 struct section
{ Polyhedron
* D
; evalue E
; };
1109 void eadd_partitions(const evalue
*e1
, evalue
*res
)
1114 s
= (struct section
*)
1115 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
1116 sizeof(struct section
));
1118 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1119 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1120 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1123 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1124 assert(res
->x
.p
->size
>= 2);
1125 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1126 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
1128 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
1130 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1139 /* See if we can extend one of the domains in res to cover fd */
1140 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1141 if (is_zero_on(&res
->x
.p
->arr
[2*i
+1], fd
))
1143 if (i
< res
->x
.p
->size
/2) {
1144 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
1145 DomainConcat(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
])));
1148 value_init(s
[n
].E
.d
);
1149 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
1153 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1154 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
1155 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1157 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1158 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1164 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1165 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1167 value_init(s
[n
].E
.d
);
1168 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1169 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1170 if (!emptyQ(fd
) && is_zero_on(&e1
->x
.p
->arr
[2*j
+1], fd
)) {
1171 d
= DomainConcat(fd
, d
);
1172 fd
= Empty_Polyhedron(fd
->Dimension
);
1178 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1182 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1185 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1186 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1187 value_clear(res
->x
.p
->arr
[2*i
].d
);
1192 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1193 for (j
= 0; j
< n
; ++j
) {
1194 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1195 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1196 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1197 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1203 static void explicit_complement(evalue
*res
)
1205 enode
*rel
= new_enode(relation
, 3, 0);
1207 value_clear(rel
->arr
[0].d
);
1208 rel
->arr
[0] = res
->x
.p
->arr
[0];
1209 value_clear(rel
->arr
[1].d
);
1210 rel
->arr
[1] = res
->x
.p
->arr
[1];
1211 value_set_si(rel
->arr
[2].d
, 1);
1212 value_init(rel
->arr
[2].x
.n
);
1213 value_set_si(rel
->arr
[2].x
.n
, 0);
1218 void eadd(const evalue
*e1
, evalue
*res
)
1221 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1222 /* Add two rational numbers */
1228 value_multiply(m1
,e1
->x
.n
,res
->d
);
1229 value_multiply(m2
,res
->x
.n
,e1
->d
);
1230 value_addto(res
->x
.n
,m1
,m2
);
1231 value_multiply(res
->d
,e1
->d
,res
->d
);
1232 Gcd(res
->x
.n
,res
->d
,&g
);
1233 if (value_notone_p(g
)) {
1234 value_division(res
->d
,res
->d
,g
);
1235 value_division(res
->x
.n
,res
->x
.n
,g
);
1237 value_clear(g
); value_clear(m1
); value_clear(m2
);
1240 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1241 switch (res
->x
.p
->type
) {
1243 /* Add the constant to the constant term of a polynomial*/
1244 eadd(e1
, &res
->x
.p
->arr
[0]);
1247 /* Add the constant to all elements of a periodic number */
1248 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1249 eadd(e1
, &res
->x
.p
->arr
[i
]);
1253 fprintf(stderr
, "eadd: cannot add const with vector\n");
1257 eadd(e1
, &res
->x
.p
->arr
[1]);
1260 assert(EVALUE_IS_ZERO(*e1
));
1261 break; /* Do nothing */
1263 /* Create (zero) complement if needed */
1264 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1265 explicit_complement(res
);
1266 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1267 eadd(e1
, &res
->x
.p
->arr
[i
]);
1273 /* add polynomial or periodic to constant
1274 * you have to exchange e1 and res, before doing addition */
1276 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1280 else { // ((e1->d==0) && (res->d==0))
1281 assert(!((e1
->x
.p
->type
== partition
) ^
1282 (res
->x
.p
->type
== partition
)));
1283 if (e1
->x
.p
->type
== partition
) {
1284 eadd_partitions(e1
, res
);
1287 if (e1
->x
.p
->type
== relation
&&
1288 (res
->x
.p
->type
!= relation
||
1289 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1293 if (res
->x
.p
->type
== relation
) {
1294 if (e1
->x
.p
->type
== relation
&&
1295 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1296 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1297 explicit_complement(res
);
1298 for (i
= 1; i
< e1
->x
.p
->size
; ++i
)
1299 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1302 if (res
->x
.p
->size
< 3)
1303 explicit_complement(res
);
1304 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1305 eadd(e1
, &res
->x
.p
->arr
[i
]);
1308 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1309 /* adding to evalues of different type. two cases are possible
1310 * res is periodic and e1 is polynomial, you have to exchange
1311 * e1 and res then to add e1 to the constant term of res */
1312 if (e1
->x
.p
->type
== polynomial
) {
1313 eadd_rev_cst(e1
, res
);
1315 else if (res
->x
.p
->type
== polynomial
) {
1316 /* res is polynomial and e1 is periodic,
1317 add e1 to the constant term of res */
1319 eadd(e1
,&res
->x
.p
->arr
[0]);
1325 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1326 ((res
->x
.p
->type
== fractional
||
1327 res
->x
.p
->type
== flooring
) &&
1328 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1329 /* adding evalues of different position (i.e function of different unknowns
1330 * to case are possible */
1332 switch (res
->x
.p
->type
) {
1335 if (mod_term_smaller(res
, e1
))
1336 eadd(e1
,&res
->x
.p
->arr
[1]);
1338 eadd_rev_cst(e1
, res
);
1340 case polynomial
: // res and e1 are polynomials
1341 // add e1 to the constant term of res
1343 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1344 eadd(e1
,&res
->x
.p
->arr
[0]);
1346 eadd_rev_cst(e1
, res
);
1347 // value_clear(g); value_clear(m1); value_clear(m2);
1349 case periodic
: // res and e1 are pointers to periodic numbers
1350 //add e1 to all elements of res
1352 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1353 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1354 eadd(e1
,&res
->x
.p
->arr
[i
]);
1365 //same type , same pos and same size
1366 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1367 // add any element in e1 to the corresponding element in res
1368 i
= type_offset(res
->x
.p
);
1370 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1371 for (; i
<res
->x
.p
->size
; i
++) {
1372 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1377 /* Sizes are different */
1378 switch(res
->x
.p
->type
) {
1382 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1383 /* new enode and add res to that new node. If you do not do */
1384 /* that, you lose the the upper weight part of e1 ! */
1386 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1389 i
= type_offset(res
->x
.p
);
1391 assert(eequal(&e1
->x
.p
->arr
[0],
1392 &res
->x
.p
->arr
[0]));
1393 for (; i
<e1
->x
.p
->size
; i
++) {
1394 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1401 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1404 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1405 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1406 to add periodicaly elements of e1 to elements of ne, and finaly to
1411 value_init(ex
); value_init(ey
);value_init(ep
);
1414 value_set_si(ex
,e1
->x
.p
->size
);
1415 value_set_si(ey
,res
->x
.p
->size
);
1416 value_assign (ep
,*Lcm(ex
,ey
));
1417 p
=(int)mpz_get_si(ep
);
1418 ne
= (evalue
*) malloc (sizeof(evalue
));
1420 value_set_si( ne
->d
,0);
1422 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1424 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1427 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1430 value_assign(res
->d
, ne
->d
);
1436 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1445 static void emul_rev (evalue
*e1
, evalue
*res
)
1449 evalue_copy(&ev
, e1
);
1451 free_evalue_refs(res
);
1455 static void emul_poly (evalue
*e1
, evalue
*res
)
1457 int i
, j
, o
= type_offset(res
->x
.p
);
1459 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1461 value_set_si(tmp
.d
,0);
1462 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1464 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1465 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1466 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1467 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1470 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1471 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1472 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1475 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1476 emul(&res
->x
.p
->arr
[i
], &ev
);
1477 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1478 free_evalue_refs(&ev
);
1480 free_evalue_refs(res
);
1484 void emul_partitions (evalue
*e1
,evalue
*res
)
1489 s
= (struct section
*)
1490 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1491 sizeof(struct section
));
1493 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1494 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1495 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1498 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1499 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1500 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1501 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1507 /* This code is only needed because the partitions
1508 are not true partitions.
1510 for (k
= 0; k
< n
; ++k
) {
1511 if (DomainIncludes(s
[k
].D
, d
))
1513 if (DomainIncludes(d
, s
[k
].D
)) {
1514 Domain_Free(s
[k
].D
);
1515 free_evalue_refs(&s
[k
].E
);
1526 value_init(s
[n
].E
.d
);
1527 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1528 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1532 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1533 value_clear(res
->x
.p
->arr
[2*i
].d
);
1534 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1539 evalue_set_si(res
, 0, 1);
1541 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1542 for (j
= 0; j
< n
; ++j
) {
1543 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1544 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1545 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1546 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1553 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1555 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1556 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1557 * evalues is not treated here */
1559 void emul (evalue
*e1
, evalue
*res
){
1562 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1563 fprintf(stderr
, "emul: do not proced on evector type !\n");
1567 if (EVALUE_IS_ZERO(*res
))
1570 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1571 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1572 emul_partitions(e1
, res
);
1575 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1576 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1577 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1579 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1580 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1581 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1582 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1583 explicit_complement(res
);
1584 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1585 explicit_complement(e1
);
1586 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1587 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1590 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1591 emul(e1
, &res
->x
.p
->arr
[i
]);
1593 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1594 switch(e1
->x
.p
->type
) {
1596 switch(res
->x
.p
->type
) {
1598 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1599 /* Product of two polynomials of the same variable */
1604 /* Product of two polynomials of different variables */
1606 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1607 for( i
=0; i
<res
->x
.p
->size
; i
++)
1608 emul(e1
, &res
->x
.p
->arr
[i
]);
1617 /* Product of a polynomial and a periodic or fractional */
1624 switch(res
->x
.p
->type
) {
1626 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1627 /* Product of two periodics of the same parameter and period */
1629 for(i
=0; i
<res
->x
.p
->size
;i
++)
1630 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1635 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1636 /* Product of two periodics of the same parameter and different periods */
1640 value_init(x
); value_init(y
);value_init(z
);
1643 value_set_si(x
,e1
->x
.p
->size
);
1644 value_set_si(y
,res
->x
.p
->size
);
1645 value_assign (z
,*Lcm(x
,y
));
1646 lcm
=(int)mpz_get_si(z
);
1647 newp
= (evalue
*) malloc (sizeof(evalue
));
1648 value_init(newp
->d
);
1649 value_set_si( newp
->d
,0);
1650 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1651 for(i
=0;i
<lcm
;i
++) {
1652 evalue_copy(&newp
->x
.p
->arr
[i
],
1653 &res
->x
.p
->arr
[i
%iy
]);
1656 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1658 value_assign(res
->d
,newp
->d
);
1661 value_clear(x
); value_clear(y
);value_clear(z
);
1665 /* Product of two periodics of different parameters */
1667 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1668 for(i
=0; i
<res
->x
.p
->size
; i
++)
1669 emul(e1
, &(res
->x
.p
->arr
[i
]));
1677 /* Product of a periodic and a polynomial */
1679 for(i
=0; i
<res
->x
.p
->size
; i
++)
1680 emul(e1
, &(res
->x
.p
->arr
[i
]));
1687 switch(res
->x
.p
->type
) {
1689 for(i
=0; i
<res
->x
.p
->size
; i
++)
1690 emul(e1
, &(res
->x
.p
->arr
[i
]));
1697 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1698 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1699 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1702 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1703 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1708 value_set_si(d
.x
.n
, 1);
1709 /* { x }^2 == { x }/2 */
1710 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1711 assert(e1
->x
.p
->size
== 3);
1712 assert(res
->x
.p
->size
== 3);
1714 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1716 eadd(&res
->x
.p
->arr
[1], &tmp
);
1717 emul(&e1
->x
.p
->arr
[2], &tmp
);
1718 emul(&e1
->x
.p
->arr
[1], res
);
1719 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1720 free_evalue_refs(&tmp
);
1725 if(mod_term_smaller(res
, e1
))
1726 for(i
=1; i
<res
->x
.p
->size
; i
++)
1727 emul(e1
, &(res
->x
.p
->arr
[i
]));
1742 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1743 /* Product of two rational numbers */
1747 value_multiply(res
->d
,e1
->d
,res
->d
);
1748 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1749 Gcd(res
->x
.n
, res
->d
,&g
);
1750 if (value_notone_p(g
)) {
1751 value_division(res
->d
,res
->d
,g
);
1752 value_division(res
->x
.n
,res
->x
.n
,g
);
1758 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1759 /* Product of an expression (polynomial or peririodic) and a rational number */
1765 /* Product of a rationel number and an expression (polynomial or peririodic) */
1767 i
= type_offset(res
->x
.p
);
1768 for (; i
<res
->x
.p
->size
; i
++)
1769 emul(e1
, &res
->x
.p
->arr
[i
]);
1779 /* Frees mask content ! */
1780 void emask(evalue
*mask
, evalue
*res
) {
1787 if (EVALUE_IS_ZERO(*res
)) {
1788 free_evalue_refs(mask
);
1792 assert(value_zero_p(mask
->d
));
1793 assert(mask
->x
.p
->type
== partition
);
1794 assert(value_zero_p(res
->d
));
1795 assert(res
->x
.p
->type
== partition
);
1796 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1797 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1798 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1799 pos
= res
->x
.p
->pos
;
1801 s
= (struct section
*)
1802 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1803 sizeof(struct section
));
1807 evalue_set_si(&mone
, -1, 1);
1810 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1811 assert(mask
->x
.p
->size
>= 2);
1812 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1813 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1815 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1817 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1826 value_init(s
[n
].E
.d
);
1827 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1831 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1832 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1835 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1836 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1837 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1838 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1840 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1841 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1847 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1848 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1850 value_init(s
[n
].E
.d
);
1851 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1852 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1858 /* Just ignore; this may have been previously masked off */
1860 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1864 free_evalue_refs(&mone
);
1865 free_evalue_refs(mask
);
1866 free_evalue_refs(res
);
1869 evalue_set_si(res
, 0, 1);
1871 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1872 for (j
= 0; j
< n
; ++j
) {
1873 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1874 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1875 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1882 void evalue_copy(evalue
*dst
, const evalue
*src
)
1884 value_assign(dst
->d
, src
->d
);
1885 if(value_notzero_p(src
->d
)) {
1886 value_init(dst
->x
.n
);
1887 value_assign(dst
->x
.n
, src
->x
.n
);
1889 dst
->x
.p
= ecopy(src
->x
.p
);
1892 enode
*new_enode(enode_type type
,int size
,int pos
) {
1898 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1901 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1905 for(i
=0; i
<size
; i
++) {
1906 value_init(res
->arr
[i
].d
);
1907 value_set_si(res
->arr
[i
].d
,0);
1908 res
->arr
[i
].x
.p
= 0;
1913 enode
*ecopy(enode
*e
) {
1918 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1919 for(i
=0;i
<e
->size
;++i
) {
1920 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1921 if(value_zero_p(res
->arr
[i
].d
))
1922 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1923 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1924 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1926 value_init(res
->arr
[i
].x
.n
);
1927 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1933 int ecmp(const evalue
*e1
, const evalue
*e2
)
1939 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1943 value_multiply(m
, e1
->x
.n
, e2
->d
);
1944 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1946 if (value_lt(m
, m2
))
1948 else if (value_gt(m
, m2
))
1958 if (value_notzero_p(e1
->d
))
1960 if (value_notzero_p(e2
->d
))
1966 if (p1
->type
!= p2
->type
)
1967 return p1
->type
- p2
->type
;
1968 if (p1
->pos
!= p2
->pos
)
1969 return p1
->pos
- p2
->pos
;
1970 if (p1
->size
!= p2
->size
)
1971 return p1
->size
- p2
->size
;
1973 for (i
= p1
->size
-1; i
>= 0; --i
)
1974 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1980 int eequal(const evalue
*e1
, const evalue
*e2
)
1985 if (value_ne(e1
->d
,e2
->d
))
1988 /* e1->d == e2->d */
1989 if (value_notzero_p(e1
->d
)) {
1990 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1993 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1997 /* e1->d == e2->d == 0 */
2000 if (p1
->type
!= p2
->type
) return 0;
2001 if (p1
->size
!= p2
->size
) return 0;
2002 if (p1
->pos
!= p2
->pos
) return 0;
2003 for (i
=0; i
<p1
->size
; i
++)
2004 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
2009 void free_evalue_refs(evalue
*e
) {
2014 if (EVALUE_IS_DOMAIN(*e
)) {
2015 Domain_Free(EVALUE_DOMAIN(*e
));
2018 } else if (value_pos_p(e
->d
)) {
2020 /* 'e' stores a constant */
2022 value_clear(e
->x
.n
);
2025 assert(value_zero_p(e
->d
));
2028 if (!p
) return; /* null pointer */
2029 for (i
=0; i
<p
->size
; i
++) {
2030 free_evalue_refs(&(p
->arr
[i
]));
2034 } /* free_evalue_refs */
2036 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
2037 Vector
* val
, evalue
*res
)
2039 unsigned nparam
= periods
->Size
;
2042 double d
= compute_evalue(e
, val
->p
);
2043 d
*= VALUE_TO_DOUBLE(m
);
2048 value_assign(res
->d
, m
);
2049 value_init(res
->x
.n
);
2050 value_set_double(res
->x
.n
, d
);
2051 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
2054 if (value_one_p(periods
->p
[p
]))
2055 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
2060 value_assign(tmp
, periods
->p
[p
]);
2061 value_set_si(res
->d
, 0);
2062 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
2064 value_decrement(tmp
, tmp
);
2065 value_assign(val
->p
[p
], tmp
);
2066 mod2table_r(e
, periods
, m
, p
+1, val
,
2067 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
2068 } while (value_pos_p(tmp
));
2074 static void rel2table(evalue
*e
, int zero
)
2076 if (value_pos_p(e
->d
)) {
2077 if (value_zero_p(e
->x
.n
) == zero
)
2078 value_set_si(e
->x
.n
, 1);
2080 value_set_si(e
->x
.n
, 0);
2081 value_set_si(e
->d
, 1);
2084 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
2085 rel2table(&e
->x
.p
->arr
[i
], zero
);
2089 void evalue_mod2table(evalue
*e
, int nparam
)
2094 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2097 for (i
=0; i
<p
->size
; i
++) {
2098 evalue_mod2table(&(p
->arr
[i
]), nparam
);
2100 if (p
->type
== relation
) {
2105 evalue_copy(©
, &p
->arr
[0]);
2107 rel2table(&p
->arr
[0], 1);
2108 emul(&p
->arr
[0], &p
->arr
[1]);
2110 rel2table(©
, 0);
2111 emul(©
, &p
->arr
[2]);
2112 eadd(&p
->arr
[2], &p
->arr
[1]);
2113 free_evalue_refs(&p
->arr
[2]);
2114 free_evalue_refs(©
);
2116 free_evalue_refs(&p
->arr
[0]);
2120 } else if (p
->type
== fractional
) {
2121 Vector
*periods
= Vector_Alloc(nparam
);
2122 Vector
*val
= Vector_Alloc(nparam
);
2128 value_set_si(tmp
, 1);
2129 Vector_Set(periods
->p
, 1, nparam
);
2130 Vector_Set(val
->p
, 0, nparam
);
2131 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2134 assert(p
->type
== polynomial
);
2135 assert(p
->size
== 2);
2136 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2137 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
2139 value_lcm(tmp
, ev
->d
, &tmp
);
2141 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2144 evalue_set_si(&res
, 0, 1);
2145 /* Compute the polynomial using Horner's rule */
2146 for (i
=p
->size
-1;i
>1;i
--) {
2147 eadd(&p
->arr
[i
], &res
);
2150 eadd(&p
->arr
[1], &res
);
2152 free_evalue_refs(e
);
2153 free_evalue_refs(&EP
);
2158 Vector_Free(periods
);
2160 } /* evalue_mod2table */
2162 /********************************************************/
2163 /* function in domain */
2164 /* check if the parameters in list_args */
2165 /* verifies the constraints of Domain P */
2166 /********************************************************/
2167 int in_domain(Polyhedron
*P
, Value
*list_args
)
2170 Value v
; /* value of the constraint of a row when
2171 parameters are instantiated*/
2175 for (row
= 0; row
< P
->NbConstraints
; row
++) {
2176 Inner_Product(P
->Constraint
[row
]+1, list_args
, P
->Dimension
, &v
);
2177 value_addto(v
, v
, P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2178 if (value_neg_p(v
) ||
2179 value_zero_p(P
->Constraint
[row
][0]) && value_notzero_p(v
)) {
2186 return in
|| (P
->next
&& in_domain(P
->next
, list_args
));
2189 /****************************************************/
2190 /* function compute enode */
2191 /* compute the value of enode p with parameters */
2192 /* list "list_args */
2193 /* compute the polynomial or the periodic */
2194 /****************************************************/
2196 static double compute_enode(enode
*p
, Value
*list_args
) {
2208 if (p
->type
== polynomial
) {
2210 value_assign(param
,list_args
[p
->pos
-1]);
2212 /* Compute the polynomial using Horner's rule */
2213 for (i
=p
->size
-1;i
>0;i
--) {
2214 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2215 res
*=VALUE_TO_DOUBLE(param
);
2217 res
+=compute_evalue(&p
->arr
[0],list_args
);
2219 else if (p
->type
== fractional
) {
2220 double d
= compute_evalue(&p
->arr
[0], list_args
);
2221 d
-= floor(d
+1e-10);
2223 /* Compute the polynomial using Horner's rule */
2224 for (i
=p
->size
-1;i
>1;i
--) {
2225 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2228 res
+=compute_evalue(&p
->arr
[1],list_args
);
2230 else if (p
->type
== flooring
) {
2231 double d
= compute_evalue(&p
->arr
[0], list_args
);
2234 /* Compute the polynomial using Horner's rule */
2235 for (i
=p
->size
-1;i
>1;i
--) {
2236 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2239 res
+=compute_evalue(&p
->arr
[1],list_args
);
2241 else if (p
->type
== periodic
) {
2242 value_assign(m
,list_args
[p
->pos
-1]);
2244 /* Choose the right element of the periodic */
2245 value_set_si(param
,p
->size
);
2246 value_pmodulus(m
,m
,param
);
2247 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2249 else if (p
->type
== relation
) {
2250 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2251 res
= compute_evalue(&p
->arr
[1], list_args
);
2252 else if (p
->size
> 2)
2253 res
= compute_evalue(&p
->arr
[2], list_args
);
2255 else if (p
->type
== partition
) {
2256 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2257 Value
*vals
= list_args
;
2260 for (i
= 0; i
< dim
; ++i
) {
2261 value_init(vals
[i
]);
2263 value_assign(vals
[i
], list_args
[i
]);
2266 for (i
= 0; i
< p
->size
/2; ++i
)
2267 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2268 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2272 for (i
= 0; i
< dim
; ++i
)
2273 value_clear(vals
[i
]);
2282 } /* compute_enode */
2284 /*************************************************/
2285 /* return the value of Ehrhart Polynomial */
2286 /* It returns a double, because since it is */
2287 /* a recursive function, some intermediate value */
2288 /* might not be integral */
2289 /*************************************************/
2291 double compute_evalue(const evalue
*e
, Value
*list_args
)
2295 if (value_notzero_p(e
->d
)) {
2296 if (value_notone_p(e
->d
))
2297 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2299 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2302 res
= compute_enode(e
->x
.p
,list_args
);
2304 } /* compute_evalue */
2307 /****************************************************/
2308 /* function compute_poly : */
2309 /* Check for the good validity domain */
2310 /* return the number of point in the Polyhedron */
2311 /* in allocated memory */
2312 /* Using the Ehrhart pseudo-polynomial */
2313 /****************************************************/
2314 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2317 /* double d; int i; */
2319 tmp
= (Value
*) malloc (sizeof(Value
));
2320 assert(tmp
!= NULL
);
2322 value_set_si(*tmp
,0);
2325 return(tmp
); /* no ehrhart polynomial */
2326 if(en
->ValidityDomain
) {
2327 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2328 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2333 return(tmp
); /* no Validity Domain */
2335 if(in_domain(en
->ValidityDomain
,list_args
)) {
2337 #ifdef EVAL_EHRHART_DEBUG
2338 Print_Domain(stdout
,en
->ValidityDomain
);
2339 print_evalue(stdout
,&en
->EP
);
2342 /* d = compute_evalue(&en->EP,list_args);
2344 printf("(double)%lf = %d\n", d, i ); */
2345 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2351 value_set_si(*tmp
,0);
2352 return(tmp
); /* no compatible domain with the arguments */
2353 } /* compute_poly */
2355 static evalue
*eval_polynomial(const enode
*p
, int offset
,
2356 evalue
*base
, Value
*values
)
2361 res
= evalue_zero();
2362 for (i
= p
->size
-1; i
> offset
; --i
) {
2363 c
= evalue_eval(&p
->arr
[i
], values
);
2365 free_evalue_refs(c
);
2369 c
= evalue_eval(&p
->arr
[offset
], values
);
2371 free_evalue_refs(c
);
2377 evalue
*evalue_eval(const evalue
*e
, Value
*values
)
2384 if (value_notzero_p(e
->d
)) {
2385 res
= ALLOC(evalue
);
2387 evalue_copy(res
, e
);
2390 switch (e
->x
.p
->type
) {
2392 value_init(param
.x
.n
);
2393 value_assign(param
.x
.n
, values
[e
->x
.p
->pos
-1]);
2394 value_init(param
.d
);
2395 value_set_si(param
.d
, 1);
2397 res
= eval_polynomial(e
->x
.p
, 0, ¶m
, values
);
2398 free_evalue_refs(¶m
);
2401 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2402 mpz_fdiv_r(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2404 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2405 free_evalue_refs(param2
);
2409 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2410 mpz_fdiv_q(param2
->x
.n
, param2
->x
.n
, param2
->d
);
2411 value_set_si(param2
->d
, 1);
2413 res
= eval_polynomial(e
->x
.p
, 1, param2
, values
);
2414 free_evalue_refs(param2
);
2418 param2
= evalue_eval(&e
->x
.p
->arr
[0], values
);
2419 if (value_zero_p(param2
->x
.n
))
2420 res
= evalue_eval(&e
->x
.p
->arr
[1], values
);
2421 else if (e
->x
.p
->size
> 2)
2422 res
= evalue_eval(&e
->x
.p
->arr
[2], values
);
2424 res
= evalue_zero();
2425 free_evalue_refs(param2
);
2429 assert(e
->x
.p
->pos
== EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
);
2430 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2431 if (in_domain(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), values
)) {
2432 res
= evalue_eval(&e
->x
.p
->arr
[2*i
+1], values
);
2436 res
= evalue_zero();
2444 size_t value_size(Value v
) {
2445 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2446 * sizeof(v
[0]._mp_d
[0]);
2449 size_t domain_size(Polyhedron
*D
)
2452 size_t s
= sizeof(*D
);
2454 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2455 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2456 s
+= value_size(D
->Constraint
[i
][j
]);
2459 for (i = 0; i < D->NbRays; ++i)
2460 for (j = 0; j < D->Dimension+2; ++j)
2461 s += value_size(D->Ray[i][j]);
2464 return D
->next
? s
+domain_size(D
->next
) : s
;
2467 size_t enode_size(enode
*p
) {
2468 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2471 if (p
->type
== partition
)
2472 for (i
= 0; i
< p
->size
/2; ++i
) {
2473 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2474 s
+= evalue_size(&p
->arr
[2*i
+1]);
2477 for (i
= 0; i
< p
->size
; ++i
) {
2478 s
+= evalue_size(&p
->arr
[i
]);
2483 size_t evalue_size(evalue
*e
)
2485 size_t s
= sizeof(*e
);
2486 s
+= value_size(e
->d
);
2487 if (value_notzero_p(e
->d
))
2488 s
+= value_size(e
->x
.n
);
2490 s
+= enode_size(e
->x
.p
);
2494 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2496 evalue
*found
= NULL
;
2501 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2504 value_init(offset
.d
);
2505 value_init(offset
.x
.n
);
2506 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2507 value_lcm(m
, offset
.d
, &offset
.d
);
2508 value_set_si(offset
.x
.n
, 1);
2511 evalue_copy(©
, cst
);
2514 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2516 if (eequal(base
, &e
->x
.p
->arr
[0]))
2517 found
= &e
->x
.p
->arr
[0];
2519 value_set_si(offset
.x
.n
, -2);
2522 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2524 if (eequal(base
, &e
->x
.p
->arr
[0]))
2527 free_evalue_refs(cst
);
2528 free_evalue_refs(&offset
);
2531 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2532 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2537 static evalue
*find_relation_pair(evalue
*e
)
2540 evalue
*found
= NULL
;
2542 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2545 if (e
->x
.p
->type
== fractional
) {
2550 poly_denom(&e
->x
.p
->arr
[0], &m
);
2552 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2553 cst
= &cst
->x
.p
->arr
[0])
2556 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2557 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2562 i
= e
->x
.p
->type
== relation
;
2563 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2564 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2569 void evalue_mod2relation(evalue
*e
) {
2572 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2575 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2576 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2577 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2578 value_clear(e
->x
.p
->arr
[2*i
].d
);
2579 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2581 if (2*i
< e
->x
.p
->size
) {
2582 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2583 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2588 if (e
->x
.p
->size
== 0) {
2590 evalue_set_si(e
, 0, 1);
2596 while ((d
= find_relation_pair(e
)) != NULL
) {
2600 value_init(split
.d
);
2601 value_set_si(split
.d
, 0);
2602 split
.x
.p
= new_enode(relation
, 3, 0);
2603 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2604 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2606 ev
= &split
.x
.p
->arr
[0];
2607 value_set_si(ev
->d
, 0);
2608 ev
->x
.p
= new_enode(fractional
, 3, -1);
2609 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2610 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2611 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2617 free_evalue_refs(&split
);
2621 static int evalue_comp(const void * a
, const void * b
)
2623 const evalue
*e1
= *(const evalue
**)a
;
2624 const evalue
*e2
= *(const evalue
**)b
;
2625 return ecmp(e1
, e2
);
2628 void evalue_combine(evalue
*e
)
2635 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2638 NALLOC(evs
, e
->x
.p
->size
/2);
2639 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2640 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2641 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2642 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2643 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2644 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2645 value_clear(p
->arr
[2*k
].d
);
2646 value_clear(p
->arr
[2*k
+1].d
);
2647 p
->arr
[2*k
] = *(evs
[i
]-1);
2648 p
->arr
[2*k
+1] = *(evs
[i
]);
2651 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2654 value_clear((evs
[i
]-1)->d
);
2658 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2659 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2660 free_evalue_refs(evs
[i
]);
2664 for (i
= 2*k
; i
< p
->size
; ++i
)
2665 value_clear(p
->arr
[i
].d
);
2672 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2674 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2676 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2679 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2680 Polyhedron
*D
, *N
, **P
;
2683 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2690 if (D
->NbEq
<= H
->NbEq
) {
2696 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2697 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2698 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2699 reduce_evalue(&tmp
);
2700 if (value_notzero_p(tmp
.d
) ||
2701 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2704 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2705 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2708 free_evalue_refs(&tmp
);
2714 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2716 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2718 value_clear(e
->x
.p
->arr
[2*i
].d
);
2719 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2721 if (2*i
< e
->x
.p
->size
) {
2722 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2723 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2730 H
= DomainConvex(D
, 0);
2731 E
= DomainDifference(H
, D
, 0);
2733 D
= DomainDifference(H
, E
, 0);
2736 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2740 /* Use smallest representative for coefficients in affine form in
2741 * argument of fractional.
2742 * Since any change will make the argument non-standard,
2743 * the containing evalue will have to be reduced again afterward.
2745 static void fractional_minimal_coefficients(enode
*p
)
2751 assert(p
->type
== fractional
);
2753 while (value_zero_p(pp
->d
)) {
2754 assert(pp
->x
.p
->type
== polynomial
);
2755 assert(pp
->x
.p
->size
== 2);
2756 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2757 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2758 if (value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2759 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2760 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2761 pp
= &pp
->x
.p
->arr
[0];
2767 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2772 unsigned dim
= D
->Dimension
;
2773 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2776 assert(p
->type
== fractional
);
2778 value_set_si(T
->p
[1][dim
], 1);
2780 while (value_zero_p(pp
->d
)) {
2781 assert(pp
->x
.p
->type
== polynomial
);
2782 assert(pp
->x
.p
->size
== 2);
2783 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2784 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2785 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2786 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2787 pp
= &pp
->x
.p
->arr
[0];
2789 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2790 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2791 I
= DomainImage(D
, T
, 0);
2792 H
= DomainConvex(I
, 0);
2802 int evalue_range_reduction_in_domain(evalue
*e
, Polyhedron
*D
)
2811 if (value_notzero_p(e
->d
))
2816 if (p
->type
== relation
) {
2823 fractional_minimal_coefficients(p
->arr
[0].x
.p
);
2824 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
);
2825 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2826 equal
= value_eq(min
, max
);
2827 mpz_cdiv_q(min
, min
, d
);
2828 mpz_fdiv_q(max
, max
, d
);
2830 if (bounded
&& value_gt(min
, max
)) {
2836 evalue_set_si(e
, 0, 1);
2839 free_evalue_refs(&(p
->arr
[1]));
2840 free_evalue_refs(&(p
->arr
[0]));
2846 return r
? r
: evalue_range_reduction_in_domain(e
, D
);
2847 } else if (bounded
&& equal
) {
2850 free_evalue_refs(&(p
->arr
[2]));
2853 free_evalue_refs(&(p
->arr
[0]));
2859 return evalue_range_reduction_in_domain(e
, D
);
2860 } else if (bounded
&& value_eq(min
, max
)) {
2861 /* zero for a single value */
2863 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2864 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2865 value_multiply(min
, min
, d
);
2866 value_subtract(M
->p
[0][D
->Dimension
+1],
2867 M
->p
[0][D
->Dimension
+1], min
);
2868 E
= DomainAddConstraints(D
, M
, 0);
2874 r
= evalue_range_reduction_in_domain(&p
->arr
[1], E
);
2876 r
|= evalue_range_reduction_in_domain(&p
->arr
[2], D
);
2878 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2886 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2889 i
= p
->type
== relation
? 1 :
2890 p
->type
== fractional
? 1 : 0;
2891 for (; i
<p
->size
; i
++)
2892 r
|= evalue_range_reduction_in_domain(&p
->arr
[i
], D
);
2894 if (p
->type
!= fractional
) {
2895 if (r
&& p
->type
== polynomial
) {
2898 value_set_si(f
.d
, 0);
2899 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2900 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2901 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2902 reorder_terms_about(p
, &f
);
2913 fractional_minimal_coefficients(p
);
2914 I
= polynomial_projection(p
, D
, &d
, NULL
);
2915 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2916 mpz_fdiv_q(min
, min
, d
);
2917 mpz_fdiv_q(max
, max
, d
);
2918 value_subtract(d
, max
, min
);
2920 if (bounded
&& value_eq(min
, max
)) {
2923 value_init(inc
.x
.n
);
2924 value_set_si(inc
.d
, 1);
2925 value_oppose(inc
.x
.n
, min
);
2926 eadd(&inc
, &p
->arr
[0]);
2927 reorder_terms_about(p
, &p
->arr
[0]); /* frees arr[0] */
2931 free_evalue_refs(&inc
);
2933 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2934 /* replace {g}^2 by -(g-min)^2 + (2{g}+1)*(g-min) - {g}
2935 * See pages 199-200 of PhD thesis.
2943 value_set_si(rem
.d
, 0);
2944 rem
.x
.p
= new_enode(fractional
, 3, -1);
2945 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2946 value_clear(rem
.x
.p
->arr
[1].d
);
2947 value_clear(rem
.x
.p
->arr
[2].d
);
2948 rem
.x
.p
->arr
[1] = p
->arr
[1];
2949 rem
.x
.p
->arr
[2] = p
->arr
[2];
2950 for (i
= 3; i
< p
->size
; ++i
)
2951 p
->arr
[i
-2] = p
->arr
[i
];
2955 value_init(inc
.x
.n
);
2956 value_set_si(inc
.d
, 1);
2957 value_oppose(inc
.x
.n
, min
);
2960 evalue_copy(&t
, &p
->arr
[0]);
2964 value_set_si(f
.d
, 0);
2965 f
.x
.p
= new_enode(fractional
, 3, -1);
2966 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2967 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2968 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2970 value_init(factor
.d
);
2971 evalue_set_si(&factor
, -1, 1);
2977 value_clear(f
.x
.p
->arr
[1].x
.n
);
2978 value_clear(f
.x
.p
->arr
[2].x
.n
);
2979 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2980 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2984 reorder_terms(&rem
);
2991 free_evalue_refs(&inc
);
2992 free_evalue_refs(&t
);
2993 free_evalue_refs(&f
);
2994 free_evalue_refs(&factor
);
2995 free_evalue_refs(&rem
);
2997 evalue_range_reduction_in_domain(e
, D
);
3001 _reduce_evalue(&p
->arr
[0], 0, 1);
3013 void evalue_range_reduction(evalue
*e
)
3016 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
3019 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3020 if (evalue_range_reduction_in_domain(&e
->x
.p
->arr
[2*i
+1],
3021 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
3022 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3024 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
3025 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
3026 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3027 value_clear(e
->x
.p
->arr
[2*i
].d
);
3029 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
3030 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
3038 Enumeration
* partition2enumeration(evalue
*EP
)
3041 Enumeration
*en
, *res
= NULL
;
3043 if (EVALUE_IS_ZERO(*EP
)) {
3048 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
3049 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
3050 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
3053 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
3054 value_clear(EP
->x
.p
->arr
[2*i
].d
);
3055 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
3063 int evalue_frac2floor_in_domain3(evalue
*e
, Polyhedron
*D
, int shift
)
3072 if (value_notzero_p(e
->d
))
3077 i
= p
->type
== relation
? 1 :
3078 p
->type
== fractional
? 1 : 0;
3079 for (; i
<p
->size
; i
++)
3080 r
|= evalue_frac2floor_in_domain3(&p
->arr
[i
], D
, shift
);
3082 if (p
->type
!= fractional
) {
3083 if (r
&& p
->type
== polynomial
) {
3086 value_set_si(f
.d
, 0);
3087 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
3088 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
3089 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
3090 reorder_terms_about(p
, &f
);
3100 I
= polynomial_projection(p
, D
, &d
, NULL
);
3103 Polyhedron_Print(stderr, P_VALUE_FMT, I);
3106 assert(I
->NbEq
== 0); /* Should have been reduced */
3109 for (i
= 0; i
< I
->NbConstraints
; ++i
)
3110 if (value_pos_p(I
->Constraint
[i
][1]))
3113 if (i
< I
->NbConstraints
) {
3115 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
3116 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
3117 if (value_neg_p(min
)) {
3119 mpz_fdiv_q(min
, min
, d
);
3120 value_init(offset
.d
);
3121 value_set_si(offset
.d
, 1);
3122 value_init(offset
.x
.n
);
3123 value_oppose(offset
.x
.n
, min
);
3124 eadd(&offset
, &p
->arr
[0]);
3125 free_evalue_refs(&offset
);
3135 value_set_si(fl
.d
, 0);
3136 fl
.x
.p
= new_enode(flooring
, 3, -1);
3137 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
3138 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
3139 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
3141 eadd(&fl
, &p
->arr
[0]);
3142 reorder_terms_about(p
, &p
->arr
[0]);
3146 free_evalue_refs(&fl
);
3151 int evalue_frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
3153 return evalue_frac2floor_in_domain3(e
, D
, 1);
3156 void evalue_frac2floor2(evalue
*e
, int shift
)
3159 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
3161 if (evalue_frac2floor_in_domain3(e
, NULL
, 0))
3167 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3168 if (evalue_frac2floor_in_domain3(&e
->x
.p
->arr
[2*i
+1],
3169 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), shift
))
3170 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
3173 void evalue_frac2floor(evalue
*e
)
3175 evalue_frac2floor2(e
, 1);
3178 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
3183 int nparam
= D
->Dimension
- nvar
;
3186 nr
= D
->NbConstraints
+ 2;
3187 nc
= D
->Dimension
+ 2 + 1;
3188 C
= Matrix_Alloc(nr
, nc
);
3189 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
3190 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
3191 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3192 D
->Dimension
+ 1 - nvar
);
3197 nc
= C
->NbColumns
+ 1;
3198 C
= Matrix_Alloc(nr
, nc
);
3199 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
3200 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
3201 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3202 oldC
->NbColumns
- 1 - nvar
);
3205 value_set_si(C
->p
[nr
-2][0], 1);
3206 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
3207 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
3209 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
3210 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
3216 static void floor2frac_r(evalue
*e
, int nvar
)
3223 if (value_notzero_p(e
->d
))
3228 assert(p
->type
== flooring
);
3229 for (i
= 1; i
< p
->size
; i
++)
3230 floor2frac_r(&p
->arr
[i
], nvar
);
3232 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3233 assert(pp
->x
.p
->type
== polynomial
);
3234 pp
->x
.p
->pos
-= nvar
;
3238 value_set_si(f
.d
, 0);
3239 f
.x
.p
= new_enode(fractional
, 3, -1);
3240 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3241 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3242 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3244 eadd(&f
, &p
->arr
[0]);
3245 reorder_terms_about(p
, &p
->arr
[0]);
3249 free_evalue_refs(&f
);
3252 /* Convert flooring back to fractional and shift position
3253 * of the parameters by nvar
3255 static void floor2frac(evalue
*e
, int nvar
)
3257 floor2frac_r(e
, nvar
);
3261 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
3264 int nparam
= D
->Dimension
- nvar
;
3268 D
= Constraints2Polyhedron(C
, 0);
3272 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3274 /* Double check that D was not unbounded. */
3275 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3283 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3290 evalue
*factor
= NULL
;
3293 if (EVALUE_IS_ZERO(*e
))
3297 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
3304 res
= esum_over_domain(e
, nvar
, Q
, C
);
3307 for (Q
= DD
; Q
; Q
= DD
) {
3313 t
= esum_over_domain(e
, nvar
, Q
, C
);
3320 free_evalue_refs(t
);
3327 if (value_notzero_p(e
->d
)) {
3330 t
= esum_over_domain_cst(nvar
, D
, C
);
3332 if (!EVALUE_IS_ONE(*e
))
3338 switch (e
->x
.p
->type
) {
3340 evalue
*pp
= &e
->x
.p
->arr
[0];
3342 if (pp
->x
.p
->pos
> nvar
) {
3343 /* remainder is independent of the summated vars */
3349 floor2frac(&f
, nvar
);
3351 t
= esum_over_domain_cst(nvar
, D
, C
);
3355 free_evalue_refs(&f
);
3360 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3361 poly_denom(pp
, &row
->p
[1 + nvar
]);
3362 value_set_si(row
->p
[0], 1);
3363 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3364 pp
= &pp
->x
.p
->arr
[0]) {
3366 assert(pp
->x
.p
->type
== polynomial
);
3368 if (pos
>= 1 + nvar
)
3370 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3371 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3372 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3374 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3375 value_division(row
->p
[1 + D
->Dimension
+ 1],
3376 row
->p
[1 + D
->Dimension
+ 1],
3378 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3379 row
->p
[1 + D
->Dimension
+ 1],
3381 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3385 int pos
= e
->x
.p
->pos
;
3388 factor
= ALLOC(evalue
);
3389 value_init(factor
->d
);
3390 value_set_si(factor
->d
, 0);
3391 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3392 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3393 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3397 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3398 for (i
= 0; i
< D
->NbRays
; ++i
)
3399 if (value_notzero_p(D
->Ray
[i
][pos
]))
3401 assert(i
< D
->NbRays
);
3402 if (value_neg_p(D
->Ray
[i
][pos
])) {
3403 factor
= ALLOC(evalue
);
3404 value_init(factor
->d
);
3405 evalue_set_si(factor
, -1, 1);
3407 value_set_si(row
->p
[0], 1);
3408 value_set_si(row
->p
[pos
], 1);
3409 value_set_si(row
->p
[1 + nvar
], -1);
3416 i
= type_offset(e
->x
.p
);
3418 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3423 evalue_copy(&cum
, factor
);
3427 for (; i
< e
->x
.p
->size
; ++i
) {
3431 C
= esum_add_constraint(nvar
, D
, C
, row
);
3437 Vector_Print(stderr, P_VALUE_FMT, row);
3439 Matrix_Print(stderr, P_VALUE_FMT, C);
3441 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3450 free_evalue_refs(t
);
3453 if (factor
&& i
+1 < e
->x
.p
->size
)
3460 free_evalue_refs(factor
);
3461 free_evalue_refs(&cum
);
3473 evalue
*esum(evalue
*e
, int nvar
)
3476 evalue
*res
= ALLOC(evalue
);
3480 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3481 evalue_copy(res
, e
);
3485 evalue_set_si(res
, 0, 1);
3487 assert(value_zero_p(e
->d
));
3488 assert(e
->x
.p
->type
== partition
);
3490 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3492 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3493 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3495 free_evalue_refs(t
);
3504 /* Initial silly implementation */
3505 void eor(evalue
*e1
, evalue
*res
)
3511 evalue_set_si(&mone
, -1, 1);
3513 evalue_copy(&E
, res
);
3519 free_evalue_refs(&E
);
3520 free_evalue_refs(&mone
);
3523 /* computes denominator of polynomial evalue
3524 * d should point to a value initialized to 1
3526 void evalue_denom(const evalue
*e
, Value
*d
)
3530 if (value_notzero_p(e
->d
)) {
3531 value_lcm(*d
, e
->d
, d
);
3534 assert(e
->x
.p
->type
== polynomial
||
3535 e
->x
.p
->type
== fractional
||
3536 e
->x
.p
->type
== flooring
);
3537 offset
= type_offset(e
->x
.p
);
3538 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3539 evalue_denom(&e
->x
.p
->arr
[i
], d
);
3542 /* Divides the evalue e by the integer n */
3543 void evalue_div(evalue
* e
, Value n
)
3547 if (value_notzero_p(e
->d
)) {
3550 value_multiply(e
->d
, e
->d
, n
);
3551 Gcd(e
->x
.n
, e
->d
, &gc
);
3552 if (value_notone_p(gc
)) {
3553 value_division(e
->d
, e
->d
, gc
);
3554 value_division(e
->x
.n
, e
->x
.n
, gc
);
3559 if (e
->x
.p
->type
== partition
) {
3560 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
3561 evalue_div(&e
->x
.p
->arr
[2*i
+1], n
);
3564 offset
= type_offset(e
->x
.p
);
3565 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3566 evalue_div(&e
->x
.p
->arr
[i
], n
);
3569 static void evalue_frac2polynomial_r(evalue
*e
, int *signs
, int sign
, int in_frac
)
3574 int sign_odd
= sign
;
3576 if (value_notzero_p(e
->d
)) {
3577 if (in_frac
&& sign
* value_sign(e
->x
.n
) < 0) {
3578 value_set_si(e
->x
.n
, 0);
3579 value_set_si(e
->d
, 1);
3584 if (e
->x
.p
->type
== relation
) {
3585 for (i
= e
->x
.p
->size
-1; i
>= 1; --i
)
3586 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
, sign
, in_frac
);
3590 if (e
->x
.p
->type
== polynomial
)
3591 sign_odd
*= signs
[e
->x
.p
->pos
-1];
3592 offset
= type_offset(e
->x
.p
);
3593 evalue_frac2polynomial_r(&e
->x
.p
->arr
[offset
], signs
, sign
, in_frac
);
3594 in_frac
|= e
->x
.p
->type
== fractional
;
3595 for (i
= e
->x
.p
->size
-1; i
> offset
; --i
)
3596 evalue_frac2polynomial_r(&e
->x
.p
->arr
[i
], signs
,
3597 (i
- offset
) % 2 ? sign_odd
: sign
, in_frac
);
3599 if (e
->x
.p
->type
!= fractional
)
3602 /* replace { a/m } by (m-1)/m if sign != 0
3603 * and by (m-1)/(2m) if sign == 0
3607 evalue_denom(&e
->x
.p
->arr
[0], &d
);
3608 free_evalue_refs(&e
->x
.p
->arr
[0]);
3609 value_init(e
->x
.p
->arr
[0].d
);
3610 value_init(e
->x
.p
->arr
[0].x
.n
);
3612 value_addto(e
->x
.p
->arr
[0].d
, d
, d
);
3614 value_assign(e
->x
.p
->arr
[0].d
, d
);
3615 value_decrement(e
->x
.p
->arr
[0].x
.n
, d
);
3619 reorder_terms_about(p
, &p
->arr
[0]);
3625 /* Approximate the evalue in fractional representation by a polynomial.
3626 * If sign > 0, the result is an upper bound;
3627 * if sign < 0, the result is a lower bound;
3628 * if sign = 0, the result is an intermediate approximation.
3630 void evalue_frac2polynomial(evalue
*e
, int sign
, unsigned MaxRays
)
3635 if (value_notzero_p(e
->d
))
3637 assert(e
->x
.p
->type
== partition
);
3638 /* make sure all variables in the domains have a fixed sign */
3640 evalue_split_domains_into_orthants(e
, MaxRays
);
3642 assert(e
->x
.p
->size
>= 2);
3643 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3645 signs
= alloca(sizeof(int) * dim
);
3647 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3648 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
3649 POL_ENSURE_VERTICES(D
);
3650 for (j
= 0; j
< dim
; ++j
) {
3654 for (k
= 0; k
< D
->NbRays
; ++k
) {
3655 signs
[j
] = value_sign(D
->Ray
[k
][1+j
]);
3660 evalue_frac2polynomial_r(&e
->x
.p
->arr
[2*i
+1], signs
, sign
, 0);
3664 /* Split the domains of e (which is assumed to be a partition)
3665 * such that each resulting domain lies entirely in one orthant.
3667 void evalue_split_domains_into_orthants(evalue
*e
, unsigned MaxRays
)
3670 assert(value_zero_p(e
->d
));
3671 assert(e
->x
.p
->type
== partition
);
3672 assert(e
->x
.p
->size
>= 2);
3673 dim
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
;
3675 for (i
= 0; i
< dim
; ++i
) {
3678 C
= Matrix_Alloc(1, 1 + dim
+ 1);
3679 value_set_si(C
->p
[0][0], 1);
3680 value_init(split
.d
);
3681 value_set_si(split
.d
, 0);
3682 split
.x
.p
= new_enode(partition
, 4, dim
);
3683 value_set_si(C
->p
[0][1+i
], 1);
3684 C2
= Matrix_Copy(C
);
3685 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[0], Constraints2Polyhedron(C2
, MaxRays
));
3687 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
3688 value_set_si(C
->p
[0][1+i
], -1);
3689 value_set_si(C
->p
[0][1+dim
], -1);
3690 EVALUE_SET_DOMAIN(split
.x
.p
->arr
[2], Constraints2Polyhedron(C
, MaxRays
));
3691 evalue_set_si(&split
.x
.p
->arr
[3], 1, 1);
3693 free_evalue_refs(&split
);
3698 static Matrix
*find_fractional_with_max_periods(evalue
*e
, Polyhedron
*D
,
3700 Value
*min
, Value
*max
)
3706 if (value_notzero_p(e
->d
))
3709 if (e
->x
.p
->type
== fractional
) {
3714 I
= polynomial_projection(e
->x
.p
, D
, &d
, &T
);
3715 bounded
= line_minmax(I
, min
, max
); /* frees I */
3719 value_set_si(mp
, max_periods
);
3720 mpz_fdiv_q(*min
, *min
, d
);
3721 mpz_fdiv_q(*max
, *max
, d
);
3722 value_assign(T
->p
[1][D
->Dimension
], d
);
3723 value_subtract(d
, *max
, *min
);
3724 if (value_ge(d
, mp
)) {
3738 for (i
= type_offset(e
->x
.p
); i
< e
->x
.p
->size
; ++i
)
3739 if ((T
= find_fractional_with_max_periods(&e
->x
.p
->arr
[i
], D
, max_periods
,
3746 /* Look for fractional parts that can be removed by splitting the corresponding
3747 * domain into at most max_periods parts.
3748 * We use a very simply strategy that looks for the first fractional part
3749 * that satisfies the condition, performs the split and then continues
3750 * looking for other fractional parts in the split domains until no
3751 * such fractional part can be found anymore.
3753 void evalue_split_periods(evalue
*e
, int max_periods
, unsigned int MaxRays
)
3760 if (EVALUE_IS_ZERO(*e
))
3762 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
) {
3764 "WARNING: evalue_split_periods called on incorrect evalue type\n");
3772 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3776 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
3778 T
= find_fractional_with_max_periods(&e
->x
.p
->arr
[2*i
+1], D
, max_periods
,
3783 M
= Matrix_Alloc(2, 2+D
->Dimension
);
3785 value_subtract(d
, max
, min
);
3786 n
= VALUE_TO_INT(d
)+1;
3788 value_set_si(M
->p
[0][0], 1);
3789 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
3790 value_multiply(d
, max
, T
->p
[1][D
->Dimension
]);
3791 value_subtract(M
->p
[0][1+D
->Dimension
], M
->p
[0][1+D
->Dimension
], d
);
3792 value_set_si(d
, -1);
3793 value_set_si(M
->p
[1][0], 1);
3794 Vector_Scale(T
->p
[0], M
->p
[1]+1, d
, D
->Dimension
+1);
3795 value_addmul(M
->p
[1][1+D
->Dimension
], max
, T
->p
[1][D
->Dimension
]);
3796 value_addto(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
],
3797 T
->p
[1][D
->Dimension
]);
3798 value_decrement(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
]);
3800 p
= new_enode(partition
, e
->x
.p
->size
+ (n
-1)*2, e
->x
.p
->pos
);
3801 for (j
= 0; j
< 2*i
; ++j
) {
3802 value_clear(p
->arr
[j
].d
);
3803 p
->arr
[j
] = e
->x
.p
->arr
[j
];
3805 for (j
= 2*i
+2; j
< e
->x
.p
->size
; ++j
) {
3806 value_clear(p
->arr
[j
+2*(n
-1)].d
);
3807 p
->arr
[j
+2*(n
-1)] = e
->x
.p
->arr
[j
];
3809 for (j
= n
-1; j
>= 0; --j
) {
3811 value_clear(p
->arr
[2*i
+1].d
);
3812 p
->arr
[2*i
+1] = e
->x
.p
->arr
[2*i
+1];
3814 evalue_copy(&p
->arr
[2*(i
+j
)+1], &e
->x
.p
->arr
[2*i
+1]);
3816 value_subtract(M
->p
[1][1+D
->Dimension
], M
->p
[1][1+D
->Dimension
],
3817 T
->p
[1][D
->Dimension
]);
3818 value_addto(M
->p
[0][1+D
->Dimension
], M
->p
[0][1+D
->Dimension
],
3819 T
->p
[1][D
->Dimension
]);
3821 E
= DomainAddConstraints(D
, M
, MaxRays
);
3822 EVALUE_SET_DOMAIN(p
->arr
[2*(i
+j
)], E
);
3823 if (evalue_range_reduction_in_domain(&p
->arr
[2*(i
+j
)+1], E
))
3824 reduce_evalue(&p
->arr
[2*(i
+j
)+1]);
3826 value_clear(e
->x
.p
->arr
[2*i
].d
);
3840 void evalue_extract_affine(const evalue
*e
, Value
*coeff
, Value
*cst
, Value
*d
)
3842 value_set_si(*d
, 1);
3844 for ( ; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[0]) {
3845 assert(e
->x
.p
->type
== polynomial
);
3846 assert(e
->x
.p
->size
== 2);
3847 evalue
*c
= &e
->x
.p
->arr
[1];
3848 value_multiply(coeff
[e
->x
.p
->pos
-1], *d
, c
->x
.n
);
3849 value_division(coeff
[e
->x
.p
->pos
-1], coeff
[e
->x
.p
->pos
-1], c
->d
);
3851 value_multiply(*cst
, *d
, e
->x
.n
);
3852 value_division(*cst
, *cst
, e
->d
);