6 #include <barvinok/evalue.h>
7 #include <barvinok/barvinok.h>
8 #include <barvinok/util.h>
10 #ifndef value_pmodulus
11 #define value_pmodulus(ref,val1,val2) (mpz_fdiv_r((ref),(val1),(val2)))
14 #define ALLOC(type) (type*)malloc(sizeof(type))
17 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
19 #define NALLOC(p,n) p = (void *)malloc((n) * sizeof(*p))
22 void evalue_set_si(evalue
*ev
, int n
, int d
) {
23 value_set_si(ev
->d
, d
);
25 value_set_si(ev
->x
.n
, n
);
28 void evalue_set(evalue
*ev
, Value n
, Value d
) {
29 value_assign(ev
->d
, d
);
31 value_assign(ev
->x
.n
, n
);
36 evalue
*EP
= ALLOC(evalue
);
38 evalue_set_si(EP
, 0, 1);
42 void aep_evalue(evalue
*e
, int *ref
) {
47 if (value_notzero_p(e
->d
))
48 return; /* a rational number, its already reduced */
50 return; /* hum... an overflow probably occured */
52 /* First check the components of p */
53 for (i
=0;i
<p
->size
;i
++)
54 aep_evalue(&p
->arr
[i
],ref
);
61 p
->pos
= ref
[p
->pos
-1]+1;
67 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
73 if (value_notzero_p(e
->d
))
74 return; /* a rational number, its already reduced */
76 return; /* hum... an overflow probably occured */
79 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
80 for(i
=0;i
<CT
->NbRows
-1;i
++)
81 for(j
=0;j
<CT
->NbColumns
;j
++)
82 if(value_notzero_p(CT
->p
[i
][j
])) {
87 /* Transform the references in e, using ref */
91 } /* addeliminatedparams_evalue */
93 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
94 unsigned MaxRays
, unsigned nparam
)
99 if (CT
->NbRows
== CT
->NbColumns
)
102 if (EVALUE_IS_ZERO(*e
))
105 if (value_notzero_p(e
->d
)) {
108 value_set_si(res
.d
, 0);
109 res
.x
.p
= new_enode(partition
, 2, nparam
);
110 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
111 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
112 value_clear(res
.x
.p
->arr
[1].d
);
113 res
.x
.p
->arr
[1] = *e
;
120 assert(p
->type
== partition
);
123 for (i
=0; i
<p
->size
/2; i
++) {
124 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
125 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
128 T
= DomainIntersection(D
, CEq
, MaxRays
);
130 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
131 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
135 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
143 assert(value_notzero_p(e1
->d
));
144 assert(value_notzero_p(e2
->d
));
145 value_multiply(m
, e1
->x
.n
, e2
->d
);
146 value_multiply(m2
, e2
->x
.n
, e1
->d
);
149 else if (value_gt(m
, m2
))
159 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
161 if (value_notzero_p(e1
->d
)) {
163 if (value_zero_p(e2
->d
))
165 r
= mod_rational_smaller(e1
, e2
);
166 return r
== -1 ? 0 : r
;
168 if (value_notzero_p(e2
->d
))
170 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
172 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
175 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
177 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
182 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
184 assert(value_zero_p(e1
->d
));
185 assert(value_zero_p(e2
->d
));
186 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
187 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
188 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
191 /* Negative pos means inequality */
192 /* s is negative of substitution if m is not zero */
201 struct fixed_param
*fixed
;
206 static int relations_depth(evalue
*e
)
211 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
212 e
= &e
->x
.p
->arr
[1], ++d
);
216 static void poly_denom_not_constant(evalue
**pp
, Value
*d
)
221 while (value_zero_p(p
->d
)) {
222 assert(p
->x
.p
->type
== polynomial
);
223 assert(p
->x
.p
->size
== 2);
224 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
225 value_lcm(*d
, p
->x
.p
->arr
[1].d
, d
);
231 static void poly_denom(evalue
*p
, Value
*d
)
233 poly_denom_not_constant(&p
, d
);
234 value_lcm(*d
, p
->d
, d
);
237 static void realloc_substitution(struct subst
*s
, int d
)
239 struct fixed_param
*n
;
242 for (i
= 0; i
< s
->n
; ++i
)
249 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
255 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
258 /* May have been reduced already */
259 if (value_notzero_p(m
->d
))
262 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
263 assert(m
->x
.p
->size
== 3);
265 /* fractional was inverted during reduction
266 * invert it back and move constant in
268 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
269 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
270 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
271 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
272 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
273 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
274 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
275 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
276 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
277 value_set_si(m
->x
.p
->arr
[1].d
, 1);
280 /* Oops. Nested identical relations. */
281 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
284 if (s
->n
>= s
->max
) {
285 int d
= relations_depth(r
);
286 realloc_substitution(s
, d
);
290 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
291 assert(p
->x
.p
->size
== 2);
294 assert(value_pos_p(f
->x
.n
));
296 value_init(s
->fixed
[s
->n
].m
);
297 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
298 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
299 value_init(s
->fixed
[s
->n
].d
);
300 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
301 value_init(s
->fixed
[s
->n
].s
.d
);
302 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
308 static int type_offset(enode
*p
)
310 return p
->type
== fractional
? 1 :
311 p
->type
== flooring
? 1 : 0;
314 static void reorder_terms(enode
*p
, evalue
*v
)
317 int offset
= type_offset(p
);
319 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
321 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
322 free_evalue_refs(&(p
->arr
[i
]));
328 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
334 if (value_notzero_p(e
->d
)) {
336 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
337 return; /* a rational number, its already reduced */
341 return; /* hum... an overflow probably occured */
343 /* First reduce the components of p */
344 add
= p
->type
== relation
;
345 for (i
=0; i
<p
->size
; i
++) {
347 add
= add_modulo_substitution(s
, e
);
349 if (i
== 0 && p
->type
==fractional
)
350 _reduce_evalue(&p
->arr
[i
], s
, 1);
352 _reduce_evalue(&p
->arr
[i
], s
, fract
);
354 if (add
&& i
== p
->size
-1) {
356 value_clear(s
->fixed
[s
->n
].m
);
357 value_clear(s
->fixed
[s
->n
].d
);
358 free_evalue_refs(&s
->fixed
[s
->n
].s
);
359 } else if (add
&& i
== 1)
360 s
->fixed
[s
->n
-1].pos
*= -1;
363 if (p
->type
==periodic
) {
365 /* Try to reduce the period */
366 for (i
=1; i
<=(p
->size
)/2; i
++) {
367 if ((p
->size
% i
)==0) {
369 /* Can we reduce the size to i ? */
371 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
372 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
375 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
379 you_lose
: /* OK, lets not do it */
384 /* Try to reduce its strength */
387 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
391 else if (p
->type
==polynomial
) {
392 for (k
= 0; s
&& k
< s
->n
; ++k
) {
393 if (s
->fixed
[k
].pos
== p
->pos
) {
394 int divide
= value_notone_p(s
->fixed
[k
].d
);
397 if (value_notzero_p(s
->fixed
[k
].m
)) {
400 assert(p
->size
== 2);
401 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
403 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
410 value_assign(d
.d
, s
->fixed
[k
].d
);
412 if (value_notzero_p(s
->fixed
[k
].m
))
413 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
415 value_set_si(d
.x
.n
, 1);
418 for (i
=p
->size
-1;i
>=1;i
--) {
419 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
421 emul(&d
, &p
->arr
[i
]);
422 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
423 free_evalue_refs(&(p
->arr
[i
]));
426 _reduce_evalue(&p
->arr
[0], s
, fract
);
429 free_evalue_refs(&d
);
435 /* Try to reduce the degree */
436 for (i
=p
->size
-1;i
>=1;i
--) {
437 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
439 /* Zero coefficient */
440 free_evalue_refs(&(p
->arr
[i
]));
445 /* Try to reduce its strength */
448 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
452 else if (p
->type
==fractional
) {
456 if (value_notzero_p(p
->arr
[0].d
)) {
458 value_assign(v
.d
, p
->arr
[0].d
);
460 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
465 evalue
*pp
= &p
->arr
[0];
466 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
467 assert(pp
->x
.p
->size
== 2);
469 /* search for exact duplicate among the modulo inequalities */
471 f
= &pp
->x
.p
->arr
[1];
472 for (k
= 0; s
&& k
< s
->n
; ++k
) {
473 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
474 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
475 value_eq(s
->fixed
[k
].m
, f
->d
) &&
476 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
483 /* replace { E/m } by { (E-1)/m } + 1/m */
488 evalue_set_si(&extra
, 1, 1);
489 value_assign(extra
.d
, g
);
490 eadd(&extra
, &v
.x
.p
->arr
[1]);
491 free_evalue_refs(&extra
);
493 /* We've been going in circles; stop now */
494 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
495 free_evalue_refs(&v
);
497 evalue_set_si(&v
, 0, 1);
502 value_set_si(v
.d
, 0);
503 v
.x
.p
= new_enode(fractional
, 3, -1);
504 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
505 value_assign(v
.x
.p
->arr
[1].d
, g
);
506 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
507 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
510 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
513 value_division(f
->d
, g
, f
->d
);
514 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
515 value_assign(f
->d
, g
);
516 value_decrement(f
->x
.n
, f
->x
.n
);
517 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
519 Gcd(f
->d
, f
->x
.n
, &g
);
520 value_division(f
->d
, f
->d
, g
);
521 value_division(f
->x
.n
, f
->x
.n
, g
);
530 /* reduction may have made this fractional arg smaller */
531 i
= reorder
? p
->size
: 1;
532 for ( ; i
< p
->size
; ++i
)
533 if (value_zero_p(p
->arr
[i
].d
) &&
534 p
->arr
[i
].x
.p
->type
== fractional
&&
535 !mod_term_smaller(e
, &p
->arr
[i
]))
539 value_set_si(v
.d
, 0);
540 v
.x
.p
= new_enode(fractional
, 3, -1);
541 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
542 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
543 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
551 evalue
*pp
= &p
->arr
[0];
554 poly_denom_not_constant(&pp
, &m
);
555 mpz_fdiv_r(r
, m
, pp
->d
);
556 if (value_notzero_p(r
)) {
558 value_set_si(v
.d
, 0);
559 v
.x
.p
= new_enode(fractional
, 3, -1);
561 value_multiply(r
, m
, pp
->x
.n
);
562 value_multiply(v
.x
.p
->arr
[1].d
, m
, pp
->d
);
563 value_init(v
.x
.p
->arr
[1].x
.n
);
564 mpz_fdiv_r(v
.x
.p
->arr
[1].x
.n
, r
, pp
->d
);
565 mpz_fdiv_q(r
, r
, pp
->d
);
567 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
568 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
570 while (value_zero_p(pp
->d
))
571 pp
= &pp
->x
.p
->arr
[0];
573 value_assign(pp
->d
, m
);
574 value_assign(pp
->x
.n
, r
);
576 Gcd(pp
->d
, pp
->x
.n
, &r
);
577 value_division(pp
->d
, pp
->d
, r
);
578 value_division(pp
->x
.n
, pp
->x
.n
, r
);
591 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
592 pp
= &pp
->x
.p
->arr
[0]) {
593 f
= &pp
->x
.p
->arr
[1];
594 assert(value_pos_p(f
->d
));
595 mpz_mul_ui(twice
, f
->x
.n
, 2);
596 if (value_lt(twice
, f
->d
))
598 if (value_eq(twice
, f
->d
))
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], 0, 1);
609 poly_denom(&p
->arr
[0], &twice
);
610 value_assign(v
.x
.p
->arr
[1].d
, twice
);
611 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
612 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
613 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
615 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
616 pp
= &pp
->x
.p
->arr
[0]) {
617 f
= &pp
->x
.p
->arr
[1];
618 value_oppose(f
->x
.n
, f
->x
.n
);
619 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
621 value_division(pp
->d
, twice
, pp
->d
);
622 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
623 value_assign(pp
->d
, twice
);
624 value_oppose(pp
->x
.n
, pp
->x
.n
);
625 value_decrement(pp
->x
.n
, pp
->x
.n
);
626 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
628 /* Maybe we should do this during reduction of
631 Gcd(pp
->d
, pp
->x
.n
, &twice
);
632 value_division(pp
->d
, pp
->d
, twice
);
633 value_division(pp
->x
.n
, pp
->x
.n
, twice
);
643 reorder_terms(p
, &v
);
644 _reduce_evalue(&p
->arr
[1], s
, fract
);
647 /* Try to reduce the degree */
648 for (i
=p
->size
-1;i
>=2;i
--) {
649 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
651 /* Zero coefficient */
652 free_evalue_refs(&(p
->arr
[i
]));
657 /* Try to reduce its strength */
660 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
661 free_evalue_refs(&(p
->arr
[0]));
665 else if (p
->type
== flooring
) {
666 /* Try to reduce the degree */
667 for (i
=p
->size
-1;i
>=2;i
--) {
668 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
670 /* Zero coefficient */
671 free_evalue_refs(&(p
->arr
[i
]));
676 /* Try to reduce its strength */
679 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
680 free_evalue_refs(&(p
->arr
[0]));
684 else if (p
->type
== relation
) {
685 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
686 free_evalue_refs(&(p
->arr
[2]));
687 free_evalue_refs(&(p
->arr
[0]));
694 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
695 free_evalue_refs(&(p
->arr
[2]));
698 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
699 free_evalue_refs(&(p
->arr
[1]));
700 free_evalue_refs(&(p
->arr
[0]));
701 evalue_set_si(e
, 0, 1);
708 /* Relation was reduced by means of an identical
709 * inequality => remove
711 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
714 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
715 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
717 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
719 free_evalue_refs(&(p
->arr
[2]));
723 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
725 evalue_set_si(e
, 0, 1);
726 free_evalue_refs(&(p
->arr
[1]));
728 free_evalue_refs(&(p
->arr
[0]));
734 } /* reduce_evalue */
736 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
741 for (k
= 0; k
< dim
; ++k
)
742 if (value_notzero_p(row
[k
+1]))
745 Vector_Normalize_Positive(row
+1, dim
+1, k
);
746 assert(s
->n
< s
->max
);
747 value_init(s
->fixed
[s
->n
].d
);
748 value_init(s
->fixed
[s
->n
].m
);
749 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
750 s
->fixed
[s
->n
].pos
= k
+1;
751 value_set_si(s
->fixed
[s
->n
].m
, 0);
752 r
= &s
->fixed
[s
->n
].s
;
754 for (l
= k
+1; l
< dim
; ++l
)
755 if (value_notzero_p(row
[l
+1])) {
756 value_set_si(r
->d
, 0);
757 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
758 value_init(r
->x
.p
->arr
[1].x
.n
);
759 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
760 value_set_si(r
->x
.p
->arr
[1].d
, 1);
764 value_oppose(r
->x
.n
, row
[dim
+1]);
765 value_set_si(r
->d
, 1);
769 void reduce_evalue (evalue
*e
) {
770 struct subst s
= { NULL
, 0, 0 };
772 if (value_notzero_p(e
->d
))
773 return; /* a rational number, its already reduced */
775 if (e
->x
.p
->type
== partition
) {
778 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
779 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
781 /* This shouldn't really happen;
782 * Empty domains should not be added.
784 POL_ENSURE_VERTICES(D
);
790 D
= DomainConvex(D
, 0);
791 if (!D
->next
&& D
->NbEq
) {
795 realloc_substitution(&s
, dim
);
797 int d
= relations_depth(&e
->x
.p
->arr
[2*i
+1]);
799 NALLOC(s
.fixed
, s
.max
);
802 for (j
= 0; j
< D
->NbEq
; ++j
)
803 add_substitution(&s
, D
->Constraint
[j
], dim
);
805 if (D
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
807 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
808 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
810 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
811 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
812 value_clear(e
->x
.p
->arr
[2*i
].d
);
814 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
815 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
820 for (j
= 0; j
< s
.n
; ++j
) {
821 value_clear(s
.fixed
[j
].d
);
822 value_clear(s
.fixed
[j
].m
);
823 free_evalue_refs(&s
.fixed
[j
].s
);
827 if (e
->x
.p
->size
== 0) {
829 evalue_set_si(e
, 0, 1);
832 _reduce_evalue(e
, &s
, 0);
837 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
839 if(value_notzero_p(e
->d
)) {
840 if(value_notone_p(e
->d
)) {
841 value_print(DST
,VALUE_FMT
,e
->x
.n
);
843 value_print(DST
,VALUE_FMT
,e
->d
);
846 value_print(DST
,VALUE_FMT
,e
->x
.n
);
850 print_enode(DST
,e
->x
.p
,pname
);
854 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
859 fprintf(DST
, "NULL");
865 for (i
=0; i
<p
->size
; i
++) {
866 print_evalue(DST
, &p
->arr
[i
], pname
);
870 fprintf(DST
, " }\n");
874 for (i
=p
->size
-1; i
>=0; i
--) {
875 print_evalue(DST
, &p
->arr
[i
], pname
);
876 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
878 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
880 fprintf(DST
, " )\n");
884 for (i
=0; i
<p
->size
; i
++) {
885 print_evalue(DST
, &p
->arr
[i
], pname
);
886 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
888 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
893 for (i
=p
->size
-1; i
>=1; i
--) {
894 print_evalue(DST
, &p
->arr
[i
], pname
);
897 fprintf(DST
, p
->type
== flooring
? "[" : "{");
898 print_evalue(DST
, &p
->arr
[0], pname
);
899 fprintf(DST
, p
->type
== flooring
? "]" : "}");
901 fprintf(DST
, "^%d + ", i
-1);
906 fprintf(DST
, " )\n");
910 print_evalue(DST
, &p
->arr
[0], pname
);
911 fprintf(DST
, "= 0 ] * \n");
912 print_evalue(DST
, &p
->arr
[1], pname
);
914 fprintf(DST
, " +\n [ ");
915 print_evalue(DST
, &p
->arr
[0], pname
);
916 fprintf(DST
, "!= 0 ] * \n");
917 print_evalue(DST
, &p
->arr
[2], pname
);
921 char **names
= pname
;
922 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
923 if (!pname
|| p
->pos
< maxdim
) {
924 NALLOC(names
, maxdim
);
925 for (i
= 0; i
< p
->pos
; ++i
) {
929 NALLOC(names
[i
], 10);
930 snprintf(names
[i
], 10, "%c", 'P'+i
);
933 for ( ; i
< maxdim
; ++i
) {
934 NALLOC(names
[i
], 10);
935 snprintf(names
[i
], 10, "_p%d", i
);
939 for (i
=0; i
<p
->size
/2; i
++) {
940 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
941 print_evalue(DST
, &p
->arr
[2*i
+1], names
);
944 if (!pname
|| p
->pos
< maxdim
) {
945 for (i
= pname
? p
->pos
: 0; i
< maxdim
; ++i
)
958 static void eadd_rev(evalue
*e1
, evalue
*res
)
962 evalue_copy(&ev
, e1
);
964 free_evalue_refs(res
);
968 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
972 evalue_copy(&ev
, e1
);
973 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
974 free_evalue_refs(res
);
978 static int is_zero_on(evalue
*e
, Polyhedron
*D
)
983 tmp
.x
.p
= new_enode(partition
, 2, D
->Dimension
);
984 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Domain_Copy(D
));
985 evalue_copy(&tmp
.x
.p
->arr
[1], e
);
987 is_zero
= EVALUE_IS_ZERO(tmp
);
988 free_evalue_refs(&tmp
);
992 struct section
{ Polyhedron
* D
; evalue E
; };
994 void eadd_partitions (evalue
*e1
,evalue
*res
)
999 s
= (struct section
*)
1000 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
1001 sizeof(struct section
));
1003 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1004 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1005 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1008 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1009 assert(res
->x
.p
->size
>= 2);
1010 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1011 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
1013 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
1015 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1024 /* See if we can extend one of the domains in res to cover fd */
1025 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1026 if (is_zero_on(&res
->x
.p
->arr
[2*i
+1], fd
))
1028 if (i
< res
->x
.p
->size
/2) {
1029 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
1030 DomainConcat(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
])));
1033 value_init(s
[n
].E
.d
);
1034 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
1038 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1039 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
1040 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1042 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1043 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1049 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1050 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1052 value_init(s
[n
].E
.d
);
1053 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1054 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1055 if (!emptyQ(fd
) && is_zero_on(&e1
->x
.p
->arr
[2*j
+1], fd
)) {
1056 d
= DomainConcat(fd
, d
);
1057 fd
= Empty_Polyhedron(fd
->Dimension
);
1063 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1067 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1070 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1071 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1072 value_clear(res
->x
.p
->arr
[2*i
].d
);
1077 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1078 for (j
= 0; j
< n
; ++j
) {
1079 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1080 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1081 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1082 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1088 static void explicit_complement(evalue
*res
)
1090 enode
*rel
= new_enode(relation
, 3, 0);
1092 value_clear(rel
->arr
[0].d
);
1093 rel
->arr
[0] = res
->x
.p
->arr
[0];
1094 value_clear(rel
->arr
[1].d
);
1095 rel
->arr
[1] = res
->x
.p
->arr
[1];
1096 value_set_si(rel
->arr
[2].d
, 1);
1097 value_init(rel
->arr
[2].x
.n
);
1098 value_set_si(rel
->arr
[2].x
.n
, 0);
1103 void eadd(evalue
*e1
,evalue
*res
) {
1106 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1107 /* Add two rational numbers */
1113 value_multiply(m1
,e1
->x
.n
,res
->d
);
1114 value_multiply(m2
,res
->x
.n
,e1
->d
);
1115 value_addto(res
->x
.n
,m1
,m2
);
1116 value_multiply(res
->d
,e1
->d
,res
->d
);
1117 Gcd(res
->x
.n
,res
->d
,&g
);
1118 if (value_notone_p(g
)) {
1119 value_division(res
->d
,res
->d
,g
);
1120 value_division(res
->x
.n
,res
->x
.n
,g
);
1122 value_clear(g
); value_clear(m1
); value_clear(m2
);
1125 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1126 switch (res
->x
.p
->type
) {
1128 /* Add the constant to the constant term of a polynomial*/
1129 eadd(e1
, &res
->x
.p
->arr
[0]);
1132 /* Add the constant to all elements of a periodic number */
1133 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1134 eadd(e1
, &res
->x
.p
->arr
[i
]);
1138 fprintf(stderr
, "eadd: cannot add const with vector\n");
1142 eadd(e1
, &res
->x
.p
->arr
[1]);
1145 assert(EVALUE_IS_ZERO(*e1
));
1146 break; /* Do nothing */
1148 /* Create (zero) complement if needed */
1149 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1150 explicit_complement(res
);
1151 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1152 eadd(e1
, &res
->x
.p
->arr
[i
]);
1158 /* add polynomial or periodic to constant
1159 * you have to exchange e1 and res, before doing addition */
1161 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1165 else { // ((e1->d==0) && (res->d==0))
1166 assert(!((e1
->x
.p
->type
== partition
) ^
1167 (res
->x
.p
->type
== partition
)));
1168 if (e1
->x
.p
->type
== partition
) {
1169 eadd_partitions(e1
, res
);
1172 if (e1
->x
.p
->type
== relation
&&
1173 (res
->x
.p
->type
!= relation
||
1174 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1178 if (res
->x
.p
->type
== relation
) {
1179 if (e1
->x
.p
->type
== relation
&&
1180 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1181 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1182 explicit_complement(res
);
1183 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1184 explicit_complement(e1
);
1185 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1186 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1189 if (res
->x
.p
->size
< 3)
1190 explicit_complement(res
);
1191 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1192 eadd(e1
, &res
->x
.p
->arr
[i
]);
1195 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1196 /* adding to evalues of different type. two cases are possible
1197 * res is periodic and e1 is polynomial, you have to exchange
1198 * e1 and res then to add e1 to the constant term of res */
1199 if (e1
->x
.p
->type
== polynomial
) {
1200 eadd_rev_cst(e1
, res
);
1202 else if (res
->x
.p
->type
== polynomial
) {
1203 /* res is polynomial and e1 is periodic,
1204 add e1 to the constant term of res */
1206 eadd(e1
,&res
->x
.p
->arr
[0]);
1212 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1213 ((res
->x
.p
->type
== fractional
||
1214 res
->x
.p
->type
== flooring
) &&
1215 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1216 /* adding evalues of different position (i.e function of different unknowns
1217 * to case are possible */
1219 switch (res
->x
.p
->type
) {
1222 if(mod_term_smaller(res
, e1
))
1223 eadd(e1
,&res
->x
.p
->arr
[1]);
1225 eadd_rev_cst(e1
, res
);
1227 case polynomial
: // res and e1 are polynomials
1228 // add e1 to the constant term of res
1230 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1231 eadd(e1
,&res
->x
.p
->arr
[0]);
1233 eadd_rev_cst(e1
, res
);
1234 // value_clear(g); value_clear(m1); value_clear(m2);
1236 case periodic
: // res and e1 are pointers to periodic numbers
1237 //add e1 to all elements of res
1239 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1240 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1241 eadd(e1
,&res
->x
.p
->arr
[i
]);
1252 //same type , same pos and same size
1253 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1254 // add any element in e1 to the corresponding element in res
1255 i
= type_offset(res
->x
.p
);
1257 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1258 for (; i
<res
->x
.p
->size
; i
++) {
1259 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1264 /* Sizes are different */
1265 switch(res
->x
.p
->type
) {
1269 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1270 /* new enode and add res to that new node. If you do not do */
1271 /* that, you lose the the upper weight part of e1 ! */
1273 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1276 i
= type_offset(res
->x
.p
);
1278 assert(eequal(&e1
->x
.p
->arr
[0],
1279 &res
->x
.p
->arr
[0]));
1280 for (; i
<e1
->x
.p
->size
; i
++) {
1281 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1288 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1291 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1292 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1293 to add periodicaly elements of e1 to elements of ne, and finaly to
1298 value_init(ex
); value_init(ey
);value_init(ep
);
1301 value_set_si(ex
,e1
->x
.p
->size
);
1302 value_set_si(ey
,res
->x
.p
->size
);
1303 value_assign (ep
,*Lcm(ex
,ey
));
1304 p
=(int)mpz_get_si(ep
);
1305 ne
= (evalue
*) malloc (sizeof(evalue
));
1307 value_set_si( ne
->d
,0);
1309 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1311 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1314 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1317 value_assign(res
->d
, ne
->d
);
1323 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1332 static void emul_rev (evalue
*e1
, evalue
*res
)
1336 evalue_copy(&ev
, e1
);
1338 free_evalue_refs(res
);
1342 static void emul_poly (evalue
*e1
, evalue
*res
)
1344 int i
, j
, o
= type_offset(res
->x
.p
);
1346 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1348 value_set_si(tmp
.d
,0);
1349 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1351 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1352 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1353 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1354 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1357 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1358 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1359 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1362 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1363 emul(&res
->x
.p
->arr
[i
], &ev
);
1364 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1365 free_evalue_refs(&ev
);
1367 free_evalue_refs(res
);
1371 void emul_partitions (evalue
*e1
,evalue
*res
)
1376 s
= (struct section
*)
1377 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1378 sizeof(struct section
));
1380 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1381 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1382 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1385 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1386 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1387 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1388 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1394 /* This code is only needed because the partitions
1395 are not true partitions.
1397 for (k
= 0; k
< n
; ++k
) {
1398 if (DomainIncludes(s
[k
].D
, d
))
1400 if (DomainIncludes(d
, s
[k
].D
)) {
1401 Domain_Free(s
[k
].D
);
1402 free_evalue_refs(&s
[k
].E
);
1413 value_init(s
[n
].E
.d
);
1414 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1415 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1419 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1420 value_clear(res
->x
.p
->arr
[2*i
].d
);
1421 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1426 evalue_set_si(res
, 0, 1);
1428 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1429 for (j
= 0; j
< n
; ++j
) {
1430 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1431 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1432 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1433 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1440 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1442 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1443 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1444 * evalues is not treated here */
1446 void emul (evalue
*e1
, evalue
*res
){
1449 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1450 fprintf(stderr
, "emul: do not proced on evector type !\n");
1454 if (EVALUE_IS_ZERO(*res
))
1457 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1458 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1459 emul_partitions(e1
, res
);
1462 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1463 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1464 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1466 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1467 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1468 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1469 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1470 explicit_complement(res
);
1471 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1472 explicit_complement(e1
);
1473 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1474 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1477 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1478 emul(e1
, &res
->x
.p
->arr
[i
]);
1480 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1481 switch(e1
->x
.p
->type
) {
1483 switch(res
->x
.p
->type
) {
1485 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1486 /* Product of two polynomials of the same variable */
1491 /* Product of two polynomials of different variables */
1493 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1494 for( i
=0; i
<res
->x
.p
->size
; i
++)
1495 emul(e1
, &res
->x
.p
->arr
[i
]);
1504 /* Product of a polynomial and a periodic or fractional */
1511 switch(res
->x
.p
->type
) {
1513 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1514 /* Product of two periodics of the same parameter and period */
1516 for(i
=0; i
<res
->x
.p
->size
;i
++)
1517 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1522 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1523 /* Product of two periodics of the same parameter and different periods */
1527 value_init(x
); value_init(y
);value_init(z
);
1530 value_set_si(x
,e1
->x
.p
->size
);
1531 value_set_si(y
,res
->x
.p
->size
);
1532 value_assign (z
,*Lcm(x
,y
));
1533 lcm
=(int)mpz_get_si(z
);
1534 newp
= (evalue
*) malloc (sizeof(evalue
));
1535 value_init(newp
->d
);
1536 value_set_si( newp
->d
,0);
1537 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1538 for(i
=0;i
<lcm
;i
++) {
1539 evalue_copy(&newp
->x
.p
->arr
[i
],
1540 &res
->x
.p
->arr
[i
%iy
]);
1543 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1545 value_assign(res
->d
,newp
->d
);
1548 value_clear(x
); value_clear(y
);value_clear(z
);
1552 /* Product of two periodics of different parameters */
1554 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1555 for(i
=0; i
<res
->x
.p
->size
; i
++)
1556 emul(e1
, &(res
->x
.p
->arr
[i
]));
1564 /* Product of a periodic and a polynomial */
1566 for(i
=0; i
<res
->x
.p
->size
; i
++)
1567 emul(e1
, &(res
->x
.p
->arr
[i
]));
1574 switch(res
->x
.p
->type
) {
1576 for(i
=0; i
<res
->x
.p
->size
; i
++)
1577 emul(e1
, &(res
->x
.p
->arr
[i
]));
1584 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1585 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1586 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1589 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1590 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1595 value_set_si(d
.x
.n
, 1);
1596 /* { x }^2 == { x }/2 */
1597 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1598 assert(e1
->x
.p
->size
== 3);
1599 assert(res
->x
.p
->size
== 3);
1601 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1603 eadd(&res
->x
.p
->arr
[1], &tmp
);
1604 emul(&e1
->x
.p
->arr
[2], &tmp
);
1605 emul(&e1
->x
.p
->arr
[1], res
);
1606 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1607 free_evalue_refs(&tmp
);
1612 if(mod_term_smaller(res
, e1
))
1613 for(i
=1; i
<res
->x
.p
->size
; i
++)
1614 emul(e1
, &(res
->x
.p
->arr
[i
]));
1629 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1630 /* Product of two rational numbers */
1634 value_multiply(res
->d
,e1
->d
,res
->d
);
1635 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1636 Gcd(res
->x
.n
, res
->d
,&g
);
1637 if (value_notone_p(g
)) {
1638 value_division(res
->d
,res
->d
,g
);
1639 value_division(res
->x
.n
,res
->x
.n
,g
);
1645 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1646 /* Product of an expression (polynomial or peririodic) and a rational number */
1652 /* Product of a rationel number and an expression (polynomial or peririodic) */
1654 i
= type_offset(res
->x
.p
);
1655 for (; i
<res
->x
.p
->size
; i
++)
1656 emul(e1
, &res
->x
.p
->arr
[i
]);
1666 /* Frees mask content ! */
1667 void emask(evalue
*mask
, evalue
*res
) {
1674 if (EVALUE_IS_ZERO(*res
)) {
1675 free_evalue_refs(mask
);
1679 assert(value_zero_p(mask
->d
));
1680 assert(mask
->x
.p
->type
== partition
);
1681 assert(value_zero_p(res
->d
));
1682 assert(res
->x
.p
->type
== partition
);
1683 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1684 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1685 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1686 pos
= res
->x
.p
->pos
;
1688 s
= (struct section
*)
1689 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1690 sizeof(struct section
));
1694 evalue_set_si(&mone
, -1, 1);
1697 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1698 assert(mask
->x
.p
->size
>= 2);
1699 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1700 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1702 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1704 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1713 value_init(s
[n
].E
.d
);
1714 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1718 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1719 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1722 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1723 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1724 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1725 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1727 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1728 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1734 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1735 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1737 value_init(s
[n
].E
.d
);
1738 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1739 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1745 /* Just ignore; this may have been previously masked off */
1747 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1751 free_evalue_refs(&mone
);
1752 free_evalue_refs(mask
);
1753 free_evalue_refs(res
);
1756 evalue_set_si(res
, 0, 1);
1758 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1759 for (j
= 0; j
< n
; ++j
) {
1760 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1761 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1762 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1769 void evalue_copy(evalue
*dst
, evalue
*src
)
1771 value_assign(dst
->d
, src
->d
);
1772 if(value_notzero_p(src
->d
)) {
1773 value_init(dst
->x
.n
);
1774 value_assign(dst
->x
.n
, src
->x
.n
);
1776 dst
->x
.p
= ecopy(src
->x
.p
);
1779 enode
*new_enode(enode_type type
,int size
,int pos
) {
1785 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1788 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1792 for(i
=0; i
<size
; i
++) {
1793 value_init(res
->arr
[i
].d
);
1794 value_set_si(res
->arr
[i
].d
,0);
1795 res
->arr
[i
].x
.p
= 0;
1800 enode
*ecopy(enode
*e
) {
1805 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1806 for(i
=0;i
<e
->size
;++i
) {
1807 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1808 if(value_zero_p(res
->arr
[i
].d
))
1809 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1810 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1811 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1813 value_init(res
->arr
[i
].x
.n
);
1814 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1820 int ecmp(const evalue
*e1
, const evalue
*e2
)
1826 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1830 value_multiply(m
, e1
->x
.n
, e2
->d
);
1831 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1833 if (value_lt(m
, m2
))
1835 else if (value_gt(m
, m2
))
1845 if (value_notzero_p(e1
->d
))
1847 if (value_notzero_p(e2
->d
))
1853 if (p1
->type
!= p2
->type
)
1854 return p1
->type
- p2
->type
;
1855 if (p1
->pos
!= p2
->pos
)
1856 return p1
->pos
- p2
->pos
;
1857 if (p1
->size
!= p2
->size
)
1858 return p1
->size
- p2
->size
;
1860 for (i
= p1
->size
-1; i
>= 0; --i
)
1861 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1867 int eequal(evalue
*e1
,evalue
*e2
) {
1872 if (value_ne(e1
->d
,e2
->d
))
1875 /* e1->d == e2->d */
1876 if (value_notzero_p(e1
->d
)) {
1877 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1880 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1884 /* e1->d == e2->d == 0 */
1887 if (p1
->type
!= p2
->type
) return 0;
1888 if (p1
->size
!= p2
->size
) return 0;
1889 if (p1
->pos
!= p2
->pos
) return 0;
1890 for (i
=0; i
<p1
->size
; i
++)
1891 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1896 void free_evalue_refs(evalue
*e
) {
1901 if (EVALUE_IS_DOMAIN(*e
)) {
1902 Domain_Free(EVALUE_DOMAIN(*e
));
1905 } else if (value_pos_p(e
->d
)) {
1907 /* 'e' stores a constant */
1909 value_clear(e
->x
.n
);
1912 assert(value_zero_p(e
->d
));
1915 if (!p
) return; /* null pointer */
1916 for (i
=0; i
<p
->size
; i
++) {
1917 free_evalue_refs(&(p
->arr
[i
]));
1921 } /* free_evalue_refs */
1923 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1924 Vector
* val
, evalue
*res
)
1926 unsigned nparam
= periods
->Size
;
1929 double d
= compute_evalue(e
, val
->p
);
1930 d
*= VALUE_TO_DOUBLE(m
);
1935 value_assign(res
->d
, m
);
1936 value_init(res
->x
.n
);
1937 value_set_double(res
->x
.n
, d
);
1938 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1941 if (value_one_p(periods
->p
[p
]))
1942 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1947 value_assign(tmp
, periods
->p
[p
]);
1948 value_set_si(res
->d
, 0);
1949 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1951 value_decrement(tmp
, tmp
);
1952 value_assign(val
->p
[p
], tmp
);
1953 mod2table_r(e
, periods
, m
, p
+1, val
,
1954 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1955 } while (value_pos_p(tmp
));
1961 static void rel2table(evalue
*e
, int zero
)
1963 if (value_pos_p(e
->d
)) {
1964 if (value_zero_p(e
->x
.n
) == zero
)
1965 value_set_si(e
->x
.n
, 1);
1967 value_set_si(e
->x
.n
, 0);
1968 value_set_si(e
->d
, 1);
1971 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1972 rel2table(&e
->x
.p
->arr
[i
], zero
);
1976 void evalue_mod2table(evalue
*e
, int nparam
)
1981 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1984 for (i
=0; i
<p
->size
; i
++) {
1985 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1987 if (p
->type
== relation
) {
1992 evalue_copy(©
, &p
->arr
[0]);
1994 rel2table(&p
->arr
[0], 1);
1995 emul(&p
->arr
[0], &p
->arr
[1]);
1997 rel2table(©
, 0);
1998 emul(©
, &p
->arr
[2]);
1999 eadd(&p
->arr
[2], &p
->arr
[1]);
2000 free_evalue_refs(&p
->arr
[2]);
2001 free_evalue_refs(©
);
2003 free_evalue_refs(&p
->arr
[0]);
2007 } else if (p
->type
== fractional
) {
2008 Vector
*periods
= Vector_Alloc(nparam
);
2009 Vector
*val
= Vector_Alloc(nparam
);
2015 value_set_si(tmp
, 1);
2016 Vector_Set(periods
->p
, 1, nparam
);
2017 Vector_Set(val
->p
, 0, nparam
);
2018 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2021 assert(p
->type
== polynomial
);
2022 assert(p
->size
== 2);
2023 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2024 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
2026 value_lcm(tmp
, ev
->d
, &tmp
);
2028 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2031 evalue_set_si(&res
, 0, 1);
2032 /* Compute the polynomial using Horner's rule */
2033 for (i
=p
->size
-1;i
>1;i
--) {
2034 eadd(&p
->arr
[i
], &res
);
2037 eadd(&p
->arr
[1], &res
);
2039 free_evalue_refs(e
);
2040 free_evalue_refs(&EP
);
2045 Vector_Free(periods
);
2047 } /* evalue_mod2table */
2049 /********************************************************/
2050 /* function in domain */
2051 /* check if the parameters in list_args */
2052 /* verifies the constraints of Domain P */
2053 /********************************************************/
2054 int in_domain(Polyhedron
*P
, Value
*list_args
) {
2057 Value v
; /* value of the constraint of a row when
2058 parameters are instanciated*/
2064 /*P->Constraint constraint matrice of polyhedron P*/
2065 for(row
=0;row
<P
->NbConstraints
;row
++) {
2066 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2067 for(col
=1;col
<P
->Dimension
+1;col
++) {
2068 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
2069 value_addto(v
,v
,tmp
);
2071 if (value_notzero_p(P
->Constraint
[row
][0])) {
2073 /*if v is not >=0 then this constraint is not respected */
2074 if (value_neg_p(v
)) {
2078 return P
->next
? in_domain(P
->next
, list_args
) : 0;
2083 /*if v is not = 0 then this constraint is not respected */
2084 if (value_notzero_p(v
))
2089 /*if not return before this point => all
2090 the constraints are respected */
2096 /****************************************************/
2097 /* function compute enode */
2098 /* compute the value of enode p with parameters */
2099 /* list "list_args */
2100 /* compute the polynomial or the periodic */
2101 /****************************************************/
2103 static double compute_enode(enode
*p
, Value
*list_args
) {
2115 if (p
->type
== polynomial
) {
2117 value_assign(param
,list_args
[p
->pos
-1]);
2119 /* Compute the polynomial using Horner's rule */
2120 for (i
=p
->size
-1;i
>0;i
--) {
2121 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2122 res
*=VALUE_TO_DOUBLE(param
);
2124 res
+=compute_evalue(&p
->arr
[0],list_args
);
2126 else if (p
->type
== fractional
) {
2127 double d
= compute_evalue(&p
->arr
[0], list_args
);
2128 d
-= floor(d
+1e-10);
2130 /* Compute the polynomial using Horner's rule */
2131 for (i
=p
->size
-1;i
>1;i
--) {
2132 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2135 res
+=compute_evalue(&p
->arr
[1],list_args
);
2137 else if (p
->type
== flooring
) {
2138 double d
= compute_evalue(&p
->arr
[0], list_args
);
2141 /* Compute the polynomial using Horner's rule */
2142 for (i
=p
->size
-1;i
>1;i
--) {
2143 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2146 res
+=compute_evalue(&p
->arr
[1],list_args
);
2148 else if (p
->type
== periodic
) {
2149 value_assign(m
,list_args
[p
->pos
-1]);
2151 /* Choose the right element of the periodic */
2152 value_set_si(param
,p
->size
);
2153 value_pmodulus(m
,m
,param
);
2154 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2156 else if (p
->type
== relation
) {
2157 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2158 res
= compute_evalue(&p
->arr
[1], list_args
);
2159 else if (p
->size
> 2)
2160 res
= compute_evalue(&p
->arr
[2], list_args
);
2162 else if (p
->type
== partition
) {
2163 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2164 Value
*vals
= list_args
;
2167 for (i
= 0; i
< dim
; ++i
) {
2168 value_init(vals
[i
]);
2170 value_assign(vals
[i
], list_args
[i
]);
2173 for (i
= 0; i
< p
->size
/2; ++i
)
2174 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2175 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2179 for (i
= 0; i
< dim
; ++i
)
2180 value_clear(vals
[i
]);
2189 } /* compute_enode */
2191 /*************************************************/
2192 /* return the value of Ehrhart Polynomial */
2193 /* It returns a double, because since it is */
2194 /* a recursive function, some intermediate value */
2195 /* might not be integral */
2196 /*************************************************/
2198 double compute_evalue(evalue
*e
,Value
*list_args
) {
2202 if (value_notzero_p(e
->d
)) {
2203 if (value_notone_p(e
->d
))
2204 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2206 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2209 res
= compute_enode(e
->x
.p
,list_args
);
2211 } /* compute_evalue */
2214 /****************************************************/
2215 /* function compute_poly : */
2216 /* Check for the good validity domain */
2217 /* return the number of point in the Polyhedron */
2218 /* in allocated memory */
2219 /* Using the Ehrhart pseudo-polynomial */
2220 /****************************************************/
2221 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2224 /* double d; int i; */
2226 tmp
= (Value
*) malloc (sizeof(Value
));
2227 assert(tmp
!= NULL
);
2229 value_set_si(*tmp
,0);
2232 return(tmp
); /* no ehrhart polynomial */
2233 if(en
->ValidityDomain
) {
2234 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2235 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2240 return(tmp
); /* no Validity Domain */
2242 if(in_domain(en
->ValidityDomain
,list_args
)) {
2244 #ifdef EVAL_EHRHART_DEBUG
2245 Print_Domain(stdout
,en
->ValidityDomain
);
2246 print_evalue(stdout
,&en
->EP
);
2249 /* d = compute_evalue(&en->EP,list_args);
2251 printf("(double)%lf = %d\n", d, i ); */
2252 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2258 value_set_si(*tmp
,0);
2259 return(tmp
); /* no compatible domain with the arguments */
2260 } /* compute_poly */
2262 size_t value_size(Value v
) {
2263 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2264 * sizeof(v
[0]._mp_d
[0]);
2267 size_t domain_size(Polyhedron
*D
)
2270 size_t s
= sizeof(*D
);
2272 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2273 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2274 s
+= value_size(D
->Constraint
[i
][j
]);
2277 for (i = 0; i < D->NbRays; ++i)
2278 for (j = 0; j < D->Dimension+2; ++j)
2279 s += value_size(D->Ray[i][j]);
2282 return D
->next
? s
+domain_size(D
->next
) : s
;
2285 size_t enode_size(enode
*p
) {
2286 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2289 if (p
->type
== partition
)
2290 for (i
= 0; i
< p
->size
/2; ++i
) {
2291 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2292 s
+= evalue_size(&p
->arr
[2*i
+1]);
2295 for (i
= 0; i
< p
->size
; ++i
) {
2296 s
+= evalue_size(&p
->arr
[i
]);
2301 size_t evalue_size(evalue
*e
)
2303 size_t s
= sizeof(*e
);
2304 s
+= value_size(e
->d
);
2305 if (value_notzero_p(e
->d
))
2306 s
+= value_size(e
->x
.n
);
2308 s
+= enode_size(e
->x
.p
);
2312 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2314 evalue
*found
= NULL
;
2319 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2322 value_init(offset
.d
);
2323 value_init(offset
.x
.n
);
2324 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2325 value_lcm(m
, offset
.d
, &offset
.d
);
2326 value_set_si(offset
.x
.n
, 1);
2329 evalue_copy(©
, cst
);
2332 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2334 if (eequal(base
, &e
->x
.p
->arr
[0]))
2335 found
= &e
->x
.p
->arr
[0];
2337 value_set_si(offset
.x
.n
, -2);
2340 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2342 if (eequal(base
, &e
->x
.p
->arr
[0]))
2345 free_evalue_refs(cst
);
2346 free_evalue_refs(&offset
);
2349 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2350 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2355 static evalue
*find_relation_pair(evalue
*e
)
2358 evalue
*found
= NULL
;
2360 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2363 if (e
->x
.p
->type
== fractional
) {
2368 poly_denom(&e
->x
.p
->arr
[0], &m
);
2370 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2371 cst
= &cst
->x
.p
->arr
[0])
2374 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2375 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2380 i
= e
->x
.p
->type
== relation
;
2381 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2382 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2387 void evalue_mod2relation(evalue
*e
) {
2390 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2393 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2394 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2395 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2396 value_clear(e
->x
.p
->arr
[2*i
].d
);
2397 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2399 if (2*i
< e
->x
.p
->size
) {
2400 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2401 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2406 if (e
->x
.p
->size
== 0) {
2408 evalue_set_si(e
, 0, 1);
2414 while ((d
= find_relation_pair(e
)) != NULL
) {
2418 value_init(split
.d
);
2419 value_set_si(split
.d
, 0);
2420 split
.x
.p
= new_enode(relation
, 3, 0);
2421 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2422 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2424 ev
= &split
.x
.p
->arr
[0];
2425 value_set_si(ev
->d
, 0);
2426 ev
->x
.p
= new_enode(fractional
, 3, -1);
2427 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2428 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2429 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2435 free_evalue_refs(&split
);
2439 static int evalue_comp(const void * a
, const void * b
)
2441 const evalue
*e1
= *(const evalue
**)a
;
2442 const evalue
*e2
= *(const evalue
**)b
;
2443 return ecmp(e1
, e2
);
2446 void evalue_combine(evalue
*e
)
2453 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2456 NALLOC(evs
, e
->x
.p
->size
/2);
2457 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2458 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2459 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2460 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2461 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2462 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2463 value_clear(p
->arr
[2*k
].d
);
2464 value_clear(p
->arr
[2*k
+1].d
);
2465 p
->arr
[2*k
] = *(evs
[i
]-1);
2466 p
->arr
[2*k
+1] = *(evs
[i
]);
2469 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2472 value_clear((evs
[i
]-1)->d
);
2476 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2477 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2478 free_evalue_refs(evs
[i
]);
2482 for (i
= 2*k
; i
< p
->size
; ++i
)
2483 value_clear(p
->arr
[i
].d
);
2490 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2492 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2494 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2497 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2498 Polyhedron
*D
, *N
, **P
;
2501 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2508 if (D
->NbEq
<= H
->NbEq
) {
2514 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2515 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2516 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2517 reduce_evalue(&tmp
);
2518 if (value_notzero_p(tmp
.d
) ||
2519 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2522 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2523 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2526 free_evalue_refs(&tmp
);
2532 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2534 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2536 value_clear(e
->x
.p
->arr
[2*i
].d
);
2537 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2539 if (2*i
< e
->x
.p
->size
) {
2540 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2541 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2548 H
= DomainConvex(D
, 0);
2549 E
= DomainDifference(H
, D
, 0);
2551 D
= DomainDifference(H
, E
, 0);
2554 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2558 /* May change coefficients to become non-standard if fiddle is set
2559 * => reduce p afterwards to correct
2561 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2562 Matrix
**R
, int fiddle
)
2566 unsigned dim
= D
->Dimension
;
2567 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2572 assert(p
->type
== fractional
);
2574 value_set_si(T
->p
[1][dim
], 1);
2576 while (value_zero_p(pp
->d
)) {
2577 assert(pp
->x
.p
->type
== polynomial
);
2578 assert(pp
->x
.p
->size
== 2);
2579 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2580 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2581 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2582 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2583 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2584 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2585 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2586 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2587 pp
= &pp
->x
.p
->arr
[0];
2589 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2590 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2591 I
= DomainImage(D
, T
, 0);
2592 H
= DomainConvex(I
, 0);
2601 int reduce_in_domain(evalue
*e
, Polyhedron
*D
)
2611 if (value_notzero_p(e
->d
))
2616 if (p
->type
== relation
) {
2622 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2623 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2624 equal
= value_eq(min
, max
);
2625 mpz_cdiv_q(min
, min
, d
);
2626 mpz_fdiv_q(max
, max
, d
);
2628 if (bounded
&& value_gt(min
, max
)) {
2634 evalue_set_si(e
, 0, 1);
2637 free_evalue_refs(&(p
->arr
[1]));
2638 free_evalue_refs(&(p
->arr
[0]));
2644 return r
? r
: reduce_in_domain(e
, D
);
2645 } else if (bounded
&& equal
) {
2648 free_evalue_refs(&(p
->arr
[2]));
2651 free_evalue_refs(&(p
->arr
[0]));
2657 return reduce_in_domain(e
, D
);
2658 } else if (bounded
&& value_eq(min
, max
)) {
2659 /* zero for a single value */
2661 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2662 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2663 value_multiply(min
, min
, d
);
2664 value_subtract(M
->p
[0][D
->Dimension
+1],
2665 M
->p
[0][D
->Dimension
+1], min
);
2666 E
= DomainAddConstraints(D
, M
, 0);
2672 r
= reduce_in_domain(&p
->arr
[1], E
);
2674 r
|= reduce_in_domain(&p
->arr
[2], D
);
2676 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2684 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2687 i
= p
->type
== relation
? 1 :
2688 p
->type
== fractional
? 1 : 0;
2689 for (; i
<p
->size
; i
++)
2690 r
|= reduce_in_domain(&p
->arr
[i
], D
);
2692 if (p
->type
!= fractional
) {
2693 if (r
&& p
->type
== polynomial
) {
2696 value_set_si(f
.d
, 0);
2697 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2698 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2699 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2700 reorder_terms(p
, &f
);
2711 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2713 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2714 mpz_fdiv_q(min
, min
, d
);
2715 mpz_fdiv_q(max
, max
, d
);
2716 value_subtract(d
, max
, min
);
2718 if (bounded
&& value_eq(min
, max
)) {
2721 value_init(inc
.x
.n
);
2722 value_set_si(inc
.d
, 1);
2723 value_oppose(inc
.x
.n
, min
);
2724 eadd(&inc
, &p
->arr
[0]);
2725 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2729 free_evalue_refs(&inc
);
2731 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2738 value_set_si(rem
.d
, 0);
2739 rem
.x
.p
= new_enode(fractional
, 3, -1);
2740 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2741 value_clear(rem
.x
.p
->arr
[1].d
);
2742 value_clear(rem
.x
.p
->arr
[2].d
);
2743 rem
.x
.p
->arr
[1] = p
->arr
[1];
2744 rem
.x
.p
->arr
[2] = p
->arr
[2];
2745 for (i
= 3; i
< p
->size
; ++i
)
2746 p
->arr
[i
-2] = p
->arr
[i
];
2750 value_init(inc
.x
.n
);
2751 value_set_si(inc
.d
, 1);
2752 value_oppose(inc
.x
.n
, min
);
2755 evalue_copy(&t
, &p
->arr
[0]);
2759 value_set_si(f
.d
, 0);
2760 f
.x
.p
= new_enode(fractional
, 3, -1);
2761 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2762 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2763 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2765 value_init(factor
.d
);
2766 evalue_set_si(&factor
, -1, 1);
2772 value_clear(f
.x
.p
->arr
[1].x
.n
);
2773 value_clear(f
.x
.p
->arr
[2].x
.n
);
2774 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2775 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2781 free_evalue_refs(&inc
);
2782 free_evalue_refs(&t
);
2783 free_evalue_refs(&f
);
2784 free_evalue_refs(&factor
);
2785 free_evalue_refs(&rem
);
2787 reduce_in_domain(e
, D
);
2791 _reduce_evalue(&p
->arr
[0], 0, 1);
2795 value_set_si(f
.d
, 0);
2796 f
.x
.p
= new_enode(fractional
, 3, -1);
2797 value_clear(f
.x
.p
->arr
[0].d
);
2798 f
.x
.p
->arr
[0] = p
->arr
[0];
2799 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2800 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2801 reorder_terms(p
, &f
);
2815 void evalue_range_reduction(evalue
*e
)
2818 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2821 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2822 if (reduce_in_domain(&e
->x
.p
->arr
[2*i
+1],
2823 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2824 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2826 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2827 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2828 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2829 value_clear(e
->x
.p
->arr
[2*i
].d
);
2831 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2832 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2840 Enumeration
* partition2enumeration(evalue
*EP
)
2843 Enumeration
*en
, *res
= NULL
;
2845 if (EVALUE_IS_ZERO(*EP
)) {
2850 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2851 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
2852 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2855 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2856 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2857 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2865 static int frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2875 if (value_notzero_p(e
->d
))
2880 i
= p
->type
== relation
? 1 :
2881 p
->type
== fractional
? 1 : 0;
2882 for (; i
<p
->size
; i
++)
2883 r
|= frac2floor_in_domain(&p
->arr
[i
], D
);
2885 if (p
->type
!= fractional
) {
2886 if (r
&& p
->type
== polynomial
) {
2889 value_set_si(f
.d
, 0);
2890 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2891 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2892 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2893 reorder_terms(p
, &f
);
2902 I
= polynomial_projection(p
, D
, &d
, &T
, 0);
2905 Polyhedron_Print(stderr, P_VALUE_FMT, I);
2908 assert(I
->NbEq
== 0); /* Should have been reduced */
2911 for (i
= 0; i
< I
->NbConstraints
; ++i
)
2912 if (value_pos_p(I
->Constraint
[i
][1]))
2915 assert(i
< I
->NbConstraints
);
2917 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
2918 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
2919 if (value_neg_p(min
)) {
2921 mpz_fdiv_q(min
, min
, d
);
2922 value_init(offset
.d
);
2923 value_set_si(offset
.d
, 1);
2924 value_init(offset
.x
.n
);
2925 value_oppose(offset
.x
.n
, min
);
2926 eadd(&offset
, &p
->arr
[0]);
2927 free_evalue_refs(&offset
);
2936 value_set_si(fl
.d
, 0);
2937 fl
.x
.p
= new_enode(flooring
, 3, -1);
2938 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2939 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2940 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2942 eadd(&fl
, &p
->arr
[0]);
2943 reorder_terms(p
, &p
->arr
[0]);
2946 free_evalue_refs(&fl
);
2951 void evalue_frac2floor(evalue
*e
)
2954 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2957 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2958 if (frac2floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
2959 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])))
2960 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2963 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2968 int nparam
= D
->Dimension
- nvar
;
2971 nr
= D
->NbConstraints
+ 2;
2972 nc
= D
->Dimension
+ 2 + 1;
2973 C
= Matrix_Alloc(nr
, nc
);
2974 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2975 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
2976 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2977 D
->Dimension
+ 1 - nvar
);
2982 nc
= C
->NbColumns
+ 1;
2983 C
= Matrix_Alloc(nr
, nc
);
2984 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
2985 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
2986 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2987 oldC
->NbColumns
- 1 - nvar
);
2990 value_set_si(C
->p
[nr
-2][0], 1);
2991 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
2992 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
2994 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
2995 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
3001 static void floor2frac_r(evalue
*e
, int nvar
)
3008 if (value_notzero_p(e
->d
))
3013 assert(p
->type
== flooring
);
3014 for (i
= 1; i
< p
->size
; i
++)
3015 floor2frac_r(&p
->arr
[i
], nvar
);
3017 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3018 assert(pp
->x
.p
->type
== polynomial
);
3019 pp
->x
.p
->pos
-= nvar
;
3023 value_set_si(f
.d
, 0);
3024 f
.x
.p
= new_enode(fractional
, 3, -1);
3025 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3026 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3027 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3029 eadd(&f
, &p
->arr
[0]);
3030 reorder_terms(p
, &p
->arr
[0]);
3033 free_evalue_refs(&f
);
3036 /* Convert flooring back to fractional and shift position
3037 * of the parameters by nvar
3039 static void floor2frac(evalue
*e
, int nvar
)
3041 floor2frac_r(e
, nvar
);
3045 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
3048 int nparam
= D
->Dimension
- nvar
;
3052 D
= Constraints2Polyhedron(C
, 0);
3056 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3058 /* Double check that D was not unbounded. */
3059 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3067 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3074 evalue
*factor
= NULL
;
3077 if (EVALUE_IS_ZERO(*e
))
3081 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
3088 res
= esum_over_domain(e
, nvar
, Q
, C
);
3091 for (Q
= DD
; Q
; Q
= DD
) {
3097 t
= esum_over_domain(e
, nvar
, Q
, C
);
3104 free_evalue_refs(t
);
3111 if (value_notzero_p(e
->d
)) {
3114 t
= esum_over_domain_cst(nvar
, D
, C
);
3116 if (!EVALUE_IS_ONE(*e
))
3122 switch (e
->x
.p
->type
) {
3124 evalue
*pp
= &e
->x
.p
->arr
[0];
3126 if (pp
->x
.p
->pos
> nvar
) {
3127 /* remainder is independent of the summated vars */
3133 floor2frac(&f
, nvar
);
3135 t
= esum_over_domain_cst(nvar
, D
, C
);
3139 free_evalue_refs(&f
);
3144 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3145 poly_denom(pp
, &row
->p
[1 + nvar
]);
3146 value_set_si(row
->p
[0], 1);
3147 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3148 pp
= &pp
->x
.p
->arr
[0]) {
3150 assert(pp
->x
.p
->type
== polynomial
);
3152 if (pos
>= 1 + nvar
)
3154 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3155 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3156 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3158 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3159 value_division(row
->p
[1 + D
->Dimension
+ 1],
3160 row
->p
[1 + D
->Dimension
+ 1],
3162 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3163 row
->p
[1 + D
->Dimension
+ 1],
3165 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3169 int pos
= e
->x
.p
->pos
;
3172 factor
= ALLOC(evalue
);
3173 value_init(factor
->d
);
3174 value_set_si(factor
->d
, 0);
3175 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3176 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3177 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3181 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3182 for (i
= 0; i
< D
->NbRays
; ++i
)
3183 if (value_notzero_p(D
->Ray
[i
][pos
]))
3185 assert(i
< D
->NbRays
);
3186 if (value_neg_p(D
->Ray
[i
][pos
])) {
3187 factor
= ALLOC(evalue
);
3188 value_init(factor
->d
);
3189 evalue_set_si(factor
, -1, 1);
3191 value_set_si(row
->p
[0], 1);
3192 value_set_si(row
->p
[pos
], 1);
3193 value_set_si(row
->p
[1 + nvar
], -1);
3200 i
= type_offset(e
->x
.p
);
3202 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3207 evalue_copy(&cum
, factor
);
3211 for (; i
< e
->x
.p
->size
; ++i
) {
3215 C
= esum_add_constraint(nvar
, D
, C
, row
);
3221 Vector_Print(stderr, P_VALUE_FMT, row);
3223 Matrix_Print(stderr, P_VALUE_FMT, C);
3225 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3234 free_evalue_refs(t
);
3237 if (factor
&& i
+1 < e
->x
.p
->size
)
3244 free_evalue_refs(factor
);
3245 free_evalue_refs(&cum
);
3257 evalue
*esum(evalue
*e
, int nvar
)
3260 evalue
*res
= ALLOC(evalue
);
3264 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3265 evalue_copy(res
, e
);
3269 evalue_set_si(res
, 0, 1);
3271 assert(value_zero_p(e
->d
));
3272 assert(e
->x
.p
->type
== partition
);
3274 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3276 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3277 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3279 free_evalue_refs(t
);
3288 /* Initial silly implementation */
3289 void eor(evalue
*e1
, evalue
*res
)
3295 evalue_set_si(&mone
, -1, 1);
3297 evalue_copy(&E
, res
);
3303 free_evalue_refs(&E
);
3304 free_evalue_refs(&mone
);