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(const evalue
*e1
, const 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 static void _reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
, struct subst
*s
)
772 Polyhedron
*orig
= D
;
777 D
= DomainConvex(D
, 0);
778 if (!D
->next
&& D
->NbEq
) {
782 realloc_substitution(s
, dim
);
784 int d
= relations_depth(e
);
786 NALLOC(s
->fixed
, s
->max
);
789 for (j
= 0; j
< D
->NbEq
; ++j
)
790 add_substitution(s
, D
->Constraint
[j
], dim
);
794 _reduce_evalue(e
, s
, 0);
797 for (j
= 0; j
< s
->n
; ++j
) {
798 value_clear(s
->fixed
[j
].d
);
799 value_clear(s
->fixed
[j
].m
);
800 free_evalue_refs(&s
->fixed
[j
].s
);
805 void reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
)
807 struct subst s
= { NULL
, 0, 0 };
809 if (EVALUE_IS_ZERO(*e
))
813 evalue_set_si(e
, 0, 1);
816 _reduce_evalue_in_domain(e
, D
, &s
);
821 void reduce_evalue (evalue
*e
) {
822 struct subst s
= { NULL
, 0, 0 };
824 if (value_notzero_p(e
->d
))
825 return; /* a rational number, its already reduced */
827 if (e
->x
.p
->type
== partition
) {
830 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
831 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
833 /* This shouldn't really happen;
834 * Empty domains should not be added.
836 POL_ENSURE_VERTICES(D
);
838 _reduce_evalue_in_domain(&e
->x
.p
->arr
[2*i
+1], D
, &s
);
840 if (emptyQ(D
) || EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
841 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
842 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
843 value_clear(e
->x
.p
->arr
[2*i
].d
);
845 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
846 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
850 if (e
->x
.p
->size
== 0) {
852 evalue_set_si(e
, 0, 1);
855 _reduce_evalue(e
, &s
, 0);
860 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
862 if(value_notzero_p(e
->d
)) {
863 if(value_notone_p(e
->d
)) {
864 value_print(DST
,VALUE_FMT
,e
->x
.n
);
866 value_print(DST
,VALUE_FMT
,e
->d
);
869 value_print(DST
,VALUE_FMT
,e
->x
.n
);
873 print_enode(DST
,e
->x
.p
,pname
);
877 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
882 fprintf(DST
, "NULL");
888 for (i
=0; i
<p
->size
; i
++) {
889 print_evalue(DST
, &p
->arr
[i
], pname
);
893 fprintf(DST
, " }\n");
897 for (i
=p
->size
-1; i
>=0; i
--) {
898 print_evalue(DST
, &p
->arr
[i
], pname
);
899 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
901 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
903 fprintf(DST
, " )\n");
907 for (i
=0; i
<p
->size
; i
++) {
908 print_evalue(DST
, &p
->arr
[i
], pname
);
909 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
911 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
916 for (i
=p
->size
-1; i
>=1; i
--) {
917 print_evalue(DST
, &p
->arr
[i
], pname
);
920 fprintf(DST
, p
->type
== flooring
? "[" : "{");
921 print_evalue(DST
, &p
->arr
[0], pname
);
922 fprintf(DST
, p
->type
== flooring
? "]" : "}");
924 fprintf(DST
, "^%d + ", i
-1);
929 fprintf(DST
, " )\n");
933 print_evalue(DST
, &p
->arr
[0], pname
);
934 fprintf(DST
, "= 0 ] * \n");
935 print_evalue(DST
, &p
->arr
[1], pname
);
937 fprintf(DST
, " +\n [ ");
938 print_evalue(DST
, &p
->arr
[0], pname
);
939 fprintf(DST
, "!= 0 ] * \n");
940 print_evalue(DST
, &p
->arr
[2], pname
);
944 char **names
= pname
;
945 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
946 if (!pname
|| p
->pos
< maxdim
) {
947 NALLOC(names
, maxdim
);
948 for (i
= 0; i
< p
->pos
; ++i
) {
952 NALLOC(names
[i
], 10);
953 snprintf(names
[i
], 10, "%c", 'P'+i
);
956 for ( ; i
< maxdim
; ++i
) {
957 NALLOC(names
[i
], 10);
958 snprintf(names
[i
], 10, "_p%d", i
);
962 for (i
=0; i
<p
->size
/2; i
++) {
963 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
964 print_evalue(DST
, &p
->arr
[2*i
+1], names
);
967 if (!pname
|| p
->pos
< maxdim
) {
968 for (i
= pname
? p
->pos
: 0; i
< maxdim
; ++i
)
981 static void eadd_rev(const evalue
*e1
, evalue
*res
)
985 evalue_copy(&ev
, e1
);
987 free_evalue_refs(res
);
991 static void eadd_rev_cst(const evalue
*e1
, evalue
*res
)
995 evalue_copy(&ev
, e1
);
996 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
997 free_evalue_refs(res
);
1001 static int is_zero_on(evalue
*e
, Polyhedron
*D
)
1006 tmp
.x
.p
= new_enode(partition
, 2, D
->Dimension
);
1007 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Domain_Copy(D
));
1008 evalue_copy(&tmp
.x
.p
->arr
[1], e
);
1009 reduce_evalue(&tmp
);
1010 is_zero
= EVALUE_IS_ZERO(tmp
);
1011 free_evalue_refs(&tmp
);
1015 struct section
{ Polyhedron
* D
; evalue E
; };
1017 void eadd_partitions(const evalue
*e1
, evalue
*res
)
1022 s
= (struct section
*)
1023 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
1024 sizeof(struct section
));
1026 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1027 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1028 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1031 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1032 assert(res
->x
.p
->size
>= 2);
1033 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1034 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
1036 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
1038 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1047 /* See if we can extend one of the domains in res to cover fd */
1048 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1049 if (is_zero_on(&res
->x
.p
->arr
[2*i
+1], fd
))
1051 if (i
< res
->x
.p
->size
/2) {
1052 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
1053 DomainConcat(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
])));
1056 value_init(s
[n
].E
.d
);
1057 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
1061 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1062 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
1063 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1065 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1066 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1072 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1073 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1075 value_init(s
[n
].E
.d
);
1076 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1077 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1078 if (!emptyQ(fd
) && is_zero_on(&e1
->x
.p
->arr
[2*j
+1], fd
)) {
1079 d
= DomainConcat(fd
, d
);
1080 fd
= Empty_Polyhedron(fd
->Dimension
);
1086 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1090 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1093 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1094 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1095 value_clear(res
->x
.p
->arr
[2*i
].d
);
1100 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1101 for (j
= 0; j
< n
; ++j
) {
1102 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1103 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1104 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1105 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1111 static void explicit_complement(evalue
*res
)
1113 enode
*rel
= new_enode(relation
, 3, 0);
1115 value_clear(rel
->arr
[0].d
);
1116 rel
->arr
[0] = res
->x
.p
->arr
[0];
1117 value_clear(rel
->arr
[1].d
);
1118 rel
->arr
[1] = res
->x
.p
->arr
[1];
1119 value_set_si(rel
->arr
[2].d
, 1);
1120 value_init(rel
->arr
[2].x
.n
);
1121 value_set_si(rel
->arr
[2].x
.n
, 0);
1126 void eadd(const evalue
*e1
, evalue
*res
)
1129 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1130 /* Add two rational numbers */
1136 value_multiply(m1
,e1
->x
.n
,res
->d
);
1137 value_multiply(m2
,res
->x
.n
,e1
->d
);
1138 value_addto(res
->x
.n
,m1
,m2
);
1139 value_multiply(res
->d
,e1
->d
,res
->d
);
1140 Gcd(res
->x
.n
,res
->d
,&g
);
1141 if (value_notone_p(g
)) {
1142 value_division(res
->d
,res
->d
,g
);
1143 value_division(res
->x
.n
,res
->x
.n
,g
);
1145 value_clear(g
); value_clear(m1
); value_clear(m2
);
1148 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1149 switch (res
->x
.p
->type
) {
1151 /* Add the constant to the constant term of a polynomial*/
1152 eadd(e1
, &res
->x
.p
->arr
[0]);
1155 /* Add the constant to all elements of a periodic number */
1156 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1157 eadd(e1
, &res
->x
.p
->arr
[i
]);
1161 fprintf(stderr
, "eadd: cannot add const with vector\n");
1165 eadd(e1
, &res
->x
.p
->arr
[1]);
1168 assert(EVALUE_IS_ZERO(*e1
));
1169 break; /* Do nothing */
1171 /* Create (zero) complement if needed */
1172 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1173 explicit_complement(res
);
1174 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1175 eadd(e1
, &res
->x
.p
->arr
[i
]);
1181 /* add polynomial or periodic to constant
1182 * you have to exchange e1 and res, before doing addition */
1184 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1188 else { // ((e1->d==0) && (res->d==0))
1189 assert(!((e1
->x
.p
->type
== partition
) ^
1190 (res
->x
.p
->type
== partition
)));
1191 if (e1
->x
.p
->type
== partition
) {
1192 eadd_partitions(e1
, res
);
1195 if (e1
->x
.p
->type
== relation
&&
1196 (res
->x
.p
->type
!= relation
||
1197 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1201 if (res
->x
.p
->type
== relation
) {
1202 if (e1
->x
.p
->type
== relation
&&
1203 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1204 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1205 explicit_complement(res
);
1206 for (i
= 1; i
< e1
->x
.p
->size
; ++i
)
1207 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1210 if (res
->x
.p
->size
< 3)
1211 explicit_complement(res
);
1212 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1213 eadd(e1
, &res
->x
.p
->arr
[i
]);
1216 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1217 /* adding to evalues of different type. two cases are possible
1218 * res is periodic and e1 is polynomial, you have to exchange
1219 * e1 and res then to add e1 to the constant term of res */
1220 if (e1
->x
.p
->type
== polynomial
) {
1221 eadd_rev_cst(e1
, res
);
1223 else if (res
->x
.p
->type
== polynomial
) {
1224 /* res is polynomial and e1 is periodic,
1225 add e1 to the constant term of res */
1227 eadd(e1
,&res
->x
.p
->arr
[0]);
1233 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1234 ((res
->x
.p
->type
== fractional
||
1235 res
->x
.p
->type
== flooring
) &&
1236 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1237 /* adding evalues of different position (i.e function of different unknowns
1238 * to case are possible */
1240 switch (res
->x
.p
->type
) {
1243 if (mod_term_smaller(res
, e1
))
1244 eadd(e1
,&res
->x
.p
->arr
[1]);
1246 eadd_rev_cst(e1
, res
);
1248 case polynomial
: // res and e1 are polynomials
1249 // add e1 to the constant term of res
1251 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1252 eadd(e1
,&res
->x
.p
->arr
[0]);
1254 eadd_rev_cst(e1
, res
);
1255 // value_clear(g); value_clear(m1); value_clear(m2);
1257 case periodic
: // res and e1 are pointers to periodic numbers
1258 //add e1 to all elements of res
1260 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1261 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1262 eadd(e1
,&res
->x
.p
->arr
[i
]);
1273 //same type , same pos and same size
1274 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1275 // add any element in e1 to the corresponding element in res
1276 i
= type_offset(res
->x
.p
);
1278 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1279 for (; i
<res
->x
.p
->size
; i
++) {
1280 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1285 /* Sizes are different */
1286 switch(res
->x
.p
->type
) {
1290 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1291 /* new enode and add res to that new node. If you do not do */
1292 /* that, you lose the the upper weight part of e1 ! */
1294 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1297 i
= type_offset(res
->x
.p
);
1299 assert(eequal(&e1
->x
.p
->arr
[0],
1300 &res
->x
.p
->arr
[0]));
1301 for (; i
<e1
->x
.p
->size
; i
++) {
1302 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1309 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1312 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1313 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1314 to add periodicaly elements of e1 to elements of ne, and finaly to
1319 value_init(ex
); value_init(ey
);value_init(ep
);
1322 value_set_si(ex
,e1
->x
.p
->size
);
1323 value_set_si(ey
,res
->x
.p
->size
);
1324 value_assign (ep
,*Lcm(ex
,ey
));
1325 p
=(int)mpz_get_si(ep
);
1326 ne
= (evalue
*) malloc (sizeof(evalue
));
1328 value_set_si( ne
->d
,0);
1330 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1332 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1335 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1338 value_assign(res
->d
, ne
->d
);
1344 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1353 static void emul_rev (evalue
*e1
, evalue
*res
)
1357 evalue_copy(&ev
, e1
);
1359 free_evalue_refs(res
);
1363 static void emul_poly (evalue
*e1
, evalue
*res
)
1365 int i
, j
, o
= type_offset(res
->x
.p
);
1367 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1369 value_set_si(tmp
.d
,0);
1370 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1372 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1373 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1374 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1375 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1378 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1379 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1380 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1383 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1384 emul(&res
->x
.p
->arr
[i
], &ev
);
1385 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1386 free_evalue_refs(&ev
);
1388 free_evalue_refs(res
);
1392 void emul_partitions (evalue
*e1
,evalue
*res
)
1397 s
= (struct section
*)
1398 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1399 sizeof(struct section
));
1401 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1402 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1403 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1406 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1407 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1408 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1409 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1415 /* This code is only needed because the partitions
1416 are not true partitions.
1418 for (k
= 0; k
< n
; ++k
) {
1419 if (DomainIncludes(s
[k
].D
, d
))
1421 if (DomainIncludes(d
, s
[k
].D
)) {
1422 Domain_Free(s
[k
].D
);
1423 free_evalue_refs(&s
[k
].E
);
1434 value_init(s
[n
].E
.d
);
1435 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1436 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1440 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1441 value_clear(res
->x
.p
->arr
[2*i
].d
);
1442 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1447 evalue_set_si(res
, 0, 1);
1449 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1450 for (j
= 0; j
< n
; ++j
) {
1451 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1452 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1453 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1454 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1461 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1463 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1464 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1465 * evalues is not treated here */
1467 void emul (evalue
*e1
, evalue
*res
){
1470 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1471 fprintf(stderr
, "emul: do not proced on evector type !\n");
1475 if (EVALUE_IS_ZERO(*res
))
1478 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1479 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1480 emul_partitions(e1
, res
);
1483 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1484 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1485 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1487 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1488 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1489 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1490 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1491 explicit_complement(res
);
1492 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1493 explicit_complement(e1
);
1494 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1495 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1498 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1499 emul(e1
, &res
->x
.p
->arr
[i
]);
1501 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1502 switch(e1
->x
.p
->type
) {
1504 switch(res
->x
.p
->type
) {
1506 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1507 /* Product of two polynomials of the same variable */
1512 /* Product of two polynomials of different variables */
1514 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1515 for( i
=0; i
<res
->x
.p
->size
; i
++)
1516 emul(e1
, &res
->x
.p
->arr
[i
]);
1525 /* Product of a polynomial and a periodic or fractional */
1532 switch(res
->x
.p
->type
) {
1534 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1535 /* Product of two periodics of the same parameter and period */
1537 for(i
=0; i
<res
->x
.p
->size
;i
++)
1538 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1543 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1544 /* Product of two periodics of the same parameter and different periods */
1548 value_init(x
); value_init(y
);value_init(z
);
1551 value_set_si(x
,e1
->x
.p
->size
);
1552 value_set_si(y
,res
->x
.p
->size
);
1553 value_assign (z
,*Lcm(x
,y
));
1554 lcm
=(int)mpz_get_si(z
);
1555 newp
= (evalue
*) malloc (sizeof(evalue
));
1556 value_init(newp
->d
);
1557 value_set_si( newp
->d
,0);
1558 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1559 for(i
=0;i
<lcm
;i
++) {
1560 evalue_copy(&newp
->x
.p
->arr
[i
],
1561 &res
->x
.p
->arr
[i
%iy
]);
1564 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1566 value_assign(res
->d
,newp
->d
);
1569 value_clear(x
); value_clear(y
);value_clear(z
);
1573 /* Product of two periodics of different parameters */
1575 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1576 for(i
=0; i
<res
->x
.p
->size
; i
++)
1577 emul(e1
, &(res
->x
.p
->arr
[i
]));
1585 /* Product of a periodic and a polynomial */
1587 for(i
=0; i
<res
->x
.p
->size
; i
++)
1588 emul(e1
, &(res
->x
.p
->arr
[i
]));
1595 switch(res
->x
.p
->type
) {
1597 for(i
=0; i
<res
->x
.p
->size
; i
++)
1598 emul(e1
, &(res
->x
.p
->arr
[i
]));
1605 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1606 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1607 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1610 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1611 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1616 value_set_si(d
.x
.n
, 1);
1617 /* { x }^2 == { x }/2 */
1618 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1619 assert(e1
->x
.p
->size
== 3);
1620 assert(res
->x
.p
->size
== 3);
1622 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1624 eadd(&res
->x
.p
->arr
[1], &tmp
);
1625 emul(&e1
->x
.p
->arr
[2], &tmp
);
1626 emul(&e1
->x
.p
->arr
[1], res
);
1627 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1628 free_evalue_refs(&tmp
);
1633 if(mod_term_smaller(res
, e1
))
1634 for(i
=1; i
<res
->x
.p
->size
; i
++)
1635 emul(e1
, &(res
->x
.p
->arr
[i
]));
1650 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1651 /* Product of two rational numbers */
1655 value_multiply(res
->d
,e1
->d
,res
->d
);
1656 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1657 Gcd(res
->x
.n
, res
->d
,&g
);
1658 if (value_notone_p(g
)) {
1659 value_division(res
->d
,res
->d
,g
);
1660 value_division(res
->x
.n
,res
->x
.n
,g
);
1666 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1667 /* Product of an expression (polynomial or peririodic) and a rational number */
1673 /* Product of a rationel number and an expression (polynomial or peririodic) */
1675 i
= type_offset(res
->x
.p
);
1676 for (; i
<res
->x
.p
->size
; i
++)
1677 emul(e1
, &res
->x
.p
->arr
[i
]);
1687 /* Frees mask content ! */
1688 void emask(evalue
*mask
, evalue
*res
) {
1695 if (EVALUE_IS_ZERO(*res
)) {
1696 free_evalue_refs(mask
);
1700 assert(value_zero_p(mask
->d
));
1701 assert(mask
->x
.p
->type
== partition
);
1702 assert(value_zero_p(res
->d
));
1703 assert(res
->x
.p
->type
== partition
);
1704 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1705 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1706 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1707 pos
= res
->x
.p
->pos
;
1709 s
= (struct section
*)
1710 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1711 sizeof(struct section
));
1715 evalue_set_si(&mone
, -1, 1);
1718 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1719 assert(mask
->x
.p
->size
>= 2);
1720 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1721 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1723 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1725 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1734 value_init(s
[n
].E
.d
);
1735 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1739 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1740 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1743 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1744 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1745 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1746 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1748 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1749 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1755 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1756 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1758 value_init(s
[n
].E
.d
);
1759 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1760 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1766 /* Just ignore; this may have been previously masked off */
1768 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1772 free_evalue_refs(&mone
);
1773 free_evalue_refs(mask
);
1774 free_evalue_refs(res
);
1777 evalue_set_si(res
, 0, 1);
1779 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1780 for (j
= 0; j
< n
; ++j
) {
1781 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1782 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1783 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1790 void evalue_copy(evalue
*dst
, const evalue
*src
)
1792 value_assign(dst
->d
, src
->d
);
1793 if(value_notzero_p(src
->d
)) {
1794 value_init(dst
->x
.n
);
1795 value_assign(dst
->x
.n
, src
->x
.n
);
1797 dst
->x
.p
= ecopy(src
->x
.p
);
1800 enode
*new_enode(enode_type type
,int size
,int pos
) {
1806 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1809 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1813 for(i
=0; i
<size
; i
++) {
1814 value_init(res
->arr
[i
].d
);
1815 value_set_si(res
->arr
[i
].d
,0);
1816 res
->arr
[i
].x
.p
= 0;
1821 enode
*ecopy(enode
*e
) {
1826 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1827 for(i
=0;i
<e
->size
;++i
) {
1828 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1829 if(value_zero_p(res
->arr
[i
].d
))
1830 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1831 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1832 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1834 value_init(res
->arr
[i
].x
.n
);
1835 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1841 int ecmp(const evalue
*e1
, const evalue
*e2
)
1847 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1851 value_multiply(m
, e1
->x
.n
, e2
->d
);
1852 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1854 if (value_lt(m
, m2
))
1856 else if (value_gt(m
, m2
))
1866 if (value_notzero_p(e1
->d
))
1868 if (value_notzero_p(e2
->d
))
1874 if (p1
->type
!= p2
->type
)
1875 return p1
->type
- p2
->type
;
1876 if (p1
->pos
!= p2
->pos
)
1877 return p1
->pos
- p2
->pos
;
1878 if (p1
->size
!= p2
->size
)
1879 return p1
->size
- p2
->size
;
1881 for (i
= p1
->size
-1; i
>= 0; --i
)
1882 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1888 int eequal(evalue
*e1
,evalue
*e2
) {
1893 if (value_ne(e1
->d
,e2
->d
))
1896 /* e1->d == e2->d */
1897 if (value_notzero_p(e1
->d
)) {
1898 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1901 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1905 /* e1->d == e2->d == 0 */
1908 if (p1
->type
!= p2
->type
) return 0;
1909 if (p1
->size
!= p2
->size
) return 0;
1910 if (p1
->pos
!= p2
->pos
) return 0;
1911 for (i
=0; i
<p1
->size
; i
++)
1912 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1917 void free_evalue_refs(evalue
*e
) {
1922 if (EVALUE_IS_DOMAIN(*e
)) {
1923 Domain_Free(EVALUE_DOMAIN(*e
));
1926 } else if (value_pos_p(e
->d
)) {
1928 /* 'e' stores a constant */
1930 value_clear(e
->x
.n
);
1933 assert(value_zero_p(e
->d
));
1936 if (!p
) return; /* null pointer */
1937 for (i
=0; i
<p
->size
; i
++) {
1938 free_evalue_refs(&(p
->arr
[i
]));
1942 } /* free_evalue_refs */
1944 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1945 Vector
* val
, evalue
*res
)
1947 unsigned nparam
= periods
->Size
;
1950 double d
= compute_evalue(e
, val
->p
);
1951 d
*= VALUE_TO_DOUBLE(m
);
1956 value_assign(res
->d
, m
);
1957 value_init(res
->x
.n
);
1958 value_set_double(res
->x
.n
, d
);
1959 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1962 if (value_one_p(periods
->p
[p
]))
1963 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1968 value_assign(tmp
, periods
->p
[p
]);
1969 value_set_si(res
->d
, 0);
1970 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1972 value_decrement(tmp
, tmp
);
1973 value_assign(val
->p
[p
], tmp
);
1974 mod2table_r(e
, periods
, m
, p
+1, val
,
1975 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1976 } while (value_pos_p(tmp
));
1982 static void rel2table(evalue
*e
, int zero
)
1984 if (value_pos_p(e
->d
)) {
1985 if (value_zero_p(e
->x
.n
) == zero
)
1986 value_set_si(e
->x
.n
, 1);
1988 value_set_si(e
->x
.n
, 0);
1989 value_set_si(e
->d
, 1);
1992 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1993 rel2table(&e
->x
.p
->arr
[i
], zero
);
1997 void evalue_mod2table(evalue
*e
, int nparam
)
2002 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2005 for (i
=0; i
<p
->size
; i
++) {
2006 evalue_mod2table(&(p
->arr
[i
]), nparam
);
2008 if (p
->type
== relation
) {
2013 evalue_copy(©
, &p
->arr
[0]);
2015 rel2table(&p
->arr
[0], 1);
2016 emul(&p
->arr
[0], &p
->arr
[1]);
2018 rel2table(©
, 0);
2019 emul(©
, &p
->arr
[2]);
2020 eadd(&p
->arr
[2], &p
->arr
[1]);
2021 free_evalue_refs(&p
->arr
[2]);
2022 free_evalue_refs(©
);
2024 free_evalue_refs(&p
->arr
[0]);
2028 } else if (p
->type
== fractional
) {
2029 Vector
*periods
= Vector_Alloc(nparam
);
2030 Vector
*val
= Vector_Alloc(nparam
);
2036 value_set_si(tmp
, 1);
2037 Vector_Set(periods
->p
, 1, nparam
);
2038 Vector_Set(val
->p
, 0, nparam
);
2039 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2042 assert(p
->type
== polynomial
);
2043 assert(p
->size
== 2);
2044 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2045 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
2047 value_lcm(tmp
, ev
->d
, &tmp
);
2049 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2052 evalue_set_si(&res
, 0, 1);
2053 /* Compute the polynomial using Horner's rule */
2054 for (i
=p
->size
-1;i
>1;i
--) {
2055 eadd(&p
->arr
[i
], &res
);
2058 eadd(&p
->arr
[1], &res
);
2060 free_evalue_refs(e
);
2061 free_evalue_refs(&EP
);
2066 Vector_Free(periods
);
2068 } /* evalue_mod2table */
2070 /********************************************************/
2071 /* function in domain */
2072 /* check if the parameters in list_args */
2073 /* verifies the constraints of Domain P */
2074 /********************************************************/
2075 int in_domain(Polyhedron
*P
, Value
*list_args
) {
2078 Value v
; /* value of the constraint of a row when
2079 parameters are instanciated*/
2085 /*P->Constraint constraint matrice of polyhedron P*/
2086 for(row
=0;row
<P
->NbConstraints
;row
++) {
2087 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2088 for(col
=1;col
<P
->Dimension
+1;col
++) {
2089 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
2090 value_addto(v
,v
,tmp
);
2092 if (value_notzero_p(P
->Constraint
[row
][0])) {
2094 /*if v is not >=0 then this constraint is not respected */
2095 if (value_neg_p(v
)) {
2099 return P
->next
? in_domain(P
->next
, list_args
) : 0;
2104 /*if v is not = 0 then this constraint is not respected */
2105 if (value_notzero_p(v
))
2110 /*if not return before this point => all
2111 the constraints are respected */
2117 /****************************************************/
2118 /* function compute enode */
2119 /* compute the value of enode p with parameters */
2120 /* list "list_args */
2121 /* compute the polynomial or the periodic */
2122 /****************************************************/
2124 static double compute_enode(enode
*p
, Value
*list_args
) {
2136 if (p
->type
== polynomial
) {
2138 value_assign(param
,list_args
[p
->pos
-1]);
2140 /* Compute the polynomial using Horner's rule */
2141 for (i
=p
->size
-1;i
>0;i
--) {
2142 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2143 res
*=VALUE_TO_DOUBLE(param
);
2145 res
+=compute_evalue(&p
->arr
[0],list_args
);
2147 else if (p
->type
== fractional
) {
2148 double d
= compute_evalue(&p
->arr
[0], list_args
);
2149 d
-= floor(d
+1e-10);
2151 /* Compute the polynomial using Horner's rule */
2152 for (i
=p
->size
-1;i
>1;i
--) {
2153 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2156 res
+=compute_evalue(&p
->arr
[1],list_args
);
2158 else if (p
->type
== flooring
) {
2159 double d
= compute_evalue(&p
->arr
[0], list_args
);
2162 /* Compute the polynomial using Horner's rule */
2163 for (i
=p
->size
-1;i
>1;i
--) {
2164 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2167 res
+=compute_evalue(&p
->arr
[1],list_args
);
2169 else if (p
->type
== periodic
) {
2170 value_assign(m
,list_args
[p
->pos
-1]);
2172 /* Choose the right element of the periodic */
2173 value_set_si(param
,p
->size
);
2174 value_pmodulus(m
,m
,param
);
2175 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2177 else if (p
->type
== relation
) {
2178 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2179 res
= compute_evalue(&p
->arr
[1], list_args
);
2180 else if (p
->size
> 2)
2181 res
= compute_evalue(&p
->arr
[2], list_args
);
2183 else if (p
->type
== partition
) {
2184 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2185 Value
*vals
= list_args
;
2188 for (i
= 0; i
< dim
; ++i
) {
2189 value_init(vals
[i
]);
2191 value_assign(vals
[i
], list_args
[i
]);
2194 for (i
= 0; i
< p
->size
/2; ++i
)
2195 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2196 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2200 for (i
= 0; i
< dim
; ++i
)
2201 value_clear(vals
[i
]);
2210 } /* compute_enode */
2212 /*************************************************/
2213 /* return the value of Ehrhart Polynomial */
2214 /* It returns a double, because since it is */
2215 /* a recursive function, some intermediate value */
2216 /* might not be integral */
2217 /*************************************************/
2219 double compute_evalue(evalue
*e
,Value
*list_args
) {
2223 if (value_notzero_p(e
->d
)) {
2224 if (value_notone_p(e
->d
))
2225 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2227 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2230 res
= compute_enode(e
->x
.p
,list_args
);
2232 } /* compute_evalue */
2235 /****************************************************/
2236 /* function compute_poly : */
2237 /* Check for the good validity domain */
2238 /* return the number of point in the Polyhedron */
2239 /* in allocated memory */
2240 /* Using the Ehrhart pseudo-polynomial */
2241 /****************************************************/
2242 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2245 /* double d; int i; */
2247 tmp
= (Value
*) malloc (sizeof(Value
));
2248 assert(tmp
!= NULL
);
2250 value_set_si(*tmp
,0);
2253 return(tmp
); /* no ehrhart polynomial */
2254 if(en
->ValidityDomain
) {
2255 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2256 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2261 return(tmp
); /* no Validity Domain */
2263 if(in_domain(en
->ValidityDomain
,list_args
)) {
2265 #ifdef EVAL_EHRHART_DEBUG
2266 Print_Domain(stdout
,en
->ValidityDomain
);
2267 print_evalue(stdout
,&en
->EP
);
2270 /* d = compute_evalue(&en->EP,list_args);
2272 printf("(double)%lf = %d\n", d, i ); */
2273 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2279 value_set_si(*tmp
,0);
2280 return(tmp
); /* no compatible domain with the arguments */
2281 } /* compute_poly */
2283 size_t value_size(Value v
) {
2284 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2285 * sizeof(v
[0]._mp_d
[0]);
2288 size_t domain_size(Polyhedron
*D
)
2291 size_t s
= sizeof(*D
);
2293 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2294 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2295 s
+= value_size(D
->Constraint
[i
][j
]);
2298 for (i = 0; i < D->NbRays; ++i)
2299 for (j = 0; j < D->Dimension+2; ++j)
2300 s += value_size(D->Ray[i][j]);
2303 return D
->next
? s
+domain_size(D
->next
) : s
;
2306 size_t enode_size(enode
*p
) {
2307 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2310 if (p
->type
== partition
)
2311 for (i
= 0; i
< p
->size
/2; ++i
) {
2312 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2313 s
+= evalue_size(&p
->arr
[2*i
+1]);
2316 for (i
= 0; i
< p
->size
; ++i
) {
2317 s
+= evalue_size(&p
->arr
[i
]);
2322 size_t evalue_size(evalue
*e
)
2324 size_t s
= sizeof(*e
);
2325 s
+= value_size(e
->d
);
2326 if (value_notzero_p(e
->d
))
2327 s
+= value_size(e
->x
.n
);
2329 s
+= enode_size(e
->x
.p
);
2333 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2335 evalue
*found
= NULL
;
2340 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2343 value_init(offset
.d
);
2344 value_init(offset
.x
.n
);
2345 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2346 value_lcm(m
, offset
.d
, &offset
.d
);
2347 value_set_si(offset
.x
.n
, 1);
2350 evalue_copy(©
, cst
);
2353 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2355 if (eequal(base
, &e
->x
.p
->arr
[0]))
2356 found
= &e
->x
.p
->arr
[0];
2358 value_set_si(offset
.x
.n
, -2);
2361 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2363 if (eequal(base
, &e
->x
.p
->arr
[0]))
2366 free_evalue_refs(cst
);
2367 free_evalue_refs(&offset
);
2370 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2371 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2376 static evalue
*find_relation_pair(evalue
*e
)
2379 evalue
*found
= NULL
;
2381 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2384 if (e
->x
.p
->type
== fractional
) {
2389 poly_denom(&e
->x
.p
->arr
[0], &m
);
2391 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2392 cst
= &cst
->x
.p
->arr
[0])
2395 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2396 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2401 i
= e
->x
.p
->type
== relation
;
2402 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2403 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2408 void evalue_mod2relation(evalue
*e
) {
2411 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2414 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2415 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2416 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2417 value_clear(e
->x
.p
->arr
[2*i
].d
);
2418 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2420 if (2*i
< e
->x
.p
->size
) {
2421 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2422 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2427 if (e
->x
.p
->size
== 0) {
2429 evalue_set_si(e
, 0, 1);
2435 while ((d
= find_relation_pair(e
)) != NULL
) {
2439 value_init(split
.d
);
2440 value_set_si(split
.d
, 0);
2441 split
.x
.p
= new_enode(relation
, 3, 0);
2442 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2443 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2445 ev
= &split
.x
.p
->arr
[0];
2446 value_set_si(ev
->d
, 0);
2447 ev
->x
.p
= new_enode(fractional
, 3, -1);
2448 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2449 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2450 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2456 free_evalue_refs(&split
);
2460 static int evalue_comp(const void * a
, const void * b
)
2462 const evalue
*e1
= *(const evalue
**)a
;
2463 const evalue
*e2
= *(const evalue
**)b
;
2464 return ecmp(e1
, e2
);
2467 void evalue_combine(evalue
*e
)
2474 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2477 NALLOC(evs
, e
->x
.p
->size
/2);
2478 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2479 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2480 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2481 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2482 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2483 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2484 value_clear(p
->arr
[2*k
].d
);
2485 value_clear(p
->arr
[2*k
+1].d
);
2486 p
->arr
[2*k
] = *(evs
[i
]-1);
2487 p
->arr
[2*k
+1] = *(evs
[i
]);
2490 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2493 value_clear((evs
[i
]-1)->d
);
2497 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2498 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2499 free_evalue_refs(evs
[i
]);
2503 for (i
= 2*k
; i
< p
->size
; ++i
)
2504 value_clear(p
->arr
[i
].d
);
2511 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2513 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2515 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2518 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2519 Polyhedron
*D
, *N
, **P
;
2522 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2529 if (D
->NbEq
<= H
->NbEq
) {
2535 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2536 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2537 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2538 reduce_evalue(&tmp
);
2539 if (value_notzero_p(tmp
.d
) ||
2540 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2543 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2544 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2547 free_evalue_refs(&tmp
);
2553 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2555 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2557 value_clear(e
->x
.p
->arr
[2*i
].d
);
2558 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2560 if (2*i
< e
->x
.p
->size
) {
2561 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2562 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2569 H
= DomainConvex(D
, 0);
2570 E
= DomainDifference(H
, D
, 0);
2572 D
= DomainDifference(H
, E
, 0);
2575 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2579 /* May change coefficients to become non-standard if fiddle is set
2580 * => reduce p afterwards to correct
2582 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2583 Matrix
**R
, int fiddle
)
2587 unsigned dim
= D
->Dimension
;
2588 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2593 assert(p
->type
== fractional
);
2595 value_set_si(T
->p
[1][dim
], 1);
2597 while (value_zero_p(pp
->d
)) {
2598 assert(pp
->x
.p
->type
== polynomial
);
2599 assert(pp
->x
.p
->size
== 2);
2600 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2601 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2602 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2603 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2604 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2605 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2606 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2607 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2608 pp
= &pp
->x
.p
->arr
[0];
2610 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2611 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2612 I
= DomainImage(D
, T
, 0);
2613 H
= DomainConvex(I
, 0);
2622 int evalue_range_reduction_in_domain(evalue
*e
, Polyhedron
*D
)
2632 if (value_notzero_p(e
->d
))
2637 if (p
->type
== relation
) {
2643 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2644 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2645 equal
= value_eq(min
, max
);
2646 mpz_cdiv_q(min
, min
, d
);
2647 mpz_fdiv_q(max
, max
, d
);
2649 if (bounded
&& value_gt(min
, max
)) {
2655 evalue_set_si(e
, 0, 1);
2658 free_evalue_refs(&(p
->arr
[1]));
2659 free_evalue_refs(&(p
->arr
[0]));
2665 return r
? r
: evalue_range_reduction_in_domain(e
, D
);
2666 } else if (bounded
&& equal
) {
2669 free_evalue_refs(&(p
->arr
[2]));
2672 free_evalue_refs(&(p
->arr
[0]));
2678 return evalue_range_reduction_in_domain(e
, D
);
2679 } else if (bounded
&& value_eq(min
, max
)) {
2680 /* zero for a single value */
2682 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2683 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2684 value_multiply(min
, min
, d
);
2685 value_subtract(M
->p
[0][D
->Dimension
+1],
2686 M
->p
[0][D
->Dimension
+1], min
);
2687 E
= DomainAddConstraints(D
, M
, 0);
2693 r
= evalue_range_reduction_in_domain(&p
->arr
[1], E
);
2695 r
|= evalue_range_reduction_in_domain(&p
->arr
[2], D
);
2697 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2705 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2708 i
= p
->type
== relation
? 1 :
2709 p
->type
== fractional
? 1 : 0;
2710 for (; i
<p
->size
; i
++)
2711 r
|= evalue_range_reduction_in_domain(&p
->arr
[i
], D
);
2713 if (p
->type
!= fractional
) {
2714 if (r
&& p
->type
== polynomial
) {
2717 value_set_si(f
.d
, 0);
2718 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2719 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2720 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2721 reorder_terms(p
, &f
);
2732 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2734 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2735 mpz_fdiv_q(min
, min
, d
);
2736 mpz_fdiv_q(max
, max
, d
);
2737 value_subtract(d
, max
, min
);
2739 if (bounded
&& value_eq(min
, max
)) {
2742 value_init(inc
.x
.n
);
2743 value_set_si(inc
.d
, 1);
2744 value_oppose(inc
.x
.n
, min
);
2745 eadd(&inc
, &p
->arr
[0]);
2746 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2750 free_evalue_refs(&inc
);
2752 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2759 value_set_si(rem
.d
, 0);
2760 rem
.x
.p
= new_enode(fractional
, 3, -1);
2761 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2762 value_clear(rem
.x
.p
->arr
[1].d
);
2763 value_clear(rem
.x
.p
->arr
[2].d
);
2764 rem
.x
.p
->arr
[1] = p
->arr
[1];
2765 rem
.x
.p
->arr
[2] = p
->arr
[2];
2766 for (i
= 3; i
< p
->size
; ++i
)
2767 p
->arr
[i
-2] = p
->arr
[i
];
2771 value_init(inc
.x
.n
);
2772 value_set_si(inc
.d
, 1);
2773 value_oppose(inc
.x
.n
, min
);
2776 evalue_copy(&t
, &p
->arr
[0]);
2780 value_set_si(f
.d
, 0);
2781 f
.x
.p
= new_enode(fractional
, 3, -1);
2782 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2783 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2784 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2786 value_init(factor
.d
);
2787 evalue_set_si(&factor
, -1, 1);
2793 value_clear(f
.x
.p
->arr
[1].x
.n
);
2794 value_clear(f
.x
.p
->arr
[2].x
.n
);
2795 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2796 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2802 free_evalue_refs(&inc
);
2803 free_evalue_refs(&t
);
2804 free_evalue_refs(&f
);
2805 free_evalue_refs(&factor
);
2806 free_evalue_refs(&rem
);
2808 evalue_range_reduction_in_domain(e
, D
);
2812 _reduce_evalue(&p
->arr
[0], 0, 1);
2816 value_set_si(f
.d
, 0);
2817 f
.x
.p
= new_enode(fractional
, 3, -1);
2818 value_clear(f
.x
.p
->arr
[0].d
);
2819 f
.x
.p
->arr
[0] = p
->arr
[0];
2820 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2821 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2822 reorder_terms(p
, &f
);
2836 void evalue_range_reduction(evalue
*e
)
2839 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2842 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2843 if (evalue_range_reduction_in_domain(&e
->x
.p
->arr
[2*i
+1],
2844 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2845 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2847 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2848 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2849 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2850 value_clear(e
->x
.p
->arr
[2*i
].d
);
2852 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2853 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2861 Enumeration
* partition2enumeration(evalue
*EP
)
2864 Enumeration
*en
, *res
= NULL
;
2866 if (EVALUE_IS_ZERO(*EP
)) {
2871 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2872 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
2873 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2876 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2877 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2878 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2886 int evalue_frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2896 if (value_notzero_p(e
->d
))
2901 i
= p
->type
== relation
? 1 :
2902 p
->type
== fractional
? 1 : 0;
2903 for (; i
<p
->size
; i
++)
2904 r
|= evalue_frac2floor_in_domain(&p
->arr
[i
], D
);
2906 if (p
->type
!= fractional
) {
2907 if (r
&& p
->type
== polynomial
) {
2910 value_set_si(f
.d
, 0);
2911 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2912 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2913 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2914 reorder_terms(p
, &f
);
2923 I
= polynomial_projection(p
, D
, &d
, &T
, 0);
2926 Polyhedron_Print(stderr, P_VALUE_FMT, I);
2929 assert(I
->NbEq
== 0); /* Should have been reduced */
2932 for (i
= 0; i
< I
->NbConstraints
; ++i
)
2933 if (value_pos_p(I
->Constraint
[i
][1]))
2936 if (i
< I
->NbConstraints
) {
2938 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
2939 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
2940 if (value_neg_p(min
)) {
2942 mpz_fdiv_q(min
, min
, d
);
2943 value_init(offset
.d
);
2944 value_set_si(offset
.d
, 1);
2945 value_init(offset
.x
.n
);
2946 value_oppose(offset
.x
.n
, min
);
2947 eadd(&offset
, &p
->arr
[0]);
2948 free_evalue_refs(&offset
);
2958 value_set_si(fl
.d
, 0);
2959 fl
.x
.p
= new_enode(flooring
, 3, -1);
2960 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2961 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2962 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2964 eadd(&fl
, &p
->arr
[0]);
2965 reorder_terms(p
, &p
->arr
[0]);
2969 free_evalue_refs(&fl
);
2974 void evalue_frac2floor(evalue
*e
)
2977 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2980 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2981 if (evalue_frac2floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
2982 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])))
2983 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2986 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2991 int nparam
= D
->Dimension
- nvar
;
2994 nr
= D
->NbConstraints
+ 2;
2995 nc
= D
->Dimension
+ 2 + 1;
2996 C
= Matrix_Alloc(nr
, nc
);
2997 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2998 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
2999 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3000 D
->Dimension
+ 1 - nvar
);
3005 nc
= C
->NbColumns
+ 1;
3006 C
= Matrix_Alloc(nr
, nc
);
3007 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
3008 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
3009 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3010 oldC
->NbColumns
- 1 - nvar
);
3013 value_set_si(C
->p
[nr
-2][0], 1);
3014 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
3015 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
3017 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
3018 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
3024 static void floor2frac_r(evalue
*e
, int nvar
)
3031 if (value_notzero_p(e
->d
))
3036 assert(p
->type
== flooring
);
3037 for (i
= 1; i
< p
->size
; i
++)
3038 floor2frac_r(&p
->arr
[i
], nvar
);
3040 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3041 assert(pp
->x
.p
->type
== polynomial
);
3042 pp
->x
.p
->pos
-= nvar
;
3046 value_set_si(f
.d
, 0);
3047 f
.x
.p
= new_enode(fractional
, 3, -1);
3048 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3049 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3050 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3052 eadd(&f
, &p
->arr
[0]);
3053 reorder_terms(p
, &p
->arr
[0]);
3057 free_evalue_refs(&f
);
3060 /* Convert flooring back to fractional and shift position
3061 * of the parameters by nvar
3063 static void floor2frac(evalue
*e
, int nvar
)
3065 floor2frac_r(e
, nvar
);
3069 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
3072 int nparam
= D
->Dimension
- nvar
;
3076 D
= Constraints2Polyhedron(C
, 0);
3080 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3082 /* Double check that D was not unbounded. */
3083 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3091 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3098 evalue
*factor
= NULL
;
3101 if (EVALUE_IS_ZERO(*e
))
3105 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
3112 res
= esum_over_domain(e
, nvar
, Q
, C
);
3115 for (Q
= DD
; Q
; Q
= DD
) {
3121 t
= esum_over_domain(e
, nvar
, Q
, C
);
3128 free_evalue_refs(t
);
3135 if (value_notzero_p(e
->d
)) {
3138 t
= esum_over_domain_cst(nvar
, D
, C
);
3140 if (!EVALUE_IS_ONE(*e
))
3146 switch (e
->x
.p
->type
) {
3148 evalue
*pp
= &e
->x
.p
->arr
[0];
3150 if (pp
->x
.p
->pos
> nvar
) {
3151 /* remainder is independent of the summated vars */
3157 floor2frac(&f
, nvar
);
3159 t
= esum_over_domain_cst(nvar
, D
, C
);
3163 free_evalue_refs(&f
);
3168 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3169 poly_denom(pp
, &row
->p
[1 + nvar
]);
3170 value_set_si(row
->p
[0], 1);
3171 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3172 pp
= &pp
->x
.p
->arr
[0]) {
3174 assert(pp
->x
.p
->type
== polynomial
);
3176 if (pos
>= 1 + nvar
)
3178 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3179 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3180 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3182 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3183 value_division(row
->p
[1 + D
->Dimension
+ 1],
3184 row
->p
[1 + D
->Dimension
+ 1],
3186 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3187 row
->p
[1 + D
->Dimension
+ 1],
3189 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3193 int pos
= e
->x
.p
->pos
;
3196 factor
= ALLOC(evalue
);
3197 value_init(factor
->d
);
3198 value_set_si(factor
->d
, 0);
3199 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3200 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3201 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3205 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3206 for (i
= 0; i
< D
->NbRays
; ++i
)
3207 if (value_notzero_p(D
->Ray
[i
][pos
]))
3209 assert(i
< D
->NbRays
);
3210 if (value_neg_p(D
->Ray
[i
][pos
])) {
3211 factor
= ALLOC(evalue
);
3212 value_init(factor
->d
);
3213 evalue_set_si(factor
, -1, 1);
3215 value_set_si(row
->p
[0], 1);
3216 value_set_si(row
->p
[pos
], 1);
3217 value_set_si(row
->p
[1 + nvar
], -1);
3224 i
= type_offset(e
->x
.p
);
3226 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3231 evalue_copy(&cum
, factor
);
3235 for (; i
< e
->x
.p
->size
; ++i
) {
3239 C
= esum_add_constraint(nvar
, D
, C
, row
);
3245 Vector_Print(stderr, P_VALUE_FMT, row);
3247 Matrix_Print(stderr, P_VALUE_FMT, C);
3249 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3258 free_evalue_refs(t
);
3261 if (factor
&& i
+1 < e
->x
.p
->size
)
3268 free_evalue_refs(factor
);
3269 free_evalue_refs(&cum
);
3281 evalue
*esum(evalue
*e
, int nvar
)
3284 evalue
*res
= ALLOC(evalue
);
3288 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3289 evalue_copy(res
, e
);
3293 evalue_set_si(res
, 0, 1);
3295 assert(value_zero_p(e
->d
));
3296 assert(e
->x
.p
->type
== partition
);
3298 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3300 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3301 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3303 free_evalue_refs(t
);
3312 /* Initial silly implementation */
3313 void eor(evalue
*e1
, evalue
*res
)
3319 evalue_set_si(&mone
, -1, 1);
3321 evalue_copy(&E
, res
);
3327 free_evalue_refs(&E
);
3328 free_evalue_refs(&mone
);