5 #include "ev_operations.h"
10 #define value_pmodulus(ref,val1,val2) (mpz_fdiv_r((ref),(val1),(val2)))
13 #define ALLOC(p) p = (typeof(p))malloc(sizeof(*p))
14 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
16 void evalue_set_si(evalue
*ev
, int n
, int d
) {
17 value_set_si(ev
->d
, d
);
19 value_set_si(ev
->x
.n
, n
);
22 void evalue_set(evalue
*ev
, Value n
, Value d
) {
23 value_assign(ev
->d
, d
);
25 value_assign(ev
->x
.n
, n
);
28 void aep_evalue(evalue
*e
, int *ref
) {
33 if (value_notzero_p(e
->d
))
34 return; /* a rational number, its already reduced */
36 return; /* hum... an overflow probably occured */
38 /* First check the components of p */
39 for (i
=0;i
<p
->size
;i
++)
40 aep_evalue(&p
->arr
[i
],ref
);
47 p
->pos
= ref
[p
->pos
-1]+1;
53 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
59 if (value_notzero_p(e
->d
))
60 return; /* a rational number, its already reduced */
62 return; /* hum... an overflow probably occured */
65 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
66 for(i
=0;i
<CT
->NbRows
-1;i
++)
67 for(j
=0;j
<CT
->NbColumns
;j
++)
68 if(value_notzero_p(CT
->p
[i
][j
])) {
73 /* Transform the references in e, using ref */
77 } /* addeliminatedparams_evalue */
79 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
80 unsigned MaxRays
, unsigned nparam
)
85 if (CT
->NbRows
== CT
->NbColumns
)
88 if (EVALUE_IS_ZERO(*e
))
91 if (value_notzero_p(e
->d
)) {
94 value_set_si(res
.d
, 0);
95 res
.x
.p
= new_enode(partition
, 2, nparam
);
96 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
97 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
98 value_clear(res
.x
.p
->arr
[1].d
);
106 assert(p
->type
== partition
);
109 for (i
=0; i
<p
->size
/2; i
++) {
110 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
111 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
114 T
= DomainIntersection(D
, CEq
, MaxRays
);
116 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
117 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
121 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
129 assert(value_notzero_p(e1
->d
));
130 assert(value_notzero_p(e2
->d
));
131 value_multiply(m
, e1
->x
.n
, e2
->d
);
132 value_multiply(m2
, e2
->x
.n
, e1
->d
);
135 else if (value_gt(m
, m2
))
145 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
147 if (value_notzero_p(e1
->d
)) {
149 if (value_zero_p(e2
->d
))
151 r
= mod_rational_smaller(e1
, e2
);
152 return r
== -1 ? 0 : r
;
154 if (value_notzero_p(e2
->d
))
156 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
158 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
161 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
163 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
168 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
170 assert(value_zero_p(e1
->d
));
171 assert(value_zero_p(e2
->d
));
172 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
173 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
174 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
177 /* Negative pos means inequality */
178 /* s is negative of substitution if m is not zero */
187 struct fixed_param
*fixed
;
192 static int relations_depth(evalue
*e
)
197 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
198 e
= &e
->x
.p
->arr
[1], ++d
);
202 static void poly_denom_not_constant(evalue
**pp
, Value
*d
)
207 while (value_zero_p(p
->d
)) {
208 assert(p
->x
.p
->type
== polynomial
);
209 assert(p
->x
.p
->size
== 2);
210 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
211 value_lcm(*d
, p
->x
.p
->arr
[1].d
, d
);
217 static void poly_denom(evalue
*p
, Value
*d
)
219 poly_denom_not_constant(&p
, d
);
220 value_lcm(*d
, p
->d
, d
);
223 #define EVALUE_IS_ONE(ev) (value_one_p((ev).d) && value_one_p((ev).x.n))
225 static void realloc_substitution(struct subst
*s
, int d
)
227 struct fixed_param
*n
;
230 for (i
= 0; i
< s
->n
; ++i
)
237 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
243 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
246 /* May have been reduced already */
247 if (value_notzero_p(m
->d
))
250 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
251 assert(m
->x
.p
->size
== 3);
253 /* fractional was inverted during reduction
254 * invert it back and move constant in
256 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
257 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
258 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
259 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
260 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
261 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
262 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
263 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
264 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
265 value_set_si(m
->x
.p
->arr
[1].d
, 1);
268 /* Oops. Nested identical relations. */
269 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
272 if (s
->n
>= s
->max
) {
273 int d
= relations_depth(r
);
274 realloc_substitution(s
, d
);
278 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
279 assert(p
->x
.p
->size
== 2);
282 assert(value_pos_p(f
->x
.n
));
284 value_init(s
->fixed
[s
->n
].m
);
285 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
286 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
287 value_init(s
->fixed
[s
->n
].d
);
288 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
289 value_init(s
->fixed
[s
->n
].s
.d
);
290 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
296 static int type_offset(enode
*p
)
298 return p
->type
== fractional
? 1 :
299 p
->type
== flooring
? 1 : 0;
302 static void reorder_terms(enode
*p
, evalue
*v
)
305 int offset
= type_offset(p
);
307 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
309 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
310 free_evalue_refs(&(p
->arr
[i
]));
316 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
322 if (value_notzero_p(e
->d
)) {
324 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
325 return; /* a rational number, its already reduced */
329 return; /* hum... an overflow probably occured */
331 /* First reduce the components of p */
332 add
= p
->type
== relation
;
333 for (i
=0; i
<p
->size
; i
++) {
335 add
= add_modulo_substitution(s
, e
);
337 if (i
== 0 && p
->type
==fractional
)
338 _reduce_evalue(&p
->arr
[i
], s
, 1);
340 _reduce_evalue(&p
->arr
[i
], s
, fract
);
342 if (add
&& i
== p
->size
-1) {
344 value_clear(s
->fixed
[s
->n
].m
);
345 value_clear(s
->fixed
[s
->n
].d
);
346 free_evalue_refs(&s
->fixed
[s
->n
].s
);
347 } else if (add
&& i
== 1)
348 s
->fixed
[s
->n
-1].pos
*= -1;
351 if (p
->type
==periodic
) {
353 /* Try to reduce the period */
354 for (i
=1; i
<=(p
->size
)/2; i
++) {
355 if ((p
->size
% i
)==0) {
357 /* Can we reduce the size to i ? */
359 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
360 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
363 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
367 you_lose
: /* OK, lets not do it */
372 /* Try to reduce its strength */
375 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
379 else if (p
->type
==polynomial
) {
380 for (k
= 0; s
&& k
< s
->n
; ++k
) {
381 if (s
->fixed
[k
].pos
== p
->pos
) {
382 int divide
= value_notone_p(s
->fixed
[k
].d
);
385 if (value_notzero_p(s
->fixed
[k
].m
)) {
388 assert(p
->size
== 2);
389 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
391 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
398 value_assign(d
.d
, s
->fixed
[k
].d
);
400 if (value_notzero_p(s
->fixed
[k
].m
))
401 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
403 value_set_si(d
.x
.n
, 1);
406 for (i
=p
->size
-1;i
>=1;i
--) {
407 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
409 emul(&d
, &p
->arr
[i
]);
410 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
411 free_evalue_refs(&(p
->arr
[i
]));
414 _reduce_evalue(&p
->arr
[0], s
, fract
);
417 free_evalue_refs(&d
);
423 /* Try to reduce the degree */
424 for (i
=p
->size
-1;i
>=1;i
--) {
425 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
427 /* Zero coefficient */
428 free_evalue_refs(&(p
->arr
[i
]));
433 /* Try to reduce its strength */
436 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
440 else if (p
->type
==fractional
) {
444 if (value_notzero_p(p
->arr
[0].d
)) {
446 value_assign(v
.d
, p
->arr
[0].d
);
448 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
453 evalue
*pp
= &p
->arr
[0];
454 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
455 assert(pp
->x
.p
->size
== 2);
457 /* search for exact duplicate among the modulo inequalities */
459 f
= &pp
->x
.p
->arr
[1];
460 for (k
= 0; s
&& k
< s
->n
; ++k
) {
461 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
462 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
463 value_eq(s
->fixed
[k
].m
, f
->d
) &&
464 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
471 /* replace { E/m } by { (E-1)/m } + 1/m */
476 evalue_set_si(&extra
, 1, 1);
477 value_assign(extra
.d
, g
);
478 eadd(&extra
, &v
.x
.p
->arr
[1]);
479 free_evalue_refs(&extra
);
481 /* We've been going in circles; stop now */
482 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
483 free_evalue_refs(&v
);
485 evalue_set_si(&v
, 0, 1);
490 value_set_si(v
.d
, 0);
491 v
.x
.p
= new_enode(fractional
, 3, -1);
492 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
493 value_assign(v
.x
.p
->arr
[1].d
, g
);
494 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
495 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
498 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
501 value_division(f
->d
, g
, f
->d
);
502 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
503 value_assign(f
->d
, g
);
504 value_decrement(f
->x
.n
, f
->x
.n
);
505 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
507 Gcd(f
->d
, f
->x
.n
, &g
);
508 value_division(f
->d
, f
->d
, g
);
509 value_division(f
->x
.n
, f
->x
.n
, g
);
518 /* reduction may have made this fractional arg smaller */
519 i
= reorder
? p
->size
: 1;
520 for ( ; i
< p
->size
; ++i
)
521 if (value_zero_p(p
->arr
[i
].d
) &&
522 p
->arr
[i
].x
.p
->type
== fractional
&&
523 !mod_term_smaller(e
, &p
->arr
[i
]))
527 value_set_si(v
.d
, 0);
528 v
.x
.p
= new_enode(fractional
, 3, -1);
529 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
530 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
531 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
541 evalue
*pp
= &p
->arr
[0];
542 poly_denom_not_constant(&pp
, &m
);
543 mpz_fdiv_r(r
, m
, pp
->d
);
544 if (value_notzero_p(r
)) {
546 value_set_si(v
.d
, 0);
547 v
.x
.p
= new_enode(fractional
, 3, -1);
549 value_multiply(r
, m
, pp
->x
.n
);
550 value_multiply(v
.x
.p
->arr
[1].d
, m
, pp
->d
);
551 value_init(v
.x
.p
->arr
[1].x
.n
);
552 mpz_fdiv_r(v
.x
.p
->arr
[1].x
.n
, r
, pp
->d
);
553 mpz_fdiv_q(r
, r
, pp
->d
);
555 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
556 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
558 while (value_zero_p(pp
->d
))
559 pp
= &pp
->x
.p
->arr
[0];
561 value_assign(pp
->d
, m
);
562 value_assign(pp
->x
.n
, r
);
564 Gcd(pp
->d
, pp
->x
.n
, &r
);
565 value_division(pp
->d
, pp
->d
, r
);
566 value_division(pp
->x
.n
, pp
->x
.n
, r
);
579 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
580 pp
= &pp
->x
.p
->arr
[0]) {
581 f
= &pp
->x
.p
->arr
[1];
582 assert(value_pos_p(f
->d
));
583 mpz_mul_ui(twice
, f
->x
.n
, 2);
584 if (value_lt(twice
, f
->d
))
586 if (value_eq(twice
, f
->d
))
594 value_set_si(v
.d
, 0);
595 v
.x
.p
= new_enode(fractional
, 3, -1);
596 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
597 poly_denom(&p
->arr
[0], &twice
);
598 value_assign(v
.x
.p
->arr
[1].d
, twice
);
599 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
600 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
601 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
603 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
604 pp
= &pp
->x
.p
->arr
[0]) {
605 f
= &pp
->x
.p
->arr
[1];
606 value_oppose(f
->x
.n
, f
->x
.n
);
607 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
609 value_division(pp
->d
, twice
, pp
->d
);
610 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
611 value_assign(pp
->d
, twice
);
612 value_oppose(pp
->x
.n
, pp
->x
.n
);
613 value_decrement(pp
->x
.n
, pp
->x
.n
);
614 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
624 reorder_terms(p
, &v
);
625 _reduce_evalue(&p
->arr
[1], s
, fract
);
628 /* Try to reduce the degree */
629 for (i
=p
->size
-1;i
>=2;i
--) {
630 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
632 /* Zero coefficient */
633 free_evalue_refs(&(p
->arr
[i
]));
638 /* Try to reduce its strength */
641 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
642 free_evalue_refs(&(p
->arr
[0]));
646 else if (p
->type
== flooring
) {
647 /* Try to reduce the degree */
648 for (i
=p
->size
-1;i
>=2;i
--) {
649 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
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
== relation
) {
666 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
667 free_evalue_refs(&(p
->arr
[2]));
668 free_evalue_refs(&(p
->arr
[0]));
675 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
676 free_evalue_refs(&(p
->arr
[2]));
679 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
680 free_evalue_refs(&(p
->arr
[1]));
681 free_evalue_refs(&(p
->arr
[0]));
682 evalue_set_si(e
, 0, 1);
689 /* Relation was reduced by means of an identical
690 * inequality => remove
692 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
695 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
696 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
698 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
700 free_evalue_refs(&(p
->arr
[2]));
704 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
706 evalue_set_si(e
, 0, 1);
707 free_evalue_refs(&(p
->arr
[1]));
709 free_evalue_refs(&(p
->arr
[0]));
715 } /* reduce_evalue */
717 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
722 for (k
= 0; k
< dim
; ++k
)
723 if (value_notzero_p(row
[k
+1]))
726 Vector_Normalize_Positive(row
+1, dim
+1, k
);
727 assert(s
->n
< s
->max
);
728 value_init(s
->fixed
[s
->n
].d
);
729 value_init(s
->fixed
[s
->n
].m
);
730 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
731 s
->fixed
[s
->n
].pos
= k
+1;
732 value_set_si(s
->fixed
[s
->n
].m
, 0);
733 r
= &s
->fixed
[s
->n
].s
;
735 for (l
= k
+1; l
< dim
; ++l
)
736 if (value_notzero_p(row
[l
+1])) {
737 value_set_si(r
->d
, 0);
738 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
739 value_init(r
->x
.p
->arr
[1].x
.n
);
740 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
741 value_set_si(r
->x
.p
->arr
[1].d
, 1);
745 value_oppose(r
->x
.n
, row
[dim
+1]);
746 value_set_si(r
->d
, 1);
750 void reduce_evalue (evalue
*e
) {
751 struct subst s
= { NULL
, 0, 0 };
753 if (value_notzero_p(e
->d
))
754 return; /* a rational number, its already reduced */
756 if (e
->x
.p
->type
== partition
) {
759 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
760 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
762 /* This shouldn't really happen;
763 * Empty domains should not be added.
770 D
= DomainConvex(D
, 0);
771 if (!D
->next
&& D
->NbEq
) {
775 realloc_substitution(&s
, dim
);
777 int d
= relations_depth(&e
->x
.p
->arr
[2*i
+1]);
779 NALLOC(s
.fixed
, s
.max
);
782 for (j
= 0; j
< D
->NbEq
; ++j
)
783 add_substitution(&s
, D
->Constraint
[j
], dim
);
785 if (D
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
787 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
788 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
790 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
791 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
792 value_clear(e
->x
.p
->arr
[2*i
].d
);
794 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
795 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
800 for (j
= 0; j
< s
.n
; ++j
) {
801 value_clear(s
.fixed
[j
].d
);
802 value_clear(s
.fixed
[j
].m
);
803 free_evalue_refs(&s
.fixed
[j
].s
);
807 if (e
->x
.p
->size
== 0) {
809 evalue_set_si(e
, 0, 1);
812 _reduce_evalue(e
, &s
, 0);
817 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
819 if(value_notzero_p(e
->d
)) {
820 if(value_notone_p(e
->d
)) {
821 value_print(DST
,VALUE_FMT
,e
->x
.n
);
823 value_print(DST
,VALUE_FMT
,e
->d
);
826 value_print(DST
,VALUE_FMT
,e
->x
.n
);
830 print_enode(DST
,e
->x
.p
,pname
);
834 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
839 fprintf(DST
, "NULL");
845 for (i
=0; i
<p
->size
; i
++) {
846 print_evalue(DST
, &p
->arr
[i
], pname
);
850 fprintf(DST
, " }\n");
854 for (i
=p
->size
-1; i
>=0; i
--) {
855 print_evalue(DST
, &p
->arr
[i
], pname
);
856 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
858 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
860 fprintf(DST
, " )\n");
864 for (i
=0; i
<p
->size
; i
++) {
865 print_evalue(DST
, &p
->arr
[i
], pname
);
866 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
868 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
873 for (i
=p
->size
-1; i
>=1; i
--) {
874 print_evalue(DST
, &p
->arr
[i
], pname
);
877 fprintf(DST
, p
->type
== flooring
? "[" : "{");
878 print_evalue(DST
, &p
->arr
[0], pname
);
879 fprintf(DST
, p
->type
== flooring
? "]" : "}");
881 fprintf(DST
, "^%d + ", i
-1);
886 fprintf(DST
, " )\n");
890 print_evalue(DST
, &p
->arr
[0], pname
);
891 fprintf(DST
, "= 0 ] * \n");
892 print_evalue(DST
, &p
->arr
[1], pname
);
894 fprintf(DST
, " +\n [ ");
895 print_evalue(DST
, &p
->arr
[0], pname
);
896 fprintf(DST
, "!= 0 ] * \n");
897 print_evalue(DST
, &p
->arr
[2], pname
);
901 char **names
= pname
;
902 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
903 if (p
->pos
< maxdim
) {
904 NALLOC(names
, maxdim
);
905 for (i
= 0; i
< p
->pos
; ++i
)
907 for ( ; i
< maxdim
; ++i
) {
908 NALLOC(names
[i
], 10);
909 snprintf(names
[i
], 10, "_p%d", i
);
913 for (i
=0; i
<p
->size
/2; i
++) {
914 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
915 print_evalue(DST
, &p
->arr
[2*i
+1], names
);
918 if (p
->pos
< maxdim
) {
919 for (i
= p
->pos
; i
< maxdim
; ++i
)
932 static void eadd_rev(evalue
*e1
, evalue
*res
)
936 evalue_copy(&ev
, e1
);
938 free_evalue_refs(res
);
942 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
946 evalue_copy(&ev
, e1
);
947 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
948 free_evalue_refs(res
);
952 struct section
{ Polyhedron
* D
; evalue E
; };
954 void eadd_partitions (evalue
*e1
,evalue
*res
)
959 s
= (struct section
*)
960 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
961 sizeof(struct section
));
963 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
964 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
965 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
968 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
969 assert(res
->x
.p
->size
>= 2);
970 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
971 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
973 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
975 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
984 value_init(s
[n
].E
.d
);
985 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
989 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
990 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
991 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
993 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
994 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1000 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1001 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1003 value_init(s
[n
].E
.d
);
1004 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1005 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1010 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1014 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1017 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1018 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1019 value_clear(res
->x
.p
->arr
[2*i
].d
);
1024 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1025 for (j
= 0; j
< n
; ++j
) {
1026 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1027 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1028 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1029 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1035 static void explicit_complement(evalue
*res
)
1037 enode
*rel
= new_enode(relation
, 3, 0);
1039 value_clear(rel
->arr
[0].d
);
1040 rel
->arr
[0] = res
->x
.p
->arr
[0];
1041 value_clear(rel
->arr
[1].d
);
1042 rel
->arr
[1] = res
->x
.p
->arr
[1];
1043 value_set_si(rel
->arr
[2].d
, 1);
1044 value_init(rel
->arr
[2].x
.n
);
1045 value_set_si(rel
->arr
[2].x
.n
, 0);
1050 void eadd(evalue
*e1
,evalue
*res
) {
1053 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1054 /* Add two rational numbers */
1060 value_multiply(m1
,e1
->x
.n
,res
->d
);
1061 value_multiply(m2
,res
->x
.n
,e1
->d
);
1062 value_addto(res
->x
.n
,m1
,m2
);
1063 value_multiply(res
->d
,e1
->d
,res
->d
);
1064 Gcd(res
->x
.n
,res
->d
,&g
);
1065 if (value_notone_p(g
)) {
1066 value_division(res
->d
,res
->d
,g
);
1067 value_division(res
->x
.n
,res
->x
.n
,g
);
1069 value_clear(g
); value_clear(m1
); value_clear(m2
);
1072 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1073 switch (res
->x
.p
->type
) {
1075 /* Add the constant to the constant term of a polynomial*/
1076 eadd(e1
, &res
->x
.p
->arr
[0]);
1079 /* Add the constant to all elements of a periodic number */
1080 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1081 eadd(e1
, &res
->x
.p
->arr
[i
]);
1085 fprintf(stderr
, "eadd: cannot add const with vector\n");
1089 eadd(e1
, &res
->x
.p
->arr
[1]);
1092 assert(EVALUE_IS_ZERO(*e1
));
1093 break; /* Do nothing */
1095 /* Create (zero) complement if needed */
1096 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1097 explicit_complement(res
);
1098 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1099 eadd(e1
, &res
->x
.p
->arr
[i
]);
1105 /* add polynomial or periodic to constant
1106 * you have to exchange e1 and res, before doing addition */
1108 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1112 else { // ((e1->d==0) && (res->d==0))
1113 assert(!((e1
->x
.p
->type
== partition
) ^
1114 (res
->x
.p
->type
== partition
)));
1115 if (e1
->x
.p
->type
== partition
) {
1116 eadd_partitions(e1
, res
);
1119 if (e1
->x
.p
->type
== relation
&&
1120 (res
->x
.p
->type
!= relation
||
1121 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1125 if (res
->x
.p
->type
== relation
) {
1126 if (e1
->x
.p
->type
== relation
&&
1127 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1128 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1129 explicit_complement(res
);
1130 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1131 explicit_complement(e1
);
1132 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1133 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1136 if (res
->x
.p
->size
< 3)
1137 explicit_complement(res
);
1138 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1139 eadd(e1
, &res
->x
.p
->arr
[i
]);
1142 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1143 /* adding to evalues of different type. two cases are possible
1144 * res is periodic and e1 is polynomial, you have to exchange
1145 * e1 and res then to add e1 to the constant term of res */
1146 if (e1
->x
.p
->type
== polynomial
) {
1147 eadd_rev_cst(e1
, res
);
1149 else if (res
->x
.p
->type
== polynomial
) {
1150 /* res is polynomial and e1 is periodic,
1151 add e1 to the constant term of res */
1153 eadd(e1
,&res
->x
.p
->arr
[0]);
1159 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1160 ((res
->x
.p
->type
== fractional
||
1161 res
->x
.p
->type
== flooring
) &&
1162 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1163 /* adding evalues of different position (i.e function of different unknowns
1164 * to case are possible */
1166 switch (res
->x
.p
->type
) {
1169 if(mod_term_smaller(res
, e1
))
1170 eadd(e1
,&res
->x
.p
->arr
[1]);
1172 eadd_rev_cst(e1
, res
);
1174 case polynomial
: // res and e1 are polynomials
1175 // add e1 to the constant term of res
1177 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1178 eadd(e1
,&res
->x
.p
->arr
[0]);
1180 eadd_rev_cst(e1
, res
);
1181 // value_clear(g); value_clear(m1); value_clear(m2);
1183 case periodic
: // res and e1 are pointers to periodic numbers
1184 //add e1 to all elements of res
1186 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1187 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1188 eadd(e1
,&res
->x
.p
->arr
[i
]);
1199 //same type , same pos and same size
1200 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1201 // add any element in e1 to the corresponding element in res
1202 i
= type_offset(res
->x
.p
);
1204 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1205 for (; i
<res
->x
.p
->size
; i
++) {
1206 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1211 /* Sizes are different */
1212 switch(res
->x
.p
->type
) {
1216 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1217 /* new enode and add res to that new node. If you do not do */
1218 /* that, you lose the the upper weight part of e1 ! */
1220 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1223 i
= type_offset(res
->x
.p
);
1225 assert(eequal(&e1
->x
.p
->arr
[0],
1226 &res
->x
.p
->arr
[0]));
1227 for (; i
<e1
->x
.p
->size
; i
++) {
1228 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1235 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1238 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1239 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1240 to add periodicaly elements of e1 to elements of ne, and finaly to
1245 value_init(ex
); value_init(ey
);value_init(ep
);
1248 value_set_si(ex
,e1
->x
.p
->size
);
1249 value_set_si(ey
,res
->x
.p
->size
);
1250 value_assign (ep
,*Lcm(ex
,ey
));
1251 p
=(int)mpz_get_si(ep
);
1252 ne
= (evalue
*) malloc (sizeof(evalue
));
1254 value_set_si( ne
->d
,0);
1256 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1258 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1261 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1264 value_assign(res
->d
, ne
->d
);
1270 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1279 static void emul_rev (evalue
*e1
, evalue
*res
)
1283 evalue_copy(&ev
, e1
);
1285 free_evalue_refs(res
);
1289 static void emul_poly (evalue
*e1
, evalue
*res
)
1291 int i
, j
, o
= type_offset(res
->x
.p
);
1293 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1295 value_set_si(tmp
.d
,0);
1296 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1298 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1299 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1300 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1301 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1304 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1305 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1306 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1309 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1310 emul(&res
->x
.p
->arr
[i
], &ev
);
1311 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1312 free_evalue_refs(&ev
);
1314 free_evalue_refs(res
);
1318 void emul_partitions (evalue
*e1
,evalue
*res
)
1323 s
= (struct section
*)
1324 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1325 sizeof(struct section
));
1327 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1328 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1329 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1332 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1333 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1334 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1335 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1341 /* This code is only needed because the partitions
1342 are not true partitions.
1344 for (k
= 0; k
< n
; ++k
) {
1345 if (DomainIncludes(s
[k
].D
, d
))
1347 if (DomainIncludes(d
, s
[k
].D
)) {
1348 Domain_Free(s
[k
].D
);
1349 free_evalue_refs(&s
[k
].E
);
1360 value_init(s
[n
].E
.d
);
1361 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1362 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1366 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1367 value_clear(res
->x
.p
->arr
[2*i
].d
);
1368 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1373 evalue_set_si(res
, 0, 1);
1375 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1376 for (j
= 0; j
< n
; ++j
) {
1377 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1378 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1379 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1380 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1387 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1389 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1390 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1391 * evalues is not treated here */
1393 void emul (evalue
*e1
, evalue
*res
){
1396 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1397 fprintf(stderr
, "emul: do not proced on evector type !\n");
1401 if (EVALUE_IS_ZERO(*res
))
1404 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1405 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1406 emul_partitions(e1
, res
);
1409 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1410 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1411 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1413 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1414 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1415 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1416 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1417 explicit_complement(res
);
1418 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1419 explicit_complement(e1
);
1420 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1421 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1424 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1425 emul(e1
, &res
->x
.p
->arr
[i
]);
1427 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1428 switch(e1
->x
.p
->type
) {
1430 switch(res
->x
.p
->type
) {
1432 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1433 /* Product of two polynomials of the same variable */
1438 /* Product of two polynomials of different variables */
1440 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1441 for( i
=0; i
<res
->x
.p
->size
; i
++)
1442 emul(e1
, &res
->x
.p
->arr
[i
]);
1451 /* Product of a polynomial and a periodic or fractional */
1458 switch(res
->x
.p
->type
) {
1460 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1461 /* Product of two periodics of the same parameter and period */
1463 for(i
=0; i
<res
->x
.p
->size
;i
++)
1464 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1469 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1470 /* Product of two periodics of the same parameter and different periods */
1474 value_init(x
); value_init(y
);value_init(z
);
1477 value_set_si(x
,e1
->x
.p
->size
);
1478 value_set_si(y
,res
->x
.p
->size
);
1479 value_assign (z
,*Lcm(x
,y
));
1480 lcm
=(int)mpz_get_si(z
);
1481 newp
= (evalue
*) malloc (sizeof(evalue
));
1482 value_init(newp
->d
);
1483 value_set_si( newp
->d
,0);
1484 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1485 for(i
=0;i
<lcm
;i
++) {
1486 evalue_copy(&newp
->x
.p
->arr
[i
],
1487 &res
->x
.p
->arr
[i
%iy
]);
1490 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1492 value_assign(res
->d
,newp
->d
);
1495 value_clear(x
); value_clear(y
);value_clear(z
);
1499 /* Product of two periodics of different parameters */
1501 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1502 for(i
=0; i
<res
->x
.p
->size
; i
++)
1503 emul(e1
, &(res
->x
.p
->arr
[i
]));
1511 /* Product of a periodic and a polynomial */
1513 for(i
=0; i
<res
->x
.p
->size
; i
++)
1514 emul(e1
, &(res
->x
.p
->arr
[i
]));
1521 switch(res
->x
.p
->type
) {
1523 for(i
=0; i
<res
->x
.p
->size
; i
++)
1524 emul(e1
, &(res
->x
.p
->arr
[i
]));
1531 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1532 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1533 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1536 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1537 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1542 value_set_si(d
.x
.n
, 1);
1543 /* { x }^2 == { x }/2 */
1544 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1545 assert(e1
->x
.p
->size
== 3);
1546 assert(res
->x
.p
->size
== 3);
1548 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1550 eadd(&res
->x
.p
->arr
[1], &tmp
);
1551 emul(&e1
->x
.p
->arr
[2], &tmp
);
1552 emul(&e1
->x
.p
->arr
[1], res
);
1553 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1554 free_evalue_refs(&tmp
);
1559 if(mod_term_smaller(res
, e1
))
1560 for(i
=1; i
<res
->x
.p
->size
; i
++)
1561 emul(e1
, &(res
->x
.p
->arr
[i
]));
1576 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1577 /* Product of two rational numbers */
1581 value_multiply(res
->d
,e1
->d
,res
->d
);
1582 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1583 Gcd(res
->x
.n
, res
->d
,&g
);
1584 if (value_notone_p(g
)) {
1585 value_division(res
->d
,res
->d
,g
);
1586 value_division(res
->x
.n
,res
->x
.n
,g
);
1592 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1593 /* Product of an expression (polynomial or peririodic) and a rational number */
1599 /* Product of a rationel number and an expression (polynomial or peririodic) */
1601 i
= type_offset(res
->x
.p
);
1602 for (; i
<res
->x
.p
->size
; i
++)
1603 emul(e1
, &res
->x
.p
->arr
[i
]);
1613 /* Frees mask content ! */
1614 void emask(evalue
*mask
, evalue
*res
) {
1621 if (EVALUE_IS_ZERO(*res
)) {
1622 free_evalue_refs(mask
);
1626 assert(value_zero_p(mask
->d
));
1627 assert(mask
->x
.p
->type
== partition
);
1628 assert(value_zero_p(res
->d
));
1629 assert(res
->x
.p
->type
== partition
);
1630 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1631 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1632 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1633 pos
= res
->x
.p
->pos
;
1635 s
= (struct section
*)
1636 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1637 sizeof(struct section
));
1641 evalue_set_si(&mone
, -1, 1);
1644 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1645 assert(mask
->x
.p
->size
>= 2);
1646 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1647 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1649 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1651 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1660 value_init(s
[n
].E
.d
);
1661 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1665 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1666 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1669 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1670 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1671 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1672 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1674 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1675 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1681 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1682 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1684 value_init(s
[n
].E
.d
);
1685 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1686 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1692 /* Just ignore; this may have been previously masked off */
1694 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1698 free_evalue_refs(&mone
);
1699 free_evalue_refs(mask
);
1700 free_evalue_refs(res
);
1703 evalue_set_si(res
, 0, 1);
1705 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1706 for (j
= 0; j
< n
; ++j
) {
1707 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1708 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1709 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1716 void evalue_copy(evalue
*dst
, evalue
*src
)
1718 value_assign(dst
->d
, src
->d
);
1719 if(value_notzero_p(src
->d
)) {
1720 value_init(dst
->x
.n
);
1721 value_assign(dst
->x
.n
, src
->x
.n
);
1723 dst
->x
.p
= ecopy(src
->x
.p
);
1726 enode
*new_enode(enode_type type
,int size
,int pos
) {
1732 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1735 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1739 for(i
=0; i
<size
; i
++) {
1740 value_init(res
->arr
[i
].d
);
1741 value_set_si(res
->arr
[i
].d
,0);
1742 res
->arr
[i
].x
.p
= 0;
1747 enode
*ecopy(enode
*e
) {
1752 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1753 for(i
=0;i
<e
->size
;++i
) {
1754 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1755 if(value_zero_p(res
->arr
[i
].d
))
1756 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1757 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1758 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1760 value_init(res
->arr
[i
].x
.n
);
1761 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1767 int ecmp(const evalue
*e1
, const evalue
*e2
)
1773 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1777 value_multiply(m
, e1
->x
.n
, e2
->d
);
1778 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1780 if (value_lt(m
, m2
))
1782 else if (value_gt(m
, m2
))
1792 if (value_notzero_p(e1
->d
))
1794 if (value_notzero_p(e2
->d
))
1800 if (p1
->type
!= p2
->type
)
1801 return p1
->type
- p2
->type
;
1802 if (p1
->pos
!= p2
->pos
)
1803 return p1
->pos
- p2
->pos
;
1804 if (p1
->size
!= p2
->size
)
1805 return p1
->size
- p2
->size
;
1807 for (i
= p1
->size
-1; i
>= 0; --i
)
1808 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1814 int eequal(evalue
*e1
,evalue
*e2
) {
1819 if (value_ne(e1
->d
,e2
->d
))
1822 /* e1->d == e2->d */
1823 if (value_notzero_p(e1
->d
)) {
1824 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1827 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1831 /* e1->d == e2->d == 0 */
1834 if (p1
->type
!= p2
->type
) return 0;
1835 if (p1
->size
!= p2
->size
) return 0;
1836 if (p1
->pos
!= p2
->pos
) return 0;
1837 for (i
=0; i
<p1
->size
; i
++)
1838 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1843 void free_evalue_refs(evalue
*e
) {
1848 if (EVALUE_IS_DOMAIN(*e
)) {
1849 Domain_Free(EVALUE_DOMAIN(*e
));
1852 } else if (value_pos_p(e
->d
)) {
1854 /* 'e' stores a constant */
1856 value_clear(e
->x
.n
);
1859 assert(value_zero_p(e
->d
));
1862 if (!p
) return; /* null pointer */
1863 for (i
=0; i
<p
->size
; i
++) {
1864 free_evalue_refs(&(p
->arr
[i
]));
1868 } /* free_evalue_refs */
1870 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1871 Vector
* val
, evalue
*res
)
1873 unsigned nparam
= periods
->Size
;
1876 double d
= compute_evalue(e
, val
->p
);
1877 d
*= VALUE_TO_DOUBLE(m
);
1882 value_assign(res
->d
, m
);
1883 value_init(res
->x
.n
);
1884 value_set_double(res
->x
.n
, d
);
1885 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1888 if (value_one_p(periods
->p
[p
]))
1889 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1894 value_assign(tmp
, periods
->p
[p
]);
1895 value_set_si(res
->d
, 0);
1896 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1898 value_decrement(tmp
, tmp
);
1899 value_assign(val
->p
[p
], tmp
);
1900 mod2table_r(e
, periods
, m
, p
+1, val
,
1901 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1902 } while (value_pos_p(tmp
));
1908 static void rel2table(evalue
*e
, int zero
)
1910 if (value_pos_p(e
->d
)) {
1911 if (value_zero_p(e
->x
.n
) == zero
)
1912 value_set_si(e
->x
.n
, 1);
1914 value_set_si(e
->x
.n
, 0);
1915 value_set_si(e
->d
, 1);
1918 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1919 rel2table(&e
->x
.p
->arr
[i
], zero
);
1923 void evalue_mod2table(evalue
*e
, int nparam
)
1928 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1931 for (i
=0; i
<p
->size
; i
++) {
1932 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1934 if (p
->type
== relation
) {
1939 evalue_copy(©
, &p
->arr
[0]);
1941 rel2table(&p
->arr
[0], 1);
1942 emul(&p
->arr
[0], &p
->arr
[1]);
1944 rel2table(©
, 0);
1945 emul(©
, &p
->arr
[2]);
1946 eadd(&p
->arr
[2], &p
->arr
[1]);
1947 free_evalue_refs(&p
->arr
[2]);
1948 free_evalue_refs(©
);
1950 free_evalue_refs(&p
->arr
[0]);
1954 } else if (p
->type
== fractional
) {
1955 Vector
*periods
= Vector_Alloc(nparam
);
1956 Vector
*val
= Vector_Alloc(nparam
);
1962 value_set_si(tmp
, 1);
1963 Vector_Set(periods
->p
, 1, nparam
);
1964 Vector_Set(val
->p
, 0, nparam
);
1965 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1968 assert(p
->type
== polynomial
);
1969 assert(p
->size
== 2);
1970 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
1971 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
1973 value_lcm(tmp
, ev
->d
, &tmp
);
1975 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1978 evalue_set_si(&res
, 0, 1);
1979 /* Compute the polynomial using Horner's rule */
1980 for (i
=p
->size
-1;i
>1;i
--) {
1981 eadd(&p
->arr
[i
], &res
);
1984 eadd(&p
->arr
[1], &res
);
1986 free_evalue_refs(e
);
1987 free_evalue_refs(&EP
);
1992 Vector_Free(periods
);
1994 } /* evalue_mod2table */
1996 /********************************************************/
1997 /* function in domain */
1998 /* check if the parameters in list_args */
1999 /* verifies the constraints of Domain P */
2000 /********************************************************/
2001 int in_domain(Polyhedron
*P
, Value
*list_args
) {
2004 Value v
; /* value of the constraint of a row when
2005 parameters are instanciated*/
2011 /*P->Constraint constraint matrice of polyhedron P*/
2012 for(row
=0;row
<P
->NbConstraints
;row
++) {
2013 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2014 for(col
=1;col
<P
->Dimension
+1;col
++) {
2015 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
2016 value_addto(v
,v
,tmp
);
2018 if (value_notzero_p(P
->Constraint
[row
][0])) {
2020 /*if v is not >=0 then this constraint is not respected */
2021 if (value_neg_p(v
)) {
2025 return P
->next
? in_domain(P
->next
, list_args
) : 0;
2030 /*if v is not = 0 then this constraint is not respected */
2031 if (value_notzero_p(v
))
2036 /*if not return before this point => all
2037 the constraints are respected */
2043 /****************************************************/
2044 /* function compute enode */
2045 /* compute the value of enode p with parameters */
2046 /* list "list_args */
2047 /* compute the polynomial or the periodic */
2048 /****************************************************/
2050 static double compute_enode(enode
*p
, Value
*list_args
) {
2062 if (p
->type
== polynomial
) {
2064 value_assign(param
,list_args
[p
->pos
-1]);
2066 /* Compute the polynomial using Horner's rule */
2067 for (i
=p
->size
-1;i
>0;i
--) {
2068 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2069 res
*=VALUE_TO_DOUBLE(param
);
2071 res
+=compute_evalue(&p
->arr
[0],list_args
);
2073 else if (p
->type
== fractional
) {
2074 double d
= compute_evalue(&p
->arr
[0], list_args
);
2075 d
-= floor(d
+1e-10);
2077 /* Compute the polynomial using Horner's rule */
2078 for (i
=p
->size
-1;i
>1;i
--) {
2079 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2082 res
+=compute_evalue(&p
->arr
[1],list_args
);
2084 else if (p
->type
== flooring
) {
2085 double d
= compute_evalue(&p
->arr
[0], list_args
);
2088 /* Compute the polynomial using Horner's rule */
2089 for (i
=p
->size
-1;i
>1;i
--) {
2090 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2093 res
+=compute_evalue(&p
->arr
[1],list_args
);
2095 else if (p
->type
== periodic
) {
2096 value_assign(m
,list_args
[p
->pos
-1]);
2098 /* Choose the right element of the periodic */
2099 value_set_si(param
,p
->size
);
2100 value_pmodulus(m
,m
,param
);
2101 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2103 else if (p
->type
== relation
) {
2104 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2105 res
= compute_evalue(&p
->arr
[1], list_args
);
2106 else if (p
->size
> 2)
2107 res
= compute_evalue(&p
->arr
[2], list_args
);
2109 else if (p
->type
== partition
) {
2110 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2111 Value
*vals
= list_args
;
2114 for (i
= 0; i
< dim
; ++i
) {
2115 value_init(vals
[i
]);
2117 value_assign(vals
[i
], list_args
[i
]);
2120 for (i
= 0; i
< p
->size
/2; ++i
)
2121 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2122 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2126 for (i
= 0; i
< dim
; ++i
)
2127 value_clear(vals
[i
]);
2136 } /* compute_enode */
2138 /*************************************************/
2139 /* return the value of Ehrhart Polynomial */
2140 /* It returns a double, because since it is */
2141 /* a recursive function, some intermediate value */
2142 /* might not be integral */
2143 /*************************************************/
2145 double compute_evalue(evalue
*e
,Value
*list_args
) {
2149 if (value_notzero_p(e
->d
)) {
2150 if (value_notone_p(e
->d
))
2151 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2153 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2156 res
= compute_enode(e
->x
.p
,list_args
);
2158 } /* compute_evalue */
2161 /****************************************************/
2162 /* function compute_poly : */
2163 /* Check for the good validity domain */
2164 /* return the number of point in the Polyhedron */
2165 /* in allocated memory */
2166 /* Using the Ehrhart pseudo-polynomial */
2167 /****************************************************/
2168 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2171 /* double d; int i; */
2173 tmp
= (Value
*) malloc (sizeof(Value
));
2174 assert(tmp
!= NULL
);
2176 value_set_si(*tmp
,0);
2179 return(tmp
); /* no ehrhart polynomial */
2180 if(en
->ValidityDomain
) {
2181 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2182 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2187 return(tmp
); /* no Validity Domain */
2189 if(in_domain(en
->ValidityDomain
,list_args
)) {
2191 #ifdef EVAL_EHRHART_DEBUG
2192 Print_Domain(stdout
,en
->ValidityDomain
);
2193 print_evalue(stdout
,&en
->EP
);
2196 /* d = compute_evalue(&en->EP,list_args);
2198 printf("(double)%lf = %d\n", d, i ); */
2199 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2205 value_set_si(*tmp
,0);
2206 return(tmp
); /* no compatible domain with the arguments */
2207 } /* compute_poly */
2209 size_t value_size(Value v
) {
2210 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2211 * sizeof(v
[0]._mp_d
[0]);
2214 size_t domain_size(Polyhedron
*D
)
2217 size_t s
= sizeof(*D
);
2219 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2220 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2221 s
+= value_size(D
->Constraint
[i
][j
]);
2224 for (i = 0; i < D->NbRays; ++i)
2225 for (j = 0; j < D->Dimension+2; ++j)
2226 s += value_size(D->Ray[i][j]);
2229 return D
->next
? s
+domain_size(D
->next
) : s
;
2232 size_t enode_size(enode
*p
) {
2233 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2236 if (p
->type
== partition
)
2237 for (i
= 0; i
< p
->size
/2; ++i
) {
2238 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2239 s
+= evalue_size(&p
->arr
[2*i
+1]);
2242 for (i
= 0; i
< p
->size
; ++i
) {
2243 s
+= evalue_size(&p
->arr
[i
]);
2248 size_t evalue_size(evalue
*e
)
2250 size_t s
= sizeof(*e
);
2251 s
+= value_size(e
->d
);
2252 if (value_notzero_p(e
->d
))
2253 s
+= value_size(e
->x
.n
);
2255 s
+= enode_size(e
->x
.p
);
2259 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2261 evalue
*found
= NULL
;
2266 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2269 value_init(offset
.d
);
2270 value_init(offset
.x
.n
);
2271 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2272 value_lcm(m
, offset
.d
, &offset
.d
);
2273 value_set_si(offset
.x
.n
, 1);
2276 evalue_copy(©
, cst
);
2279 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2281 if (eequal(base
, &e
->x
.p
->arr
[0]))
2282 found
= &e
->x
.p
->arr
[0];
2284 value_set_si(offset
.x
.n
, -2);
2287 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2289 if (eequal(base
, &e
->x
.p
->arr
[0]))
2292 free_evalue_refs(cst
);
2293 free_evalue_refs(&offset
);
2296 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2297 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2302 static evalue
*find_relation_pair(evalue
*e
)
2305 evalue
*found
= NULL
;
2307 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2310 if (e
->x
.p
->type
== fractional
) {
2315 poly_denom(&e
->x
.p
->arr
[0], &m
);
2317 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2318 cst
= &cst
->x
.p
->arr
[0])
2321 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2322 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2327 i
= e
->x
.p
->type
== relation
;
2328 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2329 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2334 void evalue_mod2relation(evalue
*e
) {
2337 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2340 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2341 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2342 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2343 value_clear(e
->x
.p
->arr
[2*i
].d
);
2344 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2346 if (2*i
< e
->x
.p
->size
) {
2347 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2348 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2353 if (e
->x
.p
->size
== 0) {
2355 evalue_set_si(e
, 0, 1);
2361 while ((d
= find_relation_pair(e
)) != NULL
) {
2365 value_init(split
.d
);
2366 value_set_si(split
.d
, 0);
2367 split
.x
.p
= new_enode(relation
, 3, 0);
2368 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2369 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2371 ev
= &split
.x
.p
->arr
[0];
2372 value_set_si(ev
->d
, 0);
2373 ev
->x
.p
= new_enode(fractional
, 3, -1);
2374 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2375 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2376 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2382 free_evalue_refs(&split
);
2386 static int evalue_comp(const void * a
, const void * b
)
2388 const evalue
*e1
= *(const evalue
**)a
;
2389 const evalue
*e2
= *(const evalue
**)b
;
2390 return ecmp(e1
, e2
);
2393 void evalue_combine(evalue
*e
)
2400 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2403 NALLOC(evs
, e
->x
.p
->size
/2);
2404 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2405 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2406 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2407 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2408 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2409 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2410 value_clear(p
->arr
[2*k
].d
);
2411 value_clear(p
->arr
[2*k
+1].d
);
2412 p
->arr
[2*k
] = *(evs
[i
]-1);
2413 p
->arr
[2*k
+1] = *(evs
[i
]);
2416 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2419 value_clear((evs
[i
]-1)->d
);
2423 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2424 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2425 free_evalue_refs(evs
[i
]);
2429 for (i
= 2*k
; i
< p
->size
; ++i
)
2430 value_clear(p
->arr
[i
].d
);
2437 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2439 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2441 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2444 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2445 Polyhedron
*D
, *N
, **P
;
2448 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2455 if (D
->NbEq
<= H
->NbEq
) {
2461 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2462 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2463 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2464 reduce_evalue(&tmp
);
2465 if (value_notzero_p(tmp
.d
) ||
2466 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2469 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2470 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2473 free_evalue_refs(&tmp
);
2479 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2481 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2483 value_clear(e
->x
.p
->arr
[2*i
].d
);
2484 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2486 if (2*i
< e
->x
.p
->size
) {
2487 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2488 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2495 H
= DomainConvex(D
, 0);
2496 E
= DomainDifference(H
, D
, 0);
2498 D
= DomainDifference(H
, E
, 0);
2501 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2505 /* May change coefficients to become non-standard if fiddle is set
2506 * => reduce p afterwards to correct
2508 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2509 Matrix
**R
, int fiddle
)
2513 unsigned dim
= D
->Dimension
;
2514 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2519 assert(p
->type
== fractional
);
2521 value_set_si(T
->p
[1][dim
], 1);
2523 while (value_zero_p(pp
->d
)) {
2524 assert(pp
->x
.p
->type
== polynomial
);
2525 assert(pp
->x
.p
->size
== 2);
2526 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2527 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2528 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2529 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2530 value_substract(pp
->x
.p
->arr
[1].x
.n
,
2531 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2532 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2533 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2534 pp
= &pp
->x
.p
->arr
[0];
2536 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2537 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2538 I
= DomainImage(D
, T
, 0);
2539 H
= DomainConvex(I
, 0);
2548 static int reduce_in_domain(evalue
*e
, Polyhedron
*D
)
2558 if (value_notzero_p(e
->d
))
2563 if (p
->type
== relation
) {
2569 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2570 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2571 equal
= value_eq(min
, max
);
2572 mpz_cdiv_q(min
, min
, d
);
2573 mpz_fdiv_q(max
, max
, d
);
2575 if (bounded
&& value_gt(min
, max
)) {
2581 evalue_set_si(e
, 0, 1);
2584 free_evalue_refs(&(p
->arr
[1]));
2585 free_evalue_refs(&(p
->arr
[0]));
2591 return r
? r
: reduce_in_domain(e
, D
);
2592 } else if (bounded
&& equal
) {
2595 free_evalue_refs(&(p
->arr
[2]));
2598 free_evalue_refs(&(p
->arr
[0]));
2604 return reduce_in_domain(e
, D
);
2605 } else if (bounded
&& value_eq(min
, max
)) {
2606 /* zero for a single value */
2608 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2609 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2610 value_multiply(min
, min
, d
);
2611 value_substract(M
->p
[0][D
->Dimension
+1],
2612 M
->p
[0][D
->Dimension
+1], min
);
2613 E
= DomainAddConstraints(D
, M
, 0);
2619 r
= reduce_in_domain(&p
->arr
[1], E
);
2621 r
|= reduce_in_domain(&p
->arr
[2], D
);
2623 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2631 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2634 i
= p
->type
== relation
? 1 :
2635 p
->type
== fractional
? 1 : 0;
2636 for (; i
<p
->size
; i
++)
2637 r
|= reduce_in_domain(&p
->arr
[i
], D
);
2639 if (p
->type
!= fractional
) {
2640 if (r
&& p
->type
== polynomial
) {
2643 value_set_si(f
.d
, 0);
2644 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2645 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2646 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2647 reorder_terms(p
, &f
);
2658 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2660 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2661 mpz_fdiv_q(min
, min
, d
);
2662 mpz_fdiv_q(max
, max
, d
);
2663 value_substract(d
, max
, min
);
2665 if (bounded
&& value_eq(min
, max
)) {
2668 value_init(inc
.x
.n
);
2669 value_set_si(inc
.d
, 1);
2670 value_oppose(inc
.x
.n
, min
);
2671 eadd(&inc
, &p
->arr
[0]);
2672 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2676 free_evalue_refs(&inc
);
2678 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2685 value_set_si(rem
.d
, 0);
2686 rem
.x
.p
= new_enode(fractional
, 3, -1);
2687 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2688 rem
.x
.p
->arr
[1] = p
->arr
[1];
2689 rem
.x
.p
->arr
[2] = p
->arr
[2];
2690 for (i
= 3; i
< p
->size
; ++i
)
2691 p
->arr
[i
-2] = p
->arr
[i
];
2695 value_init(inc
.x
.n
);
2696 value_set_si(inc
.d
, 1);
2697 value_oppose(inc
.x
.n
, min
);
2700 evalue_copy(&t
, &p
->arr
[0]);
2704 value_set_si(f
.d
, 0);
2705 f
.x
.p
= new_enode(fractional
, 3, -1);
2706 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2707 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2708 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2710 value_init(factor
.d
);
2711 evalue_set_si(&factor
, -1, 1);
2717 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2718 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2724 free_evalue_refs(&inc
);
2725 free_evalue_refs(&t
);
2726 free_evalue_refs(&f
);
2727 free_evalue_refs(&factor
);
2728 free_evalue_refs(&rem
);
2730 reduce_in_domain(e
, D
);
2734 _reduce_evalue(&p
->arr
[0], 0, 1);
2738 value_set_si(f
.d
, 0);
2739 f
.x
.p
= new_enode(fractional
, 3, -1);
2740 value_clear(f
.x
.p
->arr
[0].d
);
2741 f
.x
.p
->arr
[0] = p
->arr
[0];
2742 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2743 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2744 reorder_terms(p
, &f
);
2758 void evalue_range_reduction(evalue
*e
)
2761 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2764 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2765 if (reduce_in_domain(&e
->x
.p
->arr
[2*i
+1],
2766 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2767 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2769 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2770 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2771 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2772 value_clear(e
->x
.p
->arr
[2*i
].d
);
2774 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2775 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2783 Enumeration
* partition2enumeration(evalue
*EP
)
2786 Enumeration
*en
, *res
= NULL
;
2788 if (EVALUE_IS_ZERO(*EP
)) {
2793 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2794 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
2795 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2798 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2799 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2800 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2808 static int frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2818 if (value_notzero_p(e
->d
))
2823 i
= p
->type
== relation
? 1 :
2824 p
->type
== fractional
? 1 : 0;
2825 for (; i
<p
->size
; i
++)
2826 r
|= frac2floor_in_domain(&p
->arr
[i
], D
);
2828 if (p
->type
!= fractional
) {
2829 if (r
&& p
->type
== polynomial
) {
2832 value_set_si(f
.d
, 0);
2833 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2834 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2835 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2836 reorder_terms(p
, &f
);
2845 I
= polynomial_projection(p
, D
, &d
, &T
, 0);
2848 Polyhedron_Print(stderr, P_VALUE_FMT, I);
2851 assert(I
->NbEq
== 0); /* Should have been reduced */
2854 for (i
= 0; i
< I
->NbConstraints
; ++i
)
2855 if (value_pos_p(I
->Constraint
[i
][1]))
2858 assert(i
< I
->NbConstraints
);
2860 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
2861 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
2862 if (value_neg_p(min
)) {
2864 mpz_fdiv_q(min
, min
, d
);
2865 value_init(offset
.d
);
2866 value_set_si(offset
.d
, 1);
2867 value_init(offset
.x
.n
);
2868 value_oppose(offset
.x
.n
, min
);
2869 eadd(&offset
, &p
->arr
[0]);
2870 free_evalue_refs(&offset
);
2879 value_set_si(fl
.d
, 0);
2880 fl
.x
.p
= new_enode(flooring
, 3, -1);
2881 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2882 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2883 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2885 eadd(&fl
, &p
->arr
[0]);
2886 reorder_terms(p
, &p
->arr
[0]);
2889 free_evalue_refs(&fl
);
2894 void evalue_frac2floor(evalue
*e
)
2897 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2900 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2901 if (frac2floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
2902 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])))
2903 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2906 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2911 int nparam
= D
->Dimension
- nvar
;
2914 nr
= D
->NbConstraints
+ 2;
2915 nc
= D
->Dimension
+ 2 + 1;
2916 C
= Matrix_Alloc(nr
, nc
);
2917 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2918 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
2919 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2920 D
->Dimension
+ 1 - nvar
);
2925 nc
= C
->NbColumns
+ 1;
2926 C
= Matrix_Alloc(nr
, nc
);
2927 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
2928 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
2929 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2930 oldC
->NbColumns
- 1 - nvar
);
2933 value_set_si(C
->p
[nr
-2][0], 1);
2934 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
2935 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
2937 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
2938 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
2944 static void floor2frac_r(evalue
*e
, int nvar
)
2951 if (value_notzero_p(e
->d
))
2956 assert(p
->type
== flooring
);
2957 for (i
= 1; i
< p
->size
; i
++)
2958 floor2frac_r(&p
->arr
[i
], nvar
);
2960 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
2961 assert(pp
->x
.p
->type
== polynomial
);
2962 pp
->x
.p
->pos
-= nvar
;
2966 value_set_si(f
.d
, 0);
2967 f
.x
.p
= new_enode(fractional
, 3, -1);
2968 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2969 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2970 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2972 eadd(&f
, &p
->arr
[0]);
2973 reorder_terms(p
, &p
->arr
[0]);
2976 free_evalue_refs(&f
);
2979 /* Convert flooring back to fractional and shift position
2980 * of the parameters by nvar
2982 static void floor2frac(evalue
*e
, int nvar
)
2984 floor2frac_r(e
, nvar
);
2988 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
2991 int nparam
= D
->Dimension
- nvar
;
2995 D
= Constraints2Polyhedron(C
, 0);
2999 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3001 /* Double check that D was not unbounded. */
3002 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3010 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3017 evalue
*factor
= NULL
;
3020 if (EVALUE_IS_ZERO(*e
))
3024 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
3031 res
= esum_over_domain(e
, nvar
, Q
, C
);
3034 for (Q
= DD
; Q
; Q
= DD
) {
3040 t
= esum_over_domain(e
, nvar
, Q
, C
);
3047 free_evalue_refs(t
);
3054 if (value_notzero_p(e
->d
)) {
3057 t
= esum_over_domain_cst(nvar
, D
, C
);
3059 if (!EVALUE_IS_ONE(*e
))
3065 switch (e
->x
.p
->type
) {
3067 evalue
*pp
= &e
->x
.p
->arr
[0];
3069 if (pp
->x
.p
->pos
> nvar
) {
3070 /* remainder is independent of the summated vars */
3076 floor2frac(&f
, nvar
);
3078 t
= esum_over_domain_cst(nvar
, D
, C
);
3082 free_evalue_refs(&f
);
3087 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3088 poly_denom(pp
, &row
->p
[1 + nvar
]);
3089 value_set_si(row
->p
[0], 1);
3090 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3091 pp
= &pp
->x
.p
->arr
[0]) {
3093 assert(pp
->x
.p
->type
== polynomial
);
3095 if (pos
>= 1 + nvar
)
3097 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3098 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3099 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3101 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3102 value_division(row
->p
[1 + D
->Dimension
+ 1],
3103 row
->p
[1 + D
->Dimension
+ 1],
3105 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3106 row
->p
[1 + D
->Dimension
+ 1],
3108 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3112 int pos
= e
->x
.p
->pos
;
3116 value_init(factor
->d
);
3117 value_set_si(factor
->d
, 0);
3118 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3119 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3120 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3124 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3125 for (i
= 0; i
< D
->NbRays
; ++i
)
3126 if (value_notzero_p(D
->Ray
[i
][pos
]))
3128 assert(i
< D
->NbRays
);
3129 if (value_neg_p(D
->Ray
[i
][pos
])) {
3131 value_init(factor
->d
);
3132 evalue_set_si(factor
, -1, 1);
3134 value_set_si(row
->p
[0], 1);
3135 value_set_si(row
->p
[pos
], 1);
3136 value_set_si(row
->p
[1 + nvar
], -1);
3143 i
= type_offset(e
->x
.p
);
3145 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3150 evalue_copy(&cum
, factor
);
3154 for (; i
< e
->x
.p
->size
; ++i
) {
3158 C
= esum_add_constraint(nvar
, D
, C
, row
);
3164 Vector_Print(stderr, P_VALUE_FMT, row);
3166 Matrix_Print(stderr, P_VALUE_FMT, C);
3168 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3177 free_evalue_refs(t
);
3180 if (factor
&& i
+1 < e
->x
.p
->size
)
3187 free_evalue_refs(factor
);
3188 free_evalue_refs(&cum
);
3200 evalue
*esum(evalue
*e
, int nvar
)
3208 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3209 evalue_copy(res
, e
);
3213 evalue_set_si(res
, 0, 1);
3215 assert(value_zero_p(e
->d
));
3216 assert(e
->x
.p
->type
== partition
);
3218 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3220 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3221 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3223 free_evalue_refs(t
);
3232 /* Initial silly implementation */
3233 void eor(evalue
*e1
, evalue
*res
)
3239 evalue_set_si(&mone
, -1, 1);
3241 evalue_copy(&E
, res
);
3247 free_evalue_refs(&E
);
3248 free_evalue_refs(&mone
);