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)))
15 #define ALLOC(p) p = (typeof(p))malloc(sizeof(*p))
16 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
18 #define ALLOC(p) p = (void *)malloc(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
);
34 void aep_evalue(evalue
*e
, int *ref
) {
39 if (value_notzero_p(e
->d
))
40 return; /* a rational number, its already reduced */
42 return; /* hum... an overflow probably occured */
44 /* First check the components of p */
45 for (i
=0;i
<p
->size
;i
++)
46 aep_evalue(&p
->arr
[i
],ref
);
53 p
->pos
= ref
[p
->pos
-1]+1;
59 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
65 if (value_notzero_p(e
->d
))
66 return; /* a rational number, its already reduced */
68 return; /* hum... an overflow probably occured */
71 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
72 for(i
=0;i
<CT
->NbRows
-1;i
++)
73 for(j
=0;j
<CT
->NbColumns
;j
++)
74 if(value_notzero_p(CT
->p
[i
][j
])) {
79 /* Transform the references in e, using ref */
83 } /* addeliminatedparams_evalue */
85 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
86 unsigned MaxRays
, unsigned nparam
)
91 if (CT
->NbRows
== CT
->NbColumns
)
94 if (EVALUE_IS_ZERO(*e
))
97 if (value_notzero_p(e
->d
)) {
100 value_set_si(res
.d
, 0);
101 res
.x
.p
= new_enode(partition
, 2, nparam
);
102 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
103 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
104 value_clear(res
.x
.p
->arr
[1].d
);
105 res
.x
.p
->arr
[1] = *e
;
112 assert(p
->type
== partition
);
115 for (i
=0; i
<p
->size
/2; i
++) {
116 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
117 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
120 T
= DomainIntersection(D
, CEq
, MaxRays
);
122 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
123 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
127 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
135 assert(value_notzero_p(e1
->d
));
136 assert(value_notzero_p(e2
->d
));
137 value_multiply(m
, e1
->x
.n
, e2
->d
);
138 value_multiply(m2
, e2
->x
.n
, e1
->d
);
141 else if (value_gt(m
, m2
))
151 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
153 if (value_notzero_p(e1
->d
)) {
155 if (value_zero_p(e2
->d
))
157 r
= mod_rational_smaller(e1
, e2
);
158 return r
== -1 ? 0 : r
;
160 if (value_notzero_p(e2
->d
))
162 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
164 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
167 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
169 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
174 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
176 assert(value_zero_p(e1
->d
));
177 assert(value_zero_p(e2
->d
));
178 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
179 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
180 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
183 /* Negative pos means inequality */
184 /* s is negative of substitution if m is not zero */
193 struct fixed_param
*fixed
;
198 static int relations_depth(evalue
*e
)
203 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
204 e
= &e
->x
.p
->arr
[1], ++d
);
208 static void poly_denom_not_constant(evalue
**pp
, Value
*d
)
213 while (value_zero_p(p
->d
)) {
214 assert(p
->x
.p
->type
== polynomial
);
215 assert(p
->x
.p
->size
== 2);
216 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
217 value_lcm(*d
, p
->x
.p
->arr
[1].d
, d
);
223 static void poly_denom(evalue
*p
, Value
*d
)
225 poly_denom_not_constant(&p
, d
);
226 value_lcm(*d
, p
->d
, d
);
229 static void realloc_substitution(struct subst
*s
, int d
)
231 struct fixed_param
*n
;
234 for (i
= 0; i
< s
->n
; ++i
)
241 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
247 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
250 /* May have been reduced already */
251 if (value_notzero_p(m
->d
))
254 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
255 assert(m
->x
.p
->size
== 3);
257 /* fractional was inverted during reduction
258 * invert it back and move constant in
260 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
261 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
262 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
263 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
264 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
265 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
266 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
267 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
268 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
269 value_set_si(m
->x
.p
->arr
[1].d
, 1);
272 /* Oops. Nested identical relations. */
273 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
276 if (s
->n
>= s
->max
) {
277 int d
= relations_depth(r
);
278 realloc_substitution(s
, d
);
282 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
283 assert(p
->x
.p
->size
== 2);
286 assert(value_pos_p(f
->x
.n
));
288 value_init(s
->fixed
[s
->n
].m
);
289 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
290 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
291 value_init(s
->fixed
[s
->n
].d
);
292 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
293 value_init(s
->fixed
[s
->n
].s
.d
);
294 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
300 static int type_offset(enode
*p
)
302 return p
->type
== fractional
? 1 :
303 p
->type
== flooring
? 1 : 0;
306 static void reorder_terms(enode
*p
, evalue
*v
)
309 int offset
= type_offset(p
);
311 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
313 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
314 free_evalue_refs(&(p
->arr
[i
]));
320 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
326 if (value_notzero_p(e
->d
)) {
328 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
329 return; /* a rational number, its already reduced */
333 return; /* hum... an overflow probably occured */
335 /* First reduce the components of p */
336 add
= p
->type
== relation
;
337 for (i
=0; i
<p
->size
; i
++) {
339 add
= add_modulo_substitution(s
, e
);
341 if (i
== 0 && p
->type
==fractional
)
342 _reduce_evalue(&p
->arr
[i
], s
, 1);
344 _reduce_evalue(&p
->arr
[i
], s
, fract
);
346 if (add
&& i
== p
->size
-1) {
348 value_clear(s
->fixed
[s
->n
].m
);
349 value_clear(s
->fixed
[s
->n
].d
);
350 free_evalue_refs(&s
->fixed
[s
->n
].s
);
351 } else if (add
&& i
== 1)
352 s
->fixed
[s
->n
-1].pos
*= -1;
355 if (p
->type
==periodic
) {
357 /* Try to reduce the period */
358 for (i
=1; i
<=(p
->size
)/2; i
++) {
359 if ((p
->size
% i
)==0) {
361 /* Can we reduce the size to i ? */
363 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
364 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
367 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
371 you_lose
: /* OK, lets not do it */
376 /* Try to reduce its strength */
379 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
383 else if (p
->type
==polynomial
) {
384 for (k
= 0; s
&& k
< s
->n
; ++k
) {
385 if (s
->fixed
[k
].pos
== p
->pos
) {
386 int divide
= value_notone_p(s
->fixed
[k
].d
);
389 if (value_notzero_p(s
->fixed
[k
].m
)) {
392 assert(p
->size
== 2);
393 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
395 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
402 value_assign(d
.d
, s
->fixed
[k
].d
);
404 if (value_notzero_p(s
->fixed
[k
].m
))
405 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
407 value_set_si(d
.x
.n
, 1);
410 for (i
=p
->size
-1;i
>=1;i
--) {
411 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
413 emul(&d
, &p
->arr
[i
]);
414 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
415 free_evalue_refs(&(p
->arr
[i
]));
418 _reduce_evalue(&p
->arr
[0], s
, fract
);
421 free_evalue_refs(&d
);
427 /* Try to reduce the degree */
428 for (i
=p
->size
-1;i
>=1;i
--) {
429 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
431 /* Zero coefficient */
432 free_evalue_refs(&(p
->arr
[i
]));
437 /* Try to reduce its strength */
440 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
444 else if (p
->type
==fractional
) {
448 if (value_notzero_p(p
->arr
[0].d
)) {
450 value_assign(v
.d
, p
->arr
[0].d
);
452 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
457 evalue
*pp
= &p
->arr
[0];
458 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
459 assert(pp
->x
.p
->size
== 2);
461 /* search for exact duplicate among the modulo inequalities */
463 f
= &pp
->x
.p
->arr
[1];
464 for (k
= 0; s
&& k
< s
->n
; ++k
) {
465 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
466 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
467 value_eq(s
->fixed
[k
].m
, f
->d
) &&
468 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
475 /* replace { E/m } by { (E-1)/m } + 1/m */
480 evalue_set_si(&extra
, 1, 1);
481 value_assign(extra
.d
, g
);
482 eadd(&extra
, &v
.x
.p
->arr
[1]);
483 free_evalue_refs(&extra
);
485 /* We've been going in circles; stop now */
486 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
487 free_evalue_refs(&v
);
489 evalue_set_si(&v
, 0, 1);
494 value_set_si(v
.d
, 0);
495 v
.x
.p
= new_enode(fractional
, 3, -1);
496 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
497 value_assign(v
.x
.p
->arr
[1].d
, g
);
498 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
499 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
502 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
505 value_division(f
->d
, g
, f
->d
);
506 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
507 value_assign(f
->d
, g
);
508 value_decrement(f
->x
.n
, f
->x
.n
);
509 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
511 Gcd(f
->d
, f
->x
.n
, &g
);
512 value_division(f
->d
, f
->d
, g
);
513 value_division(f
->x
.n
, f
->x
.n
, g
);
522 /* reduction may have made this fractional arg smaller */
523 i
= reorder
? p
->size
: 1;
524 for ( ; i
< p
->size
; ++i
)
525 if (value_zero_p(p
->arr
[i
].d
) &&
526 p
->arr
[i
].x
.p
->type
== fractional
&&
527 !mod_term_smaller(e
, &p
->arr
[i
]))
531 value_set_si(v
.d
, 0);
532 v
.x
.p
= new_enode(fractional
, 3, -1);
533 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
534 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
535 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
543 evalue
*pp
= &p
->arr
[0];
546 poly_denom_not_constant(&pp
, &m
);
547 mpz_fdiv_r(r
, m
, pp
->d
);
548 if (value_notzero_p(r
)) {
550 value_set_si(v
.d
, 0);
551 v
.x
.p
= new_enode(fractional
, 3, -1);
553 value_multiply(r
, m
, pp
->x
.n
);
554 value_multiply(v
.x
.p
->arr
[1].d
, m
, pp
->d
);
555 value_init(v
.x
.p
->arr
[1].x
.n
);
556 mpz_fdiv_r(v
.x
.p
->arr
[1].x
.n
, r
, pp
->d
);
557 mpz_fdiv_q(r
, r
, pp
->d
);
559 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
560 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
562 while (value_zero_p(pp
->d
))
563 pp
= &pp
->x
.p
->arr
[0];
565 value_assign(pp
->d
, m
);
566 value_assign(pp
->x
.n
, r
);
568 Gcd(pp
->d
, pp
->x
.n
, &r
);
569 value_division(pp
->d
, pp
->d
, r
);
570 value_division(pp
->x
.n
, pp
->x
.n
, r
);
583 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
584 pp
= &pp
->x
.p
->arr
[0]) {
585 f
= &pp
->x
.p
->arr
[1];
586 assert(value_pos_p(f
->d
));
587 mpz_mul_ui(twice
, f
->x
.n
, 2);
588 if (value_lt(twice
, f
->d
))
590 if (value_eq(twice
, f
->d
))
598 value_set_si(v
.d
, 0);
599 v
.x
.p
= new_enode(fractional
, 3, -1);
600 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
601 poly_denom(&p
->arr
[0], &twice
);
602 value_assign(v
.x
.p
->arr
[1].d
, twice
);
603 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
604 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
605 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
607 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
608 pp
= &pp
->x
.p
->arr
[0]) {
609 f
= &pp
->x
.p
->arr
[1];
610 value_oppose(f
->x
.n
, f
->x
.n
);
611 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
613 value_division(pp
->d
, twice
, pp
->d
);
614 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
615 value_assign(pp
->d
, twice
);
616 value_oppose(pp
->x
.n
, pp
->x
.n
);
617 value_decrement(pp
->x
.n
, pp
->x
.n
);
618 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
620 /* Maybe we should do this during reduction of
623 Gcd(pp
->d
, pp
->x
.n
, &twice
);
624 value_division(pp
->d
, pp
->d
, twice
);
625 value_division(pp
->x
.n
, pp
->x
.n
, twice
);
635 reorder_terms(p
, &v
);
636 _reduce_evalue(&p
->arr
[1], s
, fract
);
639 /* Try to reduce the degree */
640 for (i
=p
->size
-1;i
>=2;i
--) {
641 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
643 /* Zero coefficient */
644 free_evalue_refs(&(p
->arr
[i
]));
649 /* Try to reduce its strength */
652 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
653 free_evalue_refs(&(p
->arr
[0]));
657 else if (p
->type
== flooring
) {
658 /* Try to reduce the degree */
659 for (i
=p
->size
-1;i
>=2;i
--) {
660 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
662 /* Zero coefficient */
663 free_evalue_refs(&(p
->arr
[i
]));
668 /* Try to reduce its strength */
671 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
672 free_evalue_refs(&(p
->arr
[0]));
676 else if (p
->type
== relation
) {
677 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
678 free_evalue_refs(&(p
->arr
[2]));
679 free_evalue_refs(&(p
->arr
[0]));
686 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
687 free_evalue_refs(&(p
->arr
[2]));
690 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
691 free_evalue_refs(&(p
->arr
[1]));
692 free_evalue_refs(&(p
->arr
[0]));
693 evalue_set_si(e
, 0, 1);
700 /* Relation was reduced by means of an identical
701 * inequality => remove
703 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
706 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
707 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
709 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
711 free_evalue_refs(&(p
->arr
[2]));
715 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
717 evalue_set_si(e
, 0, 1);
718 free_evalue_refs(&(p
->arr
[1]));
720 free_evalue_refs(&(p
->arr
[0]));
726 } /* reduce_evalue */
728 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
733 for (k
= 0; k
< dim
; ++k
)
734 if (value_notzero_p(row
[k
+1]))
737 Vector_Normalize_Positive(row
+1, dim
+1, k
);
738 assert(s
->n
< s
->max
);
739 value_init(s
->fixed
[s
->n
].d
);
740 value_init(s
->fixed
[s
->n
].m
);
741 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
742 s
->fixed
[s
->n
].pos
= k
+1;
743 value_set_si(s
->fixed
[s
->n
].m
, 0);
744 r
= &s
->fixed
[s
->n
].s
;
746 for (l
= k
+1; l
< dim
; ++l
)
747 if (value_notzero_p(row
[l
+1])) {
748 value_set_si(r
->d
, 0);
749 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
750 value_init(r
->x
.p
->arr
[1].x
.n
);
751 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
752 value_set_si(r
->x
.p
->arr
[1].d
, 1);
756 value_oppose(r
->x
.n
, row
[dim
+1]);
757 value_set_si(r
->d
, 1);
761 void reduce_evalue (evalue
*e
) {
762 struct subst s
= { NULL
, 0, 0 };
764 if (value_notzero_p(e
->d
))
765 return; /* a rational number, its already reduced */
767 if (e
->x
.p
->type
== partition
) {
770 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
771 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
773 /* This shouldn't really happen;
774 * Empty domains should not be added.
776 POL_ENSURE_VERTICES(D
);
782 D
= DomainConvex(D
, 0);
783 if (!D
->next
&& D
->NbEq
) {
787 realloc_substitution(&s
, dim
);
789 int d
= relations_depth(&e
->x
.p
->arr
[2*i
+1]);
791 NALLOC(s
.fixed
, s
.max
);
794 for (j
= 0; j
< D
->NbEq
; ++j
)
795 add_substitution(&s
, D
->Constraint
[j
], dim
);
797 if (D
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
799 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
800 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
802 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
803 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
804 value_clear(e
->x
.p
->arr
[2*i
].d
);
806 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
807 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
812 for (j
= 0; j
< s
.n
; ++j
) {
813 value_clear(s
.fixed
[j
].d
);
814 value_clear(s
.fixed
[j
].m
);
815 free_evalue_refs(&s
.fixed
[j
].s
);
819 if (e
->x
.p
->size
== 0) {
821 evalue_set_si(e
, 0, 1);
824 _reduce_evalue(e
, &s
, 0);
829 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
831 if(value_notzero_p(e
->d
)) {
832 if(value_notone_p(e
->d
)) {
833 value_print(DST
,VALUE_FMT
,e
->x
.n
);
835 value_print(DST
,VALUE_FMT
,e
->d
);
838 value_print(DST
,VALUE_FMT
,e
->x
.n
);
842 print_enode(DST
,e
->x
.p
,pname
);
846 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
851 fprintf(DST
, "NULL");
857 for (i
=0; i
<p
->size
; i
++) {
858 print_evalue(DST
, &p
->arr
[i
], pname
);
862 fprintf(DST
, " }\n");
866 for (i
=p
->size
-1; i
>=0; i
--) {
867 print_evalue(DST
, &p
->arr
[i
], pname
);
868 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
870 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
872 fprintf(DST
, " )\n");
876 for (i
=0; i
<p
->size
; i
++) {
877 print_evalue(DST
, &p
->arr
[i
], pname
);
878 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
880 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
885 for (i
=p
->size
-1; i
>=1; i
--) {
886 print_evalue(DST
, &p
->arr
[i
], pname
);
889 fprintf(DST
, p
->type
== flooring
? "[" : "{");
890 print_evalue(DST
, &p
->arr
[0], pname
);
891 fprintf(DST
, p
->type
== flooring
? "]" : "}");
893 fprintf(DST
, "^%d + ", i
-1);
898 fprintf(DST
, " )\n");
902 print_evalue(DST
, &p
->arr
[0], pname
);
903 fprintf(DST
, "= 0 ] * \n");
904 print_evalue(DST
, &p
->arr
[1], pname
);
906 fprintf(DST
, " +\n [ ");
907 print_evalue(DST
, &p
->arr
[0], pname
);
908 fprintf(DST
, "!= 0 ] * \n");
909 print_evalue(DST
, &p
->arr
[2], pname
);
913 char **names
= pname
;
914 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
915 if (!pname
|| p
->pos
< maxdim
) {
916 NALLOC(names
, maxdim
);
917 for (i
= 0; i
< p
->pos
; ++i
) {
921 NALLOC(names
[i
], 10);
922 snprintf(names
[i
], 10, "%c", 'P'+i
);
925 for ( ; i
< maxdim
; ++i
) {
926 NALLOC(names
[i
], 10);
927 snprintf(names
[i
], 10, "_p%d", i
);
931 for (i
=0; i
<p
->size
/2; i
++) {
932 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
933 print_evalue(DST
, &p
->arr
[2*i
+1], names
);
936 if (!pname
|| p
->pos
< maxdim
) {
937 for (i
= pname
? p
->pos
: 0; i
< maxdim
; ++i
)
950 static void eadd_rev(evalue
*e1
, evalue
*res
)
954 evalue_copy(&ev
, e1
);
956 free_evalue_refs(res
);
960 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
964 evalue_copy(&ev
, e1
);
965 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
966 free_evalue_refs(res
);
970 static int is_zero_on(evalue
*e
, Polyhedron
*D
)
975 tmp
.x
.p
= new_enode(partition
, 2, D
->Dimension
);
976 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Domain_Copy(D
));
977 evalue_copy(&tmp
.x
.p
->arr
[1], e
);
979 is_zero
= EVALUE_IS_ZERO(tmp
);
980 free_evalue_refs(&tmp
);
984 struct section
{ Polyhedron
* D
; evalue E
; };
986 void eadd_partitions (evalue
*e1
,evalue
*res
)
991 s
= (struct section
*)
992 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
993 sizeof(struct section
));
995 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
996 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
997 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1000 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1001 assert(res
->x
.p
->size
>= 2);
1002 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1003 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
1005 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
1007 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1016 /* See if we can extend one of the domains in res to cover fd */
1017 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1018 if (is_zero_on(&res
->x
.p
->arr
[2*i
+1], fd
))
1020 if (i
< res
->x
.p
->size
/2) {
1021 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
1022 DomainConcat(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
])));
1025 value_init(s
[n
].E
.d
);
1026 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
1030 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1031 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
1032 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1034 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1035 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1041 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1042 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1044 value_init(s
[n
].E
.d
);
1045 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1046 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1047 if (!emptyQ(fd
) && is_zero_on(&e1
->x
.p
->arr
[2*j
+1], fd
)) {
1048 d
= DomainConcat(fd
, d
);
1049 fd
= Empty_Polyhedron(fd
->Dimension
);
1055 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1059 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1062 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1063 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1064 value_clear(res
->x
.p
->arr
[2*i
].d
);
1069 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1070 for (j
= 0; j
< n
; ++j
) {
1071 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1072 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1073 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1074 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1080 static void explicit_complement(evalue
*res
)
1082 enode
*rel
= new_enode(relation
, 3, 0);
1084 value_clear(rel
->arr
[0].d
);
1085 rel
->arr
[0] = res
->x
.p
->arr
[0];
1086 value_clear(rel
->arr
[1].d
);
1087 rel
->arr
[1] = res
->x
.p
->arr
[1];
1088 value_set_si(rel
->arr
[2].d
, 1);
1089 value_init(rel
->arr
[2].x
.n
);
1090 value_set_si(rel
->arr
[2].x
.n
, 0);
1095 void eadd(evalue
*e1
,evalue
*res
) {
1098 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1099 /* Add two rational numbers */
1105 value_multiply(m1
,e1
->x
.n
,res
->d
);
1106 value_multiply(m2
,res
->x
.n
,e1
->d
);
1107 value_addto(res
->x
.n
,m1
,m2
);
1108 value_multiply(res
->d
,e1
->d
,res
->d
);
1109 Gcd(res
->x
.n
,res
->d
,&g
);
1110 if (value_notone_p(g
)) {
1111 value_division(res
->d
,res
->d
,g
);
1112 value_division(res
->x
.n
,res
->x
.n
,g
);
1114 value_clear(g
); value_clear(m1
); value_clear(m2
);
1117 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1118 switch (res
->x
.p
->type
) {
1120 /* Add the constant to the constant term of a polynomial*/
1121 eadd(e1
, &res
->x
.p
->arr
[0]);
1124 /* Add the constant to all elements of a periodic number */
1125 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1126 eadd(e1
, &res
->x
.p
->arr
[i
]);
1130 fprintf(stderr
, "eadd: cannot add const with vector\n");
1134 eadd(e1
, &res
->x
.p
->arr
[1]);
1137 assert(EVALUE_IS_ZERO(*e1
));
1138 break; /* Do nothing */
1140 /* Create (zero) complement if needed */
1141 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1142 explicit_complement(res
);
1143 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1144 eadd(e1
, &res
->x
.p
->arr
[i
]);
1150 /* add polynomial or periodic to constant
1151 * you have to exchange e1 and res, before doing addition */
1153 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1157 else { // ((e1->d==0) && (res->d==0))
1158 assert(!((e1
->x
.p
->type
== partition
) ^
1159 (res
->x
.p
->type
== partition
)));
1160 if (e1
->x
.p
->type
== partition
) {
1161 eadd_partitions(e1
, res
);
1164 if (e1
->x
.p
->type
== relation
&&
1165 (res
->x
.p
->type
!= relation
||
1166 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1170 if (res
->x
.p
->type
== relation
) {
1171 if (e1
->x
.p
->type
== relation
&&
1172 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1173 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1174 explicit_complement(res
);
1175 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1176 explicit_complement(e1
);
1177 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1178 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1181 if (res
->x
.p
->size
< 3)
1182 explicit_complement(res
);
1183 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1184 eadd(e1
, &res
->x
.p
->arr
[i
]);
1187 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1188 /* adding to evalues of different type. two cases are possible
1189 * res is periodic and e1 is polynomial, you have to exchange
1190 * e1 and res then to add e1 to the constant term of res */
1191 if (e1
->x
.p
->type
== polynomial
) {
1192 eadd_rev_cst(e1
, res
);
1194 else if (res
->x
.p
->type
== polynomial
) {
1195 /* res is polynomial and e1 is periodic,
1196 add e1 to the constant term of res */
1198 eadd(e1
,&res
->x
.p
->arr
[0]);
1204 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1205 ((res
->x
.p
->type
== fractional
||
1206 res
->x
.p
->type
== flooring
) &&
1207 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1208 /* adding evalues of different position (i.e function of different unknowns
1209 * to case are possible */
1211 switch (res
->x
.p
->type
) {
1214 if(mod_term_smaller(res
, e1
))
1215 eadd(e1
,&res
->x
.p
->arr
[1]);
1217 eadd_rev_cst(e1
, res
);
1219 case polynomial
: // res and e1 are polynomials
1220 // add e1 to the constant term of res
1222 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1223 eadd(e1
,&res
->x
.p
->arr
[0]);
1225 eadd_rev_cst(e1
, res
);
1226 // value_clear(g); value_clear(m1); value_clear(m2);
1228 case periodic
: // res and e1 are pointers to periodic numbers
1229 //add e1 to all elements of res
1231 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1232 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1233 eadd(e1
,&res
->x
.p
->arr
[i
]);
1244 //same type , same pos and same size
1245 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1246 // add any element in e1 to the corresponding element in res
1247 i
= type_offset(res
->x
.p
);
1249 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1250 for (; i
<res
->x
.p
->size
; i
++) {
1251 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1256 /* Sizes are different */
1257 switch(res
->x
.p
->type
) {
1261 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1262 /* new enode and add res to that new node. If you do not do */
1263 /* that, you lose the the upper weight part of e1 ! */
1265 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1268 i
= type_offset(res
->x
.p
);
1270 assert(eequal(&e1
->x
.p
->arr
[0],
1271 &res
->x
.p
->arr
[0]));
1272 for (; i
<e1
->x
.p
->size
; i
++) {
1273 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1280 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1283 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1284 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1285 to add periodicaly elements of e1 to elements of ne, and finaly to
1290 value_init(ex
); value_init(ey
);value_init(ep
);
1293 value_set_si(ex
,e1
->x
.p
->size
);
1294 value_set_si(ey
,res
->x
.p
->size
);
1295 value_assign (ep
,*Lcm(ex
,ey
));
1296 p
=(int)mpz_get_si(ep
);
1297 ne
= (evalue
*) malloc (sizeof(evalue
));
1299 value_set_si( ne
->d
,0);
1301 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1303 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1306 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1309 value_assign(res
->d
, ne
->d
);
1315 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1324 static void emul_rev (evalue
*e1
, evalue
*res
)
1328 evalue_copy(&ev
, e1
);
1330 free_evalue_refs(res
);
1334 static void emul_poly (evalue
*e1
, evalue
*res
)
1336 int i
, j
, o
= type_offset(res
->x
.p
);
1338 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1340 value_set_si(tmp
.d
,0);
1341 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1343 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1344 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1345 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1346 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1349 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1350 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1351 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1354 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1355 emul(&res
->x
.p
->arr
[i
], &ev
);
1356 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1357 free_evalue_refs(&ev
);
1359 free_evalue_refs(res
);
1363 void emul_partitions (evalue
*e1
,evalue
*res
)
1368 s
= (struct section
*)
1369 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1370 sizeof(struct section
));
1372 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1373 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1374 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1377 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1378 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1379 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1380 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1386 /* This code is only needed because the partitions
1387 are not true partitions.
1389 for (k
= 0; k
< n
; ++k
) {
1390 if (DomainIncludes(s
[k
].D
, d
))
1392 if (DomainIncludes(d
, s
[k
].D
)) {
1393 Domain_Free(s
[k
].D
);
1394 free_evalue_refs(&s
[k
].E
);
1405 value_init(s
[n
].E
.d
);
1406 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1407 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1411 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1412 value_clear(res
->x
.p
->arr
[2*i
].d
);
1413 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1418 evalue_set_si(res
, 0, 1);
1420 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1421 for (j
= 0; j
< n
; ++j
) {
1422 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1423 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1424 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1425 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1432 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1434 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1435 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1436 * evalues is not treated here */
1438 void emul (evalue
*e1
, evalue
*res
){
1441 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1442 fprintf(stderr
, "emul: do not proced on evector type !\n");
1446 if (EVALUE_IS_ZERO(*res
))
1449 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1450 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1451 emul_partitions(e1
, res
);
1454 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1455 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1456 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1458 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1459 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1460 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1461 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1462 explicit_complement(res
);
1463 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1464 explicit_complement(e1
);
1465 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1466 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1469 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1470 emul(e1
, &res
->x
.p
->arr
[i
]);
1472 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1473 switch(e1
->x
.p
->type
) {
1475 switch(res
->x
.p
->type
) {
1477 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1478 /* Product of two polynomials of the same variable */
1483 /* Product of two polynomials of different variables */
1485 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1486 for( i
=0; i
<res
->x
.p
->size
; i
++)
1487 emul(e1
, &res
->x
.p
->arr
[i
]);
1496 /* Product of a polynomial and a periodic or fractional */
1503 switch(res
->x
.p
->type
) {
1505 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1506 /* Product of two periodics of the same parameter and period */
1508 for(i
=0; i
<res
->x
.p
->size
;i
++)
1509 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1514 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1515 /* Product of two periodics of the same parameter and different periods */
1519 value_init(x
); value_init(y
);value_init(z
);
1522 value_set_si(x
,e1
->x
.p
->size
);
1523 value_set_si(y
,res
->x
.p
->size
);
1524 value_assign (z
,*Lcm(x
,y
));
1525 lcm
=(int)mpz_get_si(z
);
1526 newp
= (evalue
*) malloc (sizeof(evalue
));
1527 value_init(newp
->d
);
1528 value_set_si( newp
->d
,0);
1529 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1530 for(i
=0;i
<lcm
;i
++) {
1531 evalue_copy(&newp
->x
.p
->arr
[i
],
1532 &res
->x
.p
->arr
[i
%iy
]);
1535 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1537 value_assign(res
->d
,newp
->d
);
1540 value_clear(x
); value_clear(y
);value_clear(z
);
1544 /* Product of two periodics of different parameters */
1546 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1547 for(i
=0; i
<res
->x
.p
->size
; i
++)
1548 emul(e1
, &(res
->x
.p
->arr
[i
]));
1556 /* Product of a periodic and a polynomial */
1558 for(i
=0; i
<res
->x
.p
->size
; i
++)
1559 emul(e1
, &(res
->x
.p
->arr
[i
]));
1566 switch(res
->x
.p
->type
) {
1568 for(i
=0; i
<res
->x
.p
->size
; i
++)
1569 emul(e1
, &(res
->x
.p
->arr
[i
]));
1576 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1577 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1578 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1581 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1582 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1587 value_set_si(d
.x
.n
, 1);
1588 /* { x }^2 == { x }/2 */
1589 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1590 assert(e1
->x
.p
->size
== 3);
1591 assert(res
->x
.p
->size
== 3);
1593 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1595 eadd(&res
->x
.p
->arr
[1], &tmp
);
1596 emul(&e1
->x
.p
->arr
[2], &tmp
);
1597 emul(&e1
->x
.p
->arr
[1], res
);
1598 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1599 free_evalue_refs(&tmp
);
1604 if(mod_term_smaller(res
, e1
))
1605 for(i
=1; i
<res
->x
.p
->size
; i
++)
1606 emul(e1
, &(res
->x
.p
->arr
[i
]));
1621 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1622 /* Product of two rational numbers */
1626 value_multiply(res
->d
,e1
->d
,res
->d
);
1627 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1628 Gcd(res
->x
.n
, res
->d
,&g
);
1629 if (value_notone_p(g
)) {
1630 value_division(res
->d
,res
->d
,g
);
1631 value_division(res
->x
.n
,res
->x
.n
,g
);
1637 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1638 /* Product of an expression (polynomial or peririodic) and a rational number */
1644 /* Product of a rationel number and an expression (polynomial or peririodic) */
1646 i
= type_offset(res
->x
.p
);
1647 for (; i
<res
->x
.p
->size
; i
++)
1648 emul(e1
, &res
->x
.p
->arr
[i
]);
1658 /* Frees mask content ! */
1659 void emask(evalue
*mask
, evalue
*res
) {
1666 if (EVALUE_IS_ZERO(*res
)) {
1667 free_evalue_refs(mask
);
1671 assert(value_zero_p(mask
->d
));
1672 assert(mask
->x
.p
->type
== partition
);
1673 assert(value_zero_p(res
->d
));
1674 assert(res
->x
.p
->type
== partition
);
1675 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1676 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1677 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1678 pos
= res
->x
.p
->pos
;
1680 s
= (struct section
*)
1681 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1682 sizeof(struct section
));
1686 evalue_set_si(&mone
, -1, 1);
1689 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1690 assert(mask
->x
.p
->size
>= 2);
1691 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1692 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1694 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1696 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1705 value_init(s
[n
].E
.d
);
1706 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1710 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1711 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1714 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1715 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1716 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1717 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1719 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1720 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1726 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1727 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1729 value_init(s
[n
].E
.d
);
1730 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1731 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1737 /* Just ignore; this may have been previously masked off */
1739 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1743 free_evalue_refs(&mone
);
1744 free_evalue_refs(mask
);
1745 free_evalue_refs(res
);
1748 evalue_set_si(res
, 0, 1);
1750 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1751 for (j
= 0; j
< n
; ++j
) {
1752 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1753 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1754 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1761 void evalue_copy(evalue
*dst
, evalue
*src
)
1763 value_assign(dst
->d
, src
->d
);
1764 if(value_notzero_p(src
->d
)) {
1765 value_init(dst
->x
.n
);
1766 value_assign(dst
->x
.n
, src
->x
.n
);
1768 dst
->x
.p
= ecopy(src
->x
.p
);
1771 enode
*new_enode(enode_type type
,int size
,int pos
) {
1777 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1780 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1784 for(i
=0; i
<size
; i
++) {
1785 value_init(res
->arr
[i
].d
);
1786 value_set_si(res
->arr
[i
].d
,0);
1787 res
->arr
[i
].x
.p
= 0;
1792 enode
*ecopy(enode
*e
) {
1797 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1798 for(i
=0;i
<e
->size
;++i
) {
1799 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1800 if(value_zero_p(res
->arr
[i
].d
))
1801 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1802 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1803 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1805 value_init(res
->arr
[i
].x
.n
);
1806 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1812 int ecmp(const evalue
*e1
, const evalue
*e2
)
1818 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1822 value_multiply(m
, e1
->x
.n
, e2
->d
);
1823 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1825 if (value_lt(m
, m2
))
1827 else if (value_gt(m
, m2
))
1837 if (value_notzero_p(e1
->d
))
1839 if (value_notzero_p(e2
->d
))
1845 if (p1
->type
!= p2
->type
)
1846 return p1
->type
- p2
->type
;
1847 if (p1
->pos
!= p2
->pos
)
1848 return p1
->pos
- p2
->pos
;
1849 if (p1
->size
!= p2
->size
)
1850 return p1
->size
- p2
->size
;
1852 for (i
= p1
->size
-1; i
>= 0; --i
)
1853 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1859 int eequal(evalue
*e1
,evalue
*e2
) {
1864 if (value_ne(e1
->d
,e2
->d
))
1867 /* e1->d == e2->d */
1868 if (value_notzero_p(e1
->d
)) {
1869 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1872 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1876 /* e1->d == e2->d == 0 */
1879 if (p1
->type
!= p2
->type
) return 0;
1880 if (p1
->size
!= p2
->size
) return 0;
1881 if (p1
->pos
!= p2
->pos
) return 0;
1882 for (i
=0; i
<p1
->size
; i
++)
1883 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1888 void free_evalue_refs(evalue
*e
) {
1893 if (EVALUE_IS_DOMAIN(*e
)) {
1894 Domain_Free(EVALUE_DOMAIN(*e
));
1897 } else if (value_pos_p(e
->d
)) {
1899 /* 'e' stores a constant */
1901 value_clear(e
->x
.n
);
1904 assert(value_zero_p(e
->d
));
1907 if (!p
) return; /* null pointer */
1908 for (i
=0; i
<p
->size
; i
++) {
1909 free_evalue_refs(&(p
->arr
[i
]));
1913 } /* free_evalue_refs */
1915 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1916 Vector
* val
, evalue
*res
)
1918 unsigned nparam
= periods
->Size
;
1921 double d
= compute_evalue(e
, val
->p
);
1922 d
*= VALUE_TO_DOUBLE(m
);
1927 value_assign(res
->d
, m
);
1928 value_init(res
->x
.n
);
1929 value_set_double(res
->x
.n
, d
);
1930 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1933 if (value_one_p(periods
->p
[p
]))
1934 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1939 value_assign(tmp
, periods
->p
[p
]);
1940 value_set_si(res
->d
, 0);
1941 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1943 value_decrement(tmp
, tmp
);
1944 value_assign(val
->p
[p
], tmp
);
1945 mod2table_r(e
, periods
, m
, p
+1, val
,
1946 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1947 } while (value_pos_p(tmp
));
1953 static void rel2table(evalue
*e
, int zero
)
1955 if (value_pos_p(e
->d
)) {
1956 if (value_zero_p(e
->x
.n
) == zero
)
1957 value_set_si(e
->x
.n
, 1);
1959 value_set_si(e
->x
.n
, 0);
1960 value_set_si(e
->d
, 1);
1963 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1964 rel2table(&e
->x
.p
->arr
[i
], zero
);
1968 void evalue_mod2table(evalue
*e
, int nparam
)
1973 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1976 for (i
=0; i
<p
->size
; i
++) {
1977 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1979 if (p
->type
== relation
) {
1984 evalue_copy(©
, &p
->arr
[0]);
1986 rel2table(&p
->arr
[0], 1);
1987 emul(&p
->arr
[0], &p
->arr
[1]);
1989 rel2table(©
, 0);
1990 emul(©
, &p
->arr
[2]);
1991 eadd(&p
->arr
[2], &p
->arr
[1]);
1992 free_evalue_refs(&p
->arr
[2]);
1993 free_evalue_refs(©
);
1995 free_evalue_refs(&p
->arr
[0]);
1999 } else if (p
->type
== fractional
) {
2000 Vector
*periods
= Vector_Alloc(nparam
);
2001 Vector
*val
= Vector_Alloc(nparam
);
2007 value_set_si(tmp
, 1);
2008 Vector_Set(periods
->p
, 1, nparam
);
2009 Vector_Set(val
->p
, 0, nparam
);
2010 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2013 assert(p
->type
== polynomial
);
2014 assert(p
->size
== 2);
2015 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2016 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
2018 value_lcm(tmp
, ev
->d
, &tmp
);
2020 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2023 evalue_set_si(&res
, 0, 1);
2024 /* Compute the polynomial using Horner's rule */
2025 for (i
=p
->size
-1;i
>1;i
--) {
2026 eadd(&p
->arr
[i
], &res
);
2029 eadd(&p
->arr
[1], &res
);
2031 free_evalue_refs(e
);
2032 free_evalue_refs(&EP
);
2037 Vector_Free(periods
);
2039 } /* evalue_mod2table */
2041 /********************************************************/
2042 /* function in domain */
2043 /* check if the parameters in list_args */
2044 /* verifies the constraints of Domain P */
2045 /********************************************************/
2046 int in_domain(Polyhedron
*P
, Value
*list_args
) {
2049 Value v
; /* value of the constraint of a row when
2050 parameters are instanciated*/
2056 /*P->Constraint constraint matrice of polyhedron P*/
2057 for(row
=0;row
<P
->NbConstraints
;row
++) {
2058 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2059 for(col
=1;col
<P
->Dimension
+1;col
++) {
2060 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
2061 value_addto(v
,v
,tmp
);
2063 if (value_notzero_p(P
->Constraint
[row
][0])) {
2065 /*if v is not >=0 then this constraint is not respected */
2066 if (value_neg_p(v
)) {
2070 return P
->next
? in_domain(P
->next
, list_args
) : 0;
2075 /*if v is not = 0 then this constraint is not respected */
2076 if (value_notzero_p(v
))
2081 /*if not return before this point => all
2082 the constraints are respected */
2088 /****************************************************/
2089 /* function compute enode */
2090 /* compute the value of enode p with parameters */
2091 /* list "list_args */
2092 /* compute the polynomial or the periodic */
2093 /****************************************************/
2095 static double compute_enode(enode
*p
, Value
*list_args
) {
2107 if (p
->type
== polynomial
) {
2109 value_assign(param
,list_args
[p
->pos
-1]);
2111 /* Compute the polynomial using Horner's rule */
2112 for (i
=p
->size
-1;i
>0;i
--) {
2113 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2114 res
*=VALUE_TO_DOUBLE(param
);
2116 res
+=compute_evalue(&p
->arr
[0],list_args
);
2118 else if (p
->type
== fractional
) {
2119 double d
= compute_evalue(&p
->arr
[0], list_args
);
2120 d
-= floor(d
+1e-10);
2122 /* Compute the polynomial using Horner's rule */
2123 for (i
=p
->size
-1;i
>1;i
--) {
2124 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2127 res
+=compute_evalue(&p
->arr
[1],list_args
);
2129 else if (p
->type
== flooring
) {
2130 double d
= compute_evalue(&p
->arr
[0], list_args
);
2133 /* Compute the polynomial using Horner's rule */
2134 for (i
=p
->size
-1;i
>1;i
--) {
2135 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2138 res
+=compute_evalue(&p
->arr
[1],list_args
);
2140 else if (p
->type
== periodic
) {
2141 value_assign(m
,list_args
[p
->pos
-1]);
2143 /* Choose the right element of the periodic */
2144 value_set_si(param
,p
->size
);
2145 value_pmodulus(m
,m
,param
);
2146 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2148 else if (p
->type
== relation
) {
2149 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2150 res
= compute_evalue(&p
->arr
[1], list_args
);
2151 else if (p
->size
> 2)
2152 res
= compute_evalue(&p
->arr
[2], list_args
);
2154 else if (p
->type
== partition
) {
2155 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2156 Value
*vals
= list_args
;
2159 for (i
= 0; i
< dim
; ++i
) {
2160 value_init(vals
[i
]);
2162 value_assign(vals
[i
], list_args
[i
]);
2165 for (i
= 0; i
< p
->size
/2; ++i
)
2166 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2167 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2171 for (i
= 0; i
< dim
; ++i
)
2172 value_clear(vals
[i
]);
2181 } /* compute_enode */
2183 /*************************************************/
2184 /* return the value of Ehrhart Polynomial */
2185 /* It returns a double, because since it is */
2186 /* a recursive function, some intermediate value */
2187 /* might not be integral */
2188 /*************************************************/
2190 double compute_evalue(evalue
*e
,Value
*list_args
) {
2194 if (value_notzero_p(e
->d
)) {
2195 if (value_notone_p(e
->d
))
2196 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2198 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2201 res
= compute_enode(e
->x
.p
,list_args
);
2203 } /* compute_evalue */
2206 /****************************************************/
2207 /* function compute_poly : */
2208 /* Check for the good validity domain */
2209 /* return the number of point in the Polyhedron */
2210 /* in allocated memory */
2211 /* Using the Ehrhart pseudo-polynomial */
2212 /****************************************************/
2213 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2216 /* double d; int i; */
2218 tmp
= (Value
*) malloc (sizeof(Value
));
2219 assert(tmp
!= NULL
);
2221 value_set_si(*tmp
,0);
2224 return(tmp
); /* no ehrhart polynomial */
2225 if(en
->ValidityDomain
) {
2226 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2227 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2232 return(tmp
); /* no Validity Domain */
2234 if(in_domain(en
->ValidityDomain
,list_args
)) {
2236 #ifdef EVAL_EHRHART_DEBUG
2237 Print_Domain(stdout
,en
->ValidityDomain
);
2238 print_evalue(stdout
,&en
->EP
);
2241 /* d = compute_evalue(&en->EP,list_args);
2243 printf("(double)%lf = %d\n", d, i ); */
2244 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2250 value_set_si(*tmp
,0);
2251 return(tmp
); /* no compatible domain with the arguments */
2252 } /* compute_poly */
2254 size_t value_size(Value v
) {
2255 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2256 * sizeof(v
[0]._mp_d
[0]);
2259 size_t domain_size(Polyhedron
*D
)
2262 size_t s
= sizeof(*D
);
2264 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2265 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2266 s
+= value_size(D
->Constraint
[i
][j
]);
2269 for (i = 0; i < D->NbRays; ++i)
2270 for (j = 0; j < D->Dimension+2; ++j)
2271 s += value_size(D->Ray[i][j]);
2274 return D
->next
? s
+domain_size(D
->next
) : s
;
2277 size_t enode_size(enode
*p
) {
2278 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2281 if (p
->type
== partition
)
2282 for (i
= 0; i
< p
->size
/2; ++i
) {
2283 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2284 s
+= evalue_size(&p
->arr
[2*i
+1]);
2287 for (i
= 0; i
< p
->size
; ++i
) {
2288 s
+= evalue_size(&p
->arr
[i
]);
2293 size_t evalue_size(evalue
*e
)
2295 size_t s
= sizeof(*e
);
2296 s
+= value_size(e
->d
);
2297 if (value_notzero_p(e
->d
))
2298 s
+= value_size(e
->x
.n
);
2300 s
+= enode_size(e
->x
.p
);
2304 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2306 evalue
*found
= NULL
;
2311 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2314 value_init(offset
.d
);
2315 value_init(offset
.x
.n
);
2316 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2317 value_lcm(m
, offset
.d
, &offset
.d
);
2318 value_set_si(offset
.x
.n
, 1);
2321 evalue_copy(©
, cst
);
2324 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2326 if (eequal(base
, &e
->x
.p
->arr
[0]))
2327 found
= &e
->x
.p
->arr
[0];
2329 value_set_si(offset
.x
.n
, -2);
2332 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2334 if (eequal(base
, &e
->x
.p
->arr
[0]))
2337 free_evalue_refs(cst
);
2338 free_evalue_refs(&offset
);
2341 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2342 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2347 static evalue
*find_relation_pair(evalue
*e
)
2350 evalue
*found
= NULL
;
2352 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2355 if (e
->x
.p
->type
== fractional
) {
2360 poly_denom(&e
->x
.p
->arr
[0], &m
);
2362 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2363 cst
= &cst
->x
.p
->arr
[0])
2366 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2367 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2372 i
= e
->x
.p
->type
== relation
;
2373 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2374 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2379 void evalue_mod2relation(evalue
*e
) {
2382 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2385 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2386 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2387 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2388 value_clear(e
->x
.p
->arr
[2*i
].d
);
2389 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2391 if (2*i
< e
->x
.p
->size
) {
2392 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2393 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2398 if (e
->x
.p
->size
== 0) {
2400 evalue_set_si(e
, 0, 1);
2406 while ((d
= find_relation_pair(e
)) != NULL
) {
2410 value_init(split
.d
);
2411 value_set_si(split
.d
, 0);
2412 split
.x
.p
= new_enode(relation
, 3, 0);
2413 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2414 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2416 ev
= &split
.x
.p
->arr
[0];
2417 value_set_si(ev
->d
, 0);
2418 ev
->x
.p
= new_enode(fractional
, 3, -1);
2419 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2420 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2421 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2427 free_evalue_refs(&split
);
2431 static int evalue_comp(const void * a
, const void * b
)
2433 const evalue
*e1
= *(const evalue
**)a
;
2434 const evalue
*e2
= *(const evalue
**)b
;
2435 return ecmp(e1
, e2
);
2438 void evalue_combine(evalue
*e
)
2445 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2448 NALLOC(evs
, e
->x
.p
->size
/2);
2449 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2450 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2451 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2452 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2453 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2454 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2455 value_clear(p
->arr
[2*k
].d
);
2456 value_clear(p
->arr
[2*k
+1].d
);
2457 p
->arr
[2*k
] = *(evs
[i
]-1);
2458 p
->arr
[2*k
+1] = *(evs
[i
]);
2461 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2464 value_clear((evs
[i
]-1)->d
);
2468 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2469 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2470 free_evalue_refs(evs
[i
]);
2474 for (i
= 2*k
; i
< p
->size
; ++i
)
2475 value_clear(p
->arr
[i
].d
);
2482 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2484 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2486 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2489 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2490 Polyhedron
*D
, *N
, **P
;
2493 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2500 if (D
->NbEq
<= H
->NbEq
) {
2506 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2507 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2508 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2509 reduce_evalue(&tmp
);
2510 if (value_notzero_p(tmp
.d
) ||
2511 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2514 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2515 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2518 free_evalue_refs(&tmp
);
2524 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2526 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2528 value_clear(e
->x
.p
->arr
[2*i
].d
);
2529 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2531 if (2*i
< e
->x
.p
->size
) {
2532 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2533 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2540 H
= DomainConvex(D
, 0);
2541 E
= DomainDifference(H
, D
, 0);
2543 D
= DomainDifference(H
, E
, 0);
2546 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2550 /* May change coefficients to become non-standard if fiddle is set
2551 * => reduce p afterwards to correct
2553 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2554 Matrix
**R
, int fiddle
)
2558 unsigned dim
= D
->Dimension
;
2559 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2564 assert(p
->type
== fractional
);
2566 value_set_si(T
->p
[1][dim
], 1);
2568 while (value_zero_p(pp
->d
)) {
2569 assert(pp
->x
.p
->type
== polynomial
);
2570 assert(pp
->x
.p
->size
== 2);
2571 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2572 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2573 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2574 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2575 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2576 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2577 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2578 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2579 pp
= &pp
->x
.p
->arr
[0];
2581 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2582 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2583 I
= DomainImage(D
, T
, 0);
2584 H
= DomainConvex(I
, 0);
2593 int reduce_in_domain(evalue
*e
, Polyhedron
*D
)
2603 if (value_notzero_p(e
->d
))
2608 if (p
->type
== relation
) {
2614 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2615 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2616 equal
= value_eq(min
, max
);
2617 mpz_cdiv_q(min
, min
, d
);
2618 mpz_fdiv_q(max
, max
, d
);
2620 if (bounded
&& value_gt(min
, max
)) {
2626 evalue_set_si(e
, 0, 1);
2629 free_evalue_refs(&(p
->arr
[1]));
2630 free_evalue_refs(&(p
->arr
[0]));
2636 return r
? r
: reduce_in_domain(e
, D
);
2637 } else if (bounded
&& equal
) {
2640 free_evalue_refs(&(p
->arr
[2]));
2643 free_evalue_refs(&(p
->arr
[0]));
2649 return reduce_in_domain(e
, D
);
2650 } else if (bounded
&& value_eq(min
, max
)) {
2651 /* zero for a single value */
2653 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2654 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2655 value_multiply(min
, min
, d
);
2656 value_subtract(M
->p
[0][D
->Dimension
+1],
2657 M
->p
[0][D
->Dimension
+1], min
);
2658 E
= DomainAddConstraints(D
, M
, 0);
2664 r
= reduce_in_domain(&p
->arr
[1], E
);
2666 r
|= reduce_in_domain(&p
->arr
[2], D
);
2668 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2676 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2679 i
= p
->type
== relation
? 1 :
2680 p
->type
== fractional
? 1 : 0;
2681 for (; i
<p
->size
; i
++)
2682 r
|= reduce_in_domain(&p
->arr
[i
], D
);
2684 if (p
->type
!= fractional
) {
2685 if (r
&& p
->type
== polynomial
) {
2688 value_set_si(f
.d
, 0);
2689 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2690 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2691 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2692 reorder_terms(p
, &f
);
2703 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2705 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2706 mpz_fdiv_q(min
, min
, d
);
2707 mpz_fdiv_q(max
, max
, d
);
2708 value_subtract(d
, max
, min
);
2710 if (bounded
&& value_eq(min
, max
)) {
2713 value_init(inc
.x
.n
);
2714 value_set_si(inc
.d
, 1);
2715 value_oppose(inc
.x
.n
, min
);
2716 eadd(&inc
, &p
->arr
[0]);
2717 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2721 free_evalue_refs(&inc
);
2723 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2730 value_set_si(rem
.d
, 0);
2731 rem
.x
.p
= new_enode(fractional
, 3, -1);
2732 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2733 rem
.x
.p
->arr
[1] = p
->arr
[1];
2734 rem
.x
.p
->arr
[2] = p
->arr
[2];
2735 for (i
= 3; i
< p
->size
; ++i
)
2736 p
->arr
[i
-2] = p
->arr
[i
];
2740 value_init(inc
.x
.n
);
2741 value_set_si(inc
.d
, 1);
2742 value_oppose(inc
.x
.n
, min
);
2745 evalue_copy(&t
, &p
->arr
[0]);
2749 value_set_si(f
.d
, 0);
2750 f
.x
.p
= new_enode(fractional
, 3, -1);
2751 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2752 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2753 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2755 value_init(factor
.d
);
2756 evalue_set_si(&factor
, -1, 1);
2762 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2763 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2769 free_evalue_refs(&inc
);
2770 free_evalue_refs(&t
);
2771 free_evalue_refs(&f
);
2772 free_evalue_refs(&factor
);
2773 free_evalue_refs(&rem
);
2775 reduce_in_domain(e
, D
);
2779 _reduce_evalue(&p
->arr
[0], 0, 1);
2783 value_set_si(f
.d
, 0);
2784 f
.x
.p
= new_enode(fractional
, 3, -1);
2785 value_clear(f
.x
.p
->arr
[0].d
);
2786 f
.x
.p
->arr
[0] = p
->arr
[0];
2787 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2788 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2789 reorder_terms(p
, &f
);
2803 void evalue_range_reduction(evalue
*e
)
2806 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2809 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2810 if (reduce_in_domain(&e
->x
.p
->arr
[2*i
+1],
2811 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2812 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2814 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2815 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2816 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2817 value_clear(e
->x
.p
->arr
[2*i
].d
);
2819 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2820 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2828 Enumeration
* partition2enumeration(evalue
*EP
)
2831 Enumeration
*en
, *res
= NULL
;
2833 if (EVALUE_IS_ZERO(*EP
)) {
2838 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2839 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
2840 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2843 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2844 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2845 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2853 static int frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2863 if (value_notzero_p(e
->d
))
2868 i
= p
->type
== relation
? 1 :
2869 p
->type
== fractional
? 1 : 0;
2870 for (; i
<p
->size
; i
++)
2871 r
|= frac2floor_in_domain(&p
->arr
[i
], D
);
2873 if (p
->type
!= fractional
) {
2874 if (r
&& p
->type
== polynomial
) {
2877 value_set_si(f
.d
, 0);
2878 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2879 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2880 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2881 reorder_terms(p
, &f
);
2890 I
= polynomial_projection(p
, D
, &d
, &T
, 0);
2893 Polyhedron_Print(stderr, P_VALUE_FMT, I);
2896 assert(I
->NbEq
== 0); /* Should have been reduced */
2899 for (i
= 0; i
< I
->NbConstraints
; ++i
)
2900 if (value_pos_p(I
->Constraint
[i
][1]))
2903 assert(i
< I
->NbConstraints
);
2905 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
2906 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
2907 if (value_neg_p(min
)) {
2909 mpz_fdiv_q(min
, min
, d
);
2910 value_init(offset
.d
);
2911 value_set_si(offset
.d
, 1);
2912 value_init(offset
.x
.n
);
2913 value_oppose(offset
.x
.n
, min
);
2914 eadd(&offset
, &p
->arr
[0]);
2915 free_evalue_refs(&offset
);
2924 value_set_si(fl
.d
, 0);
2925 fl
.x
.p
= new_enode(flooring
, 3, -1);
2926 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2927 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2928 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2930 eadd(&fl
, &p
->arr
[0]);
2931 reorder_terms(p
, &p
->arr
[0]);
2934 free_evalue_refs(&fl
);
2939 void evalue_frac2floor(evalue
*e
)
2942 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2945 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2946 if (frac2floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
2947 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])))
2948 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2951 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2956 int nparam
= D
->Dimension
- nvar
;
2959 nr
= D
->NbConstraints
+ 2;
2960 nc
= D
->Dimension
+ 2 + 1;
2961 C
= Matrix_Alloc(nr
, nc
);
2962 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2963 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
2964 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2965 D
->Dimension
+ 1 - nvar
);
2970 nc
= C
->NbColumns
+ 1;
2971 C
= Matrix_Alloc(nr
, nc
);
2972 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
2973 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
2974 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2975 oldC
->NbColumns
- 1 - nvar
);
2978 value_set_si(C
->p
[nr
-2][0], 1);
2979 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
2980 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
2982 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
2983 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
2989 static void floor2frac_r(evalue
*e
, int nvar
)
2996 if (value_notzero_p(e
->d
))
3001 assert(p
->type
== flooring
);
3002 for (i
= 1; i
< p
->size
; i
++)
3003 floor2frac_r(&p
->arr
[i
], nvar
);
3005 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3006 assert(pp
->x
.p
->type
== polynomial
);
3007 pp
->x
.p
->pos
-= nvar
;
3011 value_set_si(f
.d
, 0);
3012 f
.x
.p
= new_enode(fractional
, 3, -1);
3013 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3014 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3015 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3017 eadd(&f
, &p
->arr
[0]);
3018 reorder_terms(p
, &p
->arr
[0]);
3021 free_evalue_refs(&f
);
3024 /* Convert flooring back to fractional and shift position
3025 * of the parameters by nvar
3027 static void floor2frac(evalue
*e
, int nvar
)
3029 floor2frac_r(e
, nvar
);
3033 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
3036 int nparam
= D
->Dimension
- nvar
;
3040 D
= Constraints2Polyhedron(C
, 0);
3044 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3046 /* Double check that D was not unbounded. */
3047 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3055 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3062 evalue
*factor
= NULL
;
3065 if (EVALUE_IS_ZERO(*e
))
3069 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
3076 res
= esum_over_domain(e
, nvar
, Q
, C
);
3079 for (Q
= DD
; Q
; Q
= DD
) {
3085 t
= esum_over_domain(e
, nvar
, Q
, C
);
3092 free_evalue_refs(t
);
3099 if (value_notzero_p(e
->d
)) {
3102 t
= esum_over_domain_cst(nvar
, D
, C
);
3104 if (!EVALUE_IS_ONE(*e
))
3110 switch (e
->x
.p
->type
) {
3112 evalue
*pp
= &e
->x
.p
->arr
[0];
3114 if (pp
->x
.p
->pos
> nvar
) {
3115 /* remainder is independent of the summated vars */
3121 floor2frac(&f
, nvar
);
3123 t
= esum_over_domain_cst(nvar
, D
, C
);
3127 free_evalue_refs(&f
);
3132 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3133 poly_denom(pp
, &row
->p
[1 + nvar
]);
3134 value_set_si(row
->p
[0], 1);
3135 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3136 pp
= &pp
->x
.p
->arr
[0]) {
3138 assert(pp
->x
.p
->type
== polynomial
);
3140 if (pos
>= 1 + nvar
)
3142 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3143 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3144 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3146 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3147 value_division(row
->p
[1 + D
->Dimension
+ 1],
3148 row
->p
[1 + D
->Dimension
+ 1],
3150 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3151 row
->p
[1 + D
->Dimension
+ 1],
3153 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3157 int pos
= e
->x
.p
->pos
;
3161 value_init(factor
->d
);
3162 value_set_si(factor
->d
, 0);
3163 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3164 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3165 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3169 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3170 for (i
= 0; i
< D
->NbRays
; ++i
)
3171 if (value_notzero_p(D
->Ray
[i
][pos
]))
3173 assert(i
< D
->NbRays
);
3174 if (value_neg_p(D
->Ray
[i
][pos
])) {
3176 value_init(factor
->d
);
3177 evalue_set_si(factor
, -1, 1);
3179 value_set_si(row
->p
[0], 1);
3180 value_set_si(row
->p
[pos
], 1);
3181 value_set_si(row
->p
[1 + nvar
], -1);
3188 i
= type_offset(e
->x
.p
);
3190 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3195 evalue_copy(&cum
, factor
);
3199 for (; i
< e
->x
.p
->size
; ++i
) {
3203 C
= esum_add_constraint(nvar
, D
, C
, row
);
3209 Vector_Print(stderr, P_VALUE_FMT, row);
3211 Matrix_Print(stderr, P_VALUE_FMT, C);
3213 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3222 free_evalue_refs(t
);
3225 if (factor
&& i
+1 < e
->x
.p
->size
)
3232 free_evalue_refs(factor
);
3233 free_evalue_refs(&cum
);
3245 evalue
*esum(evalue
*e
, int nvar
)
3253 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3254 evalue_copy(res
, e
);
3258 evalue_set_si(res
, 0, 1);
3260 assert(value_zero_p(e
->d
));
3261 assert(e
->x
.p
->type
== partition
);
3263 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3265 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3266 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3268 free_evalue_refs(t
);
3277 /* Initial silly implementation */
3278 void eor(evalue
*e1
, evalue
*res
)
3284 evalue_set_si(&mone
, -1, 1);
3286 evalue_copy(&E
, res
);
3292 free_evalue_refs(&E
);
3293 free_evalue_refs(&mone
);