5 #include "ev_operations.h"
9 #define ALLOC(p) p = (typeof(p))malloc(sizeof(*p))
10 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
12 void evalue_set_si(evalue
*ev
, int n
, int d
) {
13 value_set_si(ev
->d
, d
);
15 value_set_si(ev
->x
.n
, n
);
18 void evalue_set(evalue
*ev
, Value n
, Value d
) {
19 value_assign(ev
->d
, d
);
21 value_assign(ev
->x
.n
, n
);
24 void aep_evalue(evalue
*e
, int *ref
) {
29 if (value_notzero_p(e
->d
))
30 return; /* a rational number, its already reduced */
32 return; /* hum... an overflow probably occured */
34 /* First check the components of p */
35 for (i
=0;i
<p
->size
;i
++)
36 aep_evalue(&p
->arr
[i
],ref
);
43 p
->pos
= ref
[p
->pos
-1]+1;
49 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
55 if (value_notzero_p(e
->d
))
56 return; /* a rational number, its already reduced */
58 return; /* hum... an overflow probably occured */
61 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
62 for(i
=0;i
<CT
->NbRows
-1;i
++)
63 for(j
=0;j
<CT
->NbColumns
;j
++)
64 if(value_notzero_p(CT
->p
[i
][j
])) {
69 /* Transform the references in e, using ref */
73 } /* addeliminatedparams_evalue */
75 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
76 unsigned MaxRays
, unsigned nparam
)
81 if (CT
->NbRows
== CT
->NbColumns
)
84 if (EVALUE_IS_ZERO(*e
))
87 if (value_notzero_p(e
->d
)) {
90 value_set_si(res
.d
, 0);
91 res
.x
.p
= new_enode(partition
, 2, nparam
);
92 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
93 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
94 value_clear(res
.x
.p
->arr
[1].d
);
102 assert(p
->type
== partition
);
105 for (i
=0; i
<p
->size
/2; i
++) {
106 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
107 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
110 T
= DomainIntersection(D
, CEq
, MaxRays
);
112 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
113 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
117 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
125 assert(value_notzero_p(e1
->d
));
126 assert(value_notzero_p(e2
->d
));
127 value_multiply(m
, e1
->x
.n
, e2
->d
);
128 value_multiply(m2
, e2
->x
.n
, e1
->d
);
131 else if (value_gt(m
, m2
))
141 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
143 if (value_notzero_p(e1
->d
)) {
144 if (value_zero_p(e2
->d
))
146 int r
= mod_rational_smaller(e1
, e2
);
147 return r
== -1 ? 0 : r
;
149 if (value_notzero_p(e2
->d
))
151 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
153 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
156 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
158 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
163 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
165 assert(value_zero_p(e1
->d
));
166 assert(value_zero_p(e2
->d
));
167 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
168 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
169 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
172 /* Negative pos means inequality */
173 /* s is negative of substitution if m is not zero */
182 struct fixed_param
*fixed
;
187 static int relations_depth(evalue
*e
)
192 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
193 e
= &e
->x
.p
->arr
[1], ++d
);
197 static void poly_denom(evalue
*p
, Value
*d
)
201 while (value_zero_p(p
->d
)) {
202 assert(p
->x
.p
->type
== polynomial
);
203 assert(p
->x
.p
->size
== 2);
204 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
205 value_lcm(*d
, p
->x
.p
->arr
[1].d
, d
);
208 value_lcm(*d
, p
->d
, d
);
211 #define EVALUE_IS_ONE(ev) (value_one_p((ev).d) && value_one_p((ev).x.n))
213 static void realloc_substitution(struct subst
*s
, int d
)
215 struct fixed_param
*n
;
218 for (i
= 0; i
< s
->n
; ++i
)
225 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
231 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
234 /* May have been reduced already */
235 if (value_notzero_p(m
->d
))
238 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
239 assert(m
->x
.p
->size
== 3);
241 /* fractional was inverted during reduction
242 * invert it back and move constant in
244 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
245 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
246 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
247 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
248 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
249 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
250 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
251 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
252 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
253 value_set_si(m
->x
.p
->arr
[1].d
, 1);
256 /* Oops. Nested identical relations. */
257 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
260 if (s
->n
>= s
->max
) {
261 int d
= relations_depth(r
);
262 realloc_substitution(s
, d
);
266 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
267 assert(p
->x
.p
->size
== 2);
270 assert(value_pos_p(f
->x
.n
));
272 value_init(s
->fixed
[s
->n
].m
);
273 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
274 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
275 value_init(s
->fixed
[s
->n
].d
);
276 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
277 value_init(s
->fixed
[s
->n
].s
.d
);
278 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
284 static int type_offset(enode
*p
)
286 return p
->type
== fractional
? 1 :
287 p
->type
== flooring
? 1 : 0;
290 static void reorder_terms(enode
*p
, evalue
*v
)
293 int offset
= type_offset(p
);
295 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
297 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
298 free_evalue_refs(&(p
->arr
[i
]));
304 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
310 if (value_notzero_p(e
->d
)) {
312 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
313 return; /* a rational number, its already reduced */
317 return; /* hum... an overflow probably occured */
319 /* First reduce the components of p */
320 add
= p
->type
== relation
;
321 for (i
=0; i
<p
->size
; i
++) {
323 add
= add_modulo_substitution(s
, e
);
325 if (i
== 0 && p
->type
==fractional
)
326 _reduce_evalue(&p
->arr
[i
], s
, 1);
328 _reduce_evalue(&p
->arr
[i
], s
, fract
);
330 if (add
&& i
== p
->size
-1) {
332 value_clear(s
->fixed
[s
->n
].m
);
333 value_clear(s
->fixed
[s
->n
].d
);
334 free_evalue_refs(&s
->fixed
[s
->n
].s
);
335 } else if (add
&& i
== 1)
336 s
->fixed
[s
->n
-1].pos
*= -1;
339 if (p
->type
==periodic
) {
341 /* Try to reduce the period */
342 for (i
=1; i
<=(p
->size
)/2; i
++) {
343 if ((p
->size
% i
)==0) {
345 /* Can we reduce the size to i ? */
347 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
348 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
351 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
355 you_lose
: /* OK, lets not do it */
360 /* Try to reduce its strength */
363 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
367 else if (p
->type
==polynomial
) {
368 for (k
= 0; s
&& k
< s
->n
; ++k
) {
369 if (s
->fixed
[k
].pos
== p
->pos
) {
370 int divide
= value_notone_p(s
->fixed
[k
].d
);
373 if (value_notzero_p(s
->fixed
[k
].m
)) {
376 assert(p
->size
== 2);
377 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
379 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
386 value_assign(d
.d
, s
->fixed
[k
].d
);
388 if (value_notzero_p(s
->fixed
[k
].m
))
389 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
391 value_set_si(d
.x
.n
, 1);
394 for (i
=p
->size
-1;i
>=1;i
--) {
395 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
397 emul(&d
, &p
->arr
[i
]);
398 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
399 free_evalue_refs(&(p
->arr
[i
]));
402 _reduce_evalue(&p
->arr
[0], s
, fract
);
405 free_evalue_refs(&d
);
411 /* Try to reduce the degree */
412 for (i
=p
->size
-1;i
>=1;i
--) {
413 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
415 /* Zero coefficient */
416 free_evalue_refs(&(p
->arr
[i
]));
421 /* Try to reduce its strength */
424 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
428 else if (p
->type
==fractional
) {
432 if (value_notzero_p(p
->arr
[0].d
)) {
434 value_assign(v
.d
, p
->arr
[0].d
);
436 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
441 evalue
*pp
= &p
->arr
[0];
442 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
443 assert(pp
->x
.p
->size
== 2);
445 /* search for exact duplicate among the modulo inequalities */
447 f
= &pp
->x
.p
->arr
[1];
448 for (k
= 0; s
&& k
< s
->n
; ++k
) {
449 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
450 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
451 value_eq(s
->fixed
[k
].m
, f
->d
) &&
452 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
459 /* replace { E/m } by { (E-1)/m } + 1/m */
464 evalue_set_si(&extra
, 1, 1);
465 value_assign(extra
.d
, g
);
466 eadd(&extra
, &v
.x
.p
->arr
[1]);
467 free_evalue_refs(&extra
);
469 /* We've been going in circles; stop now */
470 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
471 free_evalue_refs(&v
);
473 evalue_set_si(&v
, 0, 1);
478 value_set_si(v
.d
, 0);
479 v
.x
.p
= new_enode(fractional
, 3, -1);
480 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
481 value_assign(v
.x
.p
->arr
[1].d
, g
);
482 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
483 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
486 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
489 value_division(f
->d
, g
, f
->d
);
490 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
491 value_assign(f
->d
, g
);
492 value_decrement(f
->x
.n
, f
->x
.n
);
493 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
495 Gcd(f
->d
, f
->x
.n
, &g
);
496 value_division(f
->d
, f
->d
, g
);
497 value_division(f
->x
.n
, f
->x
.n
, g
);
506 /* reduction may have made this fractional arg smaller */
507 i
= reorder
? p
->size
: 1;
508 for ( ; i
< p
->size
; ++i
)
509 if (value_zero_p(p
->arr
[i
].d
) &&
510 p
->arr
[i
].x
.p
->type
== fractional
&&
511 !mod_term_smaller(e
, &p
->arr
[i
]))
515 value_set_si(v
.d
, 0);
516 v
.x
.p
= new_enode(fractional
, 3, -1);
517 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
518 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
519 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
529 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
530 pp
= &pp
->x
.p
->arr
[0]) {
531 f
= &pp
->x
.p
->arr
[1];
532 assert(value_pos_p(f
->d
));
533 mpz_mul_ui(twice
, f
->x
.n
, 2);
534 if (value_lt(twice
, f
->d
))
536 if (value_eq(twice
, f
->d
))
544 value_set_si(v
.d
, 0);
545 v
.x
.p
= new_enode(fractional
, 3, -1);
546 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
547 poly_denom(&p
->arr
[0], &twice
);
548 value_assign(v
.x
.p
->arr
[1].d
, twice
);
549 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
550 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
551 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
553 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
554 pp
= &pp
->x
.p
->arr
[0]) {
555 f
= &pp
->x
.p
->arr
[1];
556 value_oppose(f
->x
.n
, f
->x
.n
);
557 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
559 value_division(pp
->d
, twice
, pp
->d
);
560 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
561 value_assign(pp
->d
, twice
);
562 value_oppose(pp
->x
.n
, pp
->x
.n
);
563 value_decrement(pp
->x
.n
, pp
->x
.n
);
564 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
574 reorder_terms(p
, &v
);
575 _reduce_evalue(&p
->arr
[1], s
, fract
);
578 /* Try to reduce the degree */
579 for (i
=p
->size
-1;i
>=2;i
--) {
580 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
582 /* Zero coefficient */
583 free_evalue_refs(&(p
->arr
[i
]));
588 /* Try to reduce its strength */
591 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
592 free_evalue_refs(&(p
->arr
[0]));
596 else if (p
->type
== flooring
) {
597 /* Try to reduce the degree */
598 for (i
=p
->size
-1;i
>=2;i
--) {
599 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
601 /* Zero coefficient */
602 free_evalue_refs(&(p
->arr
[i
]));
607 /* Try to reduce its strength */
610 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
611 free_evalue_refs(&(p
->arr
[0]));
615 else if (p
->type
== relation
) {
616 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
617 free_evalue_refs(&(p
->arr
[2]));
618 free_evalue_refs(&(p
->arr
[0]));
625 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
626 free_evalue_refs(&(p
->arr
[2]));
629 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
630 free_evalue_refs(&(p
->arr
[1]));
631 free_evalue_refs(&(p
->arr
[0]));
632 evalue_set_si(e
, 0, 1);
639 /* Relation was reduced by means of an identical
640 * inequality => remove
642 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
645 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
646 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
648 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
650 free_evalue_refs(&(p
->arr
[2]));
654 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
656 evalue_set_si(e
, 0, 1);
657 free_evalue_refs(&(p
->arr
[1]));
659 free_evalue_refs(&(p
->arr
[0]));
665 } /* reduce_evalue */
667 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
672 for (k
= 0; k
< dim
; ++k
)
673 if (value_notzero_p(row
[k
+1]))
676 Vector_Normalize_Positive(row
+1, dim
+1, k
);
677 assert(s
->n
< s
->max
);
678 value_init(s
->fixed
[s
->n
].d
);
679 value_init(s
->fixed
[s
->n
].m
);
680 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
681 s
->fixed
[s
->n
].pos
= k
+1;
682 value_set_si(s
->fixed
[s
->n
].m
, 0);
683 r
= &s
->fixed
[s
->n
].s
;
685 for (l
= k
+1; l
< dim
; ++l
)
686 if (value_notzero_p(row
[l
+1])) {
687 value_set_si(r
->d
, 0);
688 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
689 value_init(r
->x
.p
->arr
[1].x
.n
);
690 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
691 value_set_si(r
->x
.p
->arr
[1].d
, 1);
695 value_oppose(r
->x
.n
, row
[dim
+1]);
696 value_set_si(r
->d
, 1);
700 void reduce_evalue (evalue
*e
) {
701 struct subst s
= { NULL
, 0, 0 };
703 if (value_notzero_p(e
->d
))
704 return; /* a rational number, its already reduced */
706 if (e
->x
.p
->type
== partition
) {
709 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
711 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
712 /* This shouldn't really happen;
713 * Empty domains should not be added.
720 D
= DomainConvex(D
, 0);
721 if (!D
->next
&& D
->NbEq
) {
725 realloc_substitution(&s
, dim
);
727 int d
= relations_depth(&e
->x
.p
->arr
[2*i
+1]);
729 NALLOC(s
.fixed
, s
.max
);
732 for (j
= 0; j
< D
->NbEq
; ++j
)
733 add_substitution(&s
, D
->Constraint
[j
], dim
);
735 if (D
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
737 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
738 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
740 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
741 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
742 value_clear(e
->x
.p
->arr
[2*i
].d
);
744 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
745 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
750 for (j
= 0; j
< s
.n
; ++j
) {
751 value_clear(s
.fixed
[j
].d
);
752 value_clear(s
.fixed
[j
].m
);
753 free_evalue_refs(&s
.fixed
[j
].s
);
757 if (e
->x
.p
->size
== 0) {
759 evalue_set_si(e
, 0, 1);
762 _reduce_evalue(e
, &s
, 0);
767 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
769 if(value_notzero_p(e
->d
)) {
770 if(value_notone_p(e
->d
)) {
771 value_print(DST
,VALUE_FMT
,e
->x
.n
);
773 value_print(DST
,VALUE_FMT
,e
->d
);
776 value_print(DST
,VALUE_FMT
,e
->x
.n
);
780 print_enode(DST
,e
->x
.p
,pname
);
784 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
789 fprintf(DST
, "NULL");
795 for (i
=0; i
<p
->size
; i
++) {
796 print_evalue(DST
, &p
->arr
[i
], pname
);
800 fprintf(DST
, " }\n");
804 for (i
=p
->size
-1; i
>=0; i
--) {
805 print_evalue(DST
, &p
->arr
[i
], pname
);
806 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
808 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
810 fprintf(DST
, " )\n");
814 for (i
=0; i
<p
->size
; i
++) {
815 print_evalue(DST
, &p
->arr
[i
], pname
);
816 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
818 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
823 for (i
=p
->size
-1; i
>=1; i
--) {
824 print_evalue(DST
, &p
->arr
[i
], pname
);
827 fprintf(DST
, p
->type
== flooring
? "[" : "{");
828 print_evalue(DST
, &p
->arr
[0], pname
);
829 fprintf(DST
, p
->type
== flooring
? "]" : "}");
831 fprintf(DST
, "^%d + ", i
-1);
836 fprintf(DST
, " )\n");
840 print_evalue(DST
, &p
->arr
[0], pname
);
841 fprintf(DST
, "= 0 ] * \n");
842 print_evalue(DST
, &p
->arr
[1], pname
);
844 fprintf(DST
, " +\n [ ");
845 print_evalue(DST
, &p
->arr
[0], pname
);
846 fprintf(DST
, "!= 0 ] * \n");
847 print_evalue(DST
, &p
->arr
[2], pname
);
851 for (i
=0; i
<p
->size
/2; i
++) {
852 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), pname
);
853 print_evalue(DST
, &p
->arr
[2*i
+1], pname
);
862 static void eadd_rev(evalue
*e1
, evalue
*res
)
866 evalue_copy(&ev
, e1
);
868 free_evalue_refs(res
);
872 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
876 evalue_copy(&ev
, e1
);
877 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
878 free_evalue_refs(res
);
882 struct section
{ Polyhedron
* D
; evalue E
; };
884 void eadd_partitions (evalue
*e1
,evalue
*res
)
889 s
= (struct section
*)
890 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
891 sizeof(struct section
));
893 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
894 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
897 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
898 assert(res
->x
.p
->size
>= 2);
899 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
900 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
902 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
904 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
913 value_init(s
[n
].E
.d
);
914 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
918 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
919 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
920 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
922 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
923 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
929 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
930 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
932 value_init(s
[n
].E
.d
);
933 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
934 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
939 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
943 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
946 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
947 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
948 value_clear(res
->x
.p
->arr
[2*i
].d
);
953 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
954 for (j
= 0; j
< n
; ++j
) {
955 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
956 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
957 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
958 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
964 static void explicit_complement(evalue
*res
)
966 enode
*rel
= new_enode(relation
, 3, 0);
968 value_clear(rel
->arr
[0].d
);
969 rel
->arr
[0] = res
->x
.p
->arr
[0];
970 value_clear(rel
->arr
[1].d
);
971 rel
->arr
[1] = res
->x
.p
->arr
[1];
972 value_set_si(rel
->arr
[2].d
, 1);
973 value_init(rel
->arr
[2].x
.n
);
974 value_set_si(rel
->arr
[2].x
.n
, 0);
979 void eadd(evalue
*e1
,evalue
*res
) {
982 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
983 /* Add two rational numbers */
989 value_multiply(m1
,e1
->x
.n
,res
->d
);
990 value_multiply(m2
,res
->x
.n
,e1
->d
);
991 value_addto(res
->x
.n
,m1
,m2
);
992 value_multiply(res
->d
,e1
->d
,res
->d
);
993 Gcd(res
->x
.n
,res
->d
,&g
);
994 if (value_notone_p(g
)) {
995 value_division(res
->d
,res
->d
,g
);
996 value_division(res
->x
.n
,res
->x
.n
,g
);
998 value_clear(g
); value_clear(m1
); value_clear(m2
);
1001 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1002 switch (res
->x
.p
->type
) {
1004 /* Add the constant to the constant term of a polynomial*/
1005 eadd(e1
, &res
->x
.p
->arr
[0]);
1008 /* Add the constant to all elements of a periodic number */
1009 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1010 eadd(e1
, &res
->x
.p
->arr
[i
]);
1014 fprintf(stderr
, "eadd: cannot add const with vector\n");
1018 eadd(e1
, &res
->x
.p
->arr
[1]);
1021 assert(EVALUE_IS_ZERO(*e1
));
1022 break; /* Do nothing */
1024 /* Create (zero) complement if needed */
1025 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1026 explicit_complement(res
);
1027 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1028 eadd(e1
, &res
->x
.p
->arr
[i
]);
1034 /* add polynomial or periodic to constant
1035 * you have to exchange e1 and res, before doing addition */
1037 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1041 else { // ((e1->d==0) && (res->d==0))
1042 assert(!((e1
->x
.p
->type
== partition
) ^
1043 (res
->x
.p
->type
== partition
)));
1044 if (e1
->x
.p
->type
== partition
) {
1045 eadd_partitions(e1
, res
);
1048 if (e1
->x
.p
->type
== relation
&&
1049 (res
->x
.p
->type
!= relation
||
1050 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1054 if (res
->x
.p
->type
== relation
) {
1055 if (e1
->x
.p
->type
== relation
&&
1056 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1057 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1058 explicit_complement(res
);
1059 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1060 explicit_complement(e1
);
1061 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1062 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1065 if (res
->x
.p
->size
< 3)
1066 explicit_complement(res
);
1067 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1068 eadd(e1
, &res
->x
.p
->arr
[i
]);
1071 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1072 /* adding to evalues of different type. two cases are possible
1073 * res is periodic and e1 is polynomial, you have to exchange
1074 * e1 and res then to add e1 to the constant term of res */
1075 if (e1
->x
.p
->type
== polynomial
) {
1076 eadd_rev_cst(e1
, res
);
1078 else if (res
->x
.p
->type
== polynomial
) {
1079 /* res is polynomial and e1 is periodic,
1080 add e1 to the constant term of res */
1082 eadd(e1
,&res
->x
.p
->arr
[0]);
1088 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1089 ((res
->x
.p
->type
== fractional
||
1090 res
->x
.p
->type
== flooring
) &&
1091 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1092 /* adding evalues of different position (i.e function of different unknowns
1093 * to case are possible */
1095 switch (res
->x
.p
->type
) {
1098 if(mod_term_smaller(res
, e1
))
1099 eadd(e1
,&res
->x
.p
->arr
[1]);
1101 eadd_rev_cst(e1
, res
);
1103 case polynomial
: // res and e1 are polynomials
1104 // add e1 to the constant term of res
1106 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1107 eadd(e1
,&res
->x
.p
->arr
[0]);
1109 eadd_rev_cst(e1
, res
);
1110 // value_clear(g); value_clear(m1); value_clear(m2);
1112 case periodic
: // res and e1 are pointers to periodic numbers
1113 //add e1 to all elements of res
1115 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1116 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1117 eadd(e1
,&res
->x
.p
->arr
[i
]);
1128 //same type , same pos and same size
1129 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1130 // add any element in e1 to the corresponding element in res
1131 i
= type_offset(res
->x
.p
);
1133 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1134 for (; i
<res
->x
.p
->size
; i
++) {
1135 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1140 /* Sizes are different */
1141 switch(res
->x
.p
->type
) {
1145 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1146 /* new enode and add res to that new node. If you do not do */
1147 /* that, you lose the the upper weight part of e1 ! */
1149 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1152 i
= type_offset(res
->x
.p
);
1154 assert(eequal(&e1
->x
.p
->arr
[0],
1155 &res
->x
.p
->arr
[0]));
1156 for (; i
<e1
->x
.p
->size
; i
++) {
1157 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1164 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1167 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1168 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1169 to add periodicaly elements of e1 to elements of ne, and finaly to
1174 value_init(ex
); value_init(ey
);value_init(ep
);
1177 value_set_si(ex
,e1
->x
.p
->size
);
1178 value_set_si(ey
,res
->x
.p
->size
);
1179 value_assign (ep
,*Lcm(ex
,ey
));
1180 p
=(int)mpz_get_si(ep
);
1181 ne
= (evalue
*) malloc (sizeof(evalue
));
1183 value_set_si( ne
->d
,0);
1185 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1187 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1190 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1193 value_assign(res
->d
, ne
->d
);
1199 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1208 static void emul_rev (evalue
*e1
, evalue
*res
)
1212 evalue_copy(&ev
, e1
);
1214 free_evalue_refs(res
);
1218 static void emul_poly (evalue
*e1
, evalue
*res
)
1220 int i
, j
, o
= type_offset(res
->x
.p
);
1222 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1224 value_set_si(tmp
.d
,0);
1225 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1227 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1228 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1229 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1230 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1233 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1234 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1235 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1238 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1239 emul(&res
->x
.p
->arr
[i
], &ev
);
1240 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1241 free_evalue_refs(&ev
);
1243 free_evalue_refs(res
);
1247 void emul_partitions (evalue
*e1
,evalue
*res
)
1252 s
= (struct section
*)
1253 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1254 sizeof(struct section
));
1256 fprintf(stderr
, "%d %d\n", e1
->x
.p
->pos
, res
->x
.p
->pos
);
1257 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1258 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1261 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1262 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1263 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1264 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1270 /* This code is only needed because the partitions
1271 are not true partitions.
1273 for (k
= 0; k
< n
; ++k
) {
1274 if (DomainIncludes(s
[k
].D
, d
))
1276 if (DomainIncludes(d
, s
[k
].D
)) {
1277 Domain_Free(s
[k
].D
);
1278 free_evalue_refs(&s
[k
].E
);
1289 value_init(s
[n
].E
.d
);
1290 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1291 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1295 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1296 value_clear(res
->x
.p
->arr
[2*i
].d
);
1297 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1302 evalue_set_si(res
, 0, 1);
1304 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1305 for (j
= 0; j
< n
; ++j
) {
1306 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1307 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1308 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1309 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1316 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1318 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1319 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1320 * evalues is not treated here */
1322 void emul (evalue
*e1
, evalue
*res
){
1325 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1326 fprintf(stderr
, "emul: do not proced on evector type !\n");
1330 if (EVALUE_IS_ZERO(*res
))
1333 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1334 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1335 emul_partitions(e1
, res
);
1338 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1339 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1340 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1342 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1343 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1344 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1345 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1346 explicit_complement(res
);
1347 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1348 explicit_complement(e1
);
1349 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1350 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1353 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1354 emul(e1
, &res
->x
.p
->arr
[i
]);
1356 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1357 switch(e1
->x
.p
->type
) {
1359 switch(res
->x
.p
->type
) {
1361 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1362 /* Product of two polynomials of the same variable */
1367 /* Product of two polynomials of different variables */
1369 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1370 for( i
=0; i
<res
->x
.p
->size
; i
++)
1371 emul(e1
, &res
->x
.p
->arr
[i
]);
1380 /* Product of a polynomial and a periodic or fractional */
1387 switch(res
->x
.p
->type
) {
1389 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1390 /* Product of two periodics of the same parameter and period */
1392 for(i
=0; i
<res
->x
.p
->size
;i
++)
1393 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1398 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1399 /* Product of two periodics of the same parameter and different periods */
1403 value_init(x
); value_init(y
);value_init(z
);
1406 value_set_si(x
,e1
->x
.p
->size
);
1407 value_set_si(y
,res
->x
.p
->size
);
1408 value_assign (z
,*Lcm(x
,y
));
1409 lcm
=(int)mpz_get_si(z
);
1410 newp
= (evalue
*) malloc (sizeof(evalue
));
1411 value_init(newp
->d
);
1412 value_set_si( newp
->d
,0);
1413 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1414 for(i
=0;i
<lcm
;i
++) {
1415 evalue_copy(&newp
->x
.p
->arr
[i
],
1416 &res
->x
.p
->arr
[i
%iy
]);
1419 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1421 value_assign(res
->d
,newp
->d
);
1424 value_clear(x
); value_clear(y
);value_clear(z
);
1428 /* Product of two periodics of different parameters */
1430 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1431 for(i
=0; i
<res
->x
.p
->size
; i
++)
1432 emul(e1
, &(res
->x
.p
->arr
[i
]));
1440 /* Product of a periodic and a polynomial */
1442 for(i
=0; i
<res
->x
.p
->size
; i
++)
1443 emul(e1
, &(res
->x
.p
->arr
[i
]));
1450 switch(res
->x
.p
->type
) {
1452 for(i
=0; i
<res
->x
.p
->size
; i
++)
1453 emul(e1
, &(res
->x
.p
->arr
[i
]));
1460 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1461 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1462 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1465 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1466 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1470 value_set_si(d
.x
.n
, 1);
1472 /* { x }^2 == { x }/2 */
1473 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1474 assert(e1
->x
.p
->size
== 3);
1475 assert(res
->x
.p
->size
== 3);
1477 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1479 eadd(&res
->x
.p
->arr
[1], &tmp
);
1480 emul(&e1
->x
.p
->arr
[2], &tmp
);
1481 emul(&e1
->x
.p
->arr
[1], res
);
1482 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1483 free_evalue_refs(&tmp
);
1488 if(mod_term_smaller(res
, e1
))
1489 for(i
=1; i
<res
->x
.p
->size
; i
++)
1490 emul(e1
, &(res
->x
.p
->arr
[i
]));
1505 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1506 /* Product of two rational numbers */
1510 value_multiply(res
->d
,e1
->d
,res
->d
);
1511 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1512 Gcd(res
->x
.n
, res
->d
,&g
);
1513 if (value_notone_p(g
)) {
1514 value_division(res
->d
,res
->d
,g
);
1515 value_division(res
->x
.n
,res
->x
.n
,g
);
1521 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1522 /* Product of an expression (polynomial or peririodic) and a rational number */
1528 /* Product of a rationel number and an expression (polynomial or peririodic) */
1530 i
= type_offset(res
->x
.p
);
1531 for (; i
<res
->x
.p
->size
; i
++)
1532 emul(e1
, &res
->x
.p
->arr
[i
]);
1542 /* Frees mask content ! */
1543 void emask(evalue
*mask
, evalue
*res
) {
1550 if (EVALUE_IS_ZERO(*res
)) {
1551 free_evalue_refs(mask
);
1555 assert(value_zero_p(mask
->d
));
1556 assert(mask
->x
.p
->type
== partition
);
1557 assert(value_zero_p(res
->d
));
1558 assert(res
->x
.p
->type
== partition
);
1559 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1560 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1561 pos
= res
->x
.p
->pos
;
1563 s
= (struct section
*)
1564 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1565 sizeof(struct section
));
1569 evalue_set_si(&mone
, -1, 1);
1572 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1573 assert(mask
->x
.p
->size
>= 2);
1574 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1575 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1577 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1579 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1588 value_init(s
[n
].E
.d
);
1589 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1593 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1594 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1597 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1598 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1599 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1600 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1602 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1603 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1609 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1610 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1612 value_init(s
[n
].E
.d
);
1613 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1614 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1620 /* Just ignore; this may have been previously masked off */
1622 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1626 free_evalue_refs(&mone
);
1627 free_evalue_refs(mask
);
1628 free_evalue_refs(res
);
1631 evalue_set_si(res
, 0, 1);
1633 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1634 for (j
= 0; j
< n
; ++j
) {
1635 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1636 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1637 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1644 void evalue_copy(evalue
*dst
, evalue
*src
)
1646 value_assign(dst
->d
, src
->d
);
1647 if(value_notzero_p(src
->d
)) {
1648 value_init(dst
->x
.n
);
1649 value_assign(dst
->x
.n
, src
->x
.n
);
1651 dst
->x
.p
= ecopy(src
->x
.p
);
1654 enode
*new_enode(enode_type type
,int size
,int pos
) {
1660 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1663 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1667 for(i
=0; i
<size
; i
++) {
1668 value_init(res
->arr
[i
].d
);
1669 value_set_si(res
->arr
[i
].d
,0);
1670 res
->arr
[i
].x
.p
= 0;
1675 enode
*ecopy(enode
*e
) {
1680 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1681 for(i
=0;i
<e
->size
;++i
) {
1682 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1683 if(value_zero_p(res
->arr
[i
].d
))
1684 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1685 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1686 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1688 value_init(res
->arr
[i
].x
.n
);
1689 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1695 int ecmp(const evalue
*e1
, const evalue
*e2
)
1701 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1705 value_multiply(m
, e1
->x
.n
, e2
->d
);
1706 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1708 if (value_lt(m
, m2
))
1710 else if (value_gt(m
, m2
))
1720 if (value_notzero_p(e1
->d
))
1722 if (value_notzero_p(e2
->d
))
1728 if (p1
->type
!= p2
->type
)
1729 return p1
->type
- p2
->type
;
1730 if (p1
->pos
!= p2
->pos
)
1731 return p1
->pos
- p2
->pos
;
1732 if (p1
->size
!= p2
->size
)
1733 return p1
->size
- p2
->size
;
1735 for (i
= p1
->size
-1; i
>= 0; --i
)
1736 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1742 int eequal(evalue
*e1
,evalue
*e2
) {
1747 if (value_ne(e1
->d
,e2
->d
))
1750 /* e1->d == e2->d */
1751 if (value_notzero_p(e1
->d
)) {
1752 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1755 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1759 /* e1->d == e2->d == 0 */
1762 if (p1
->type
!= p2
->type
) return 0;
1763 if (p1
->size
!= p2
->size
) return 0;
1764 if (p1
->pos
!= p2
->pos
) return 0;
1765 for (i
=0; i
<p1
->size
; i
++)
1766 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1771 void free_evalue_refs(evalue
*e
) {
1776 if (EVALUE_IS_DOMAIN(*e
)) {
1777 Domain_Free(EVALUE_DOMAIN(*e
));
1780 } else if (value_pos_p(e
->d
)) {
1782 /* 'e' stores a constant */
1784 value_clear(e
->x
.n
);
1787 assert(value_zero_p(e
->d
));
1790 if (!p
) return; /* null pointer */
1791 for (i
=0; i
<p
->size
; i
++) {
1792 free_evalue_refs(&(p
->arr
[i
]));
1796 } /* free_evalue_refs */
1798 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1799 Vector
* val
, evalue
*res
)
1801 unsigned nparam
= periods
->Size
;
1804 double d
= compute_evalue(e
, val
->p
);
1805 d
*= VALUE_TO_DOUBLE(m
);
1810 value_assign(res
->d
, m
);
1811 value_init(res
->x
.n
);
1812 value_set_double(res
->x
.n
, d
);
1813 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1816 if (value_one_p(periods
->p
[p
]))
1817 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1822 value_assign(tmp
, periods
->p
[p
]);
1823 value_set_si(res
->d
, 0);
1824 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1826 value_decrement(tmp
, tmp
);
1827 value_assign(val
->p
[p
], tmp
);
1828 mod2table_r(e
, periods
, m
, p
+1, val
,
1829 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1830 } while (value_pos_p(tmp
));
1836 static void rel2table(evalue
*e
, int zero
)
1838 if (value_pos_p(e
->d
)) {
1839 if (value_zero_p(e
->x
.n
) == zero
)
1840 value_set_si(e
->x
.n
, 1);
1842 value_set_si(e
->x
.n
, 0);
1843 value_set_si(e
->d
, 1);
1846 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1847 rel2table(&e
->x
.p
->arr
[i
], zero
);
1851 void evalue_mod2table(evalue
*e
, int nparam
)
1856 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1859 for (i
=0; i
<p
->size
; i
++) {
1860 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1862 if (p
->type
== relation
) {
1867 evalue_copy(©
, &p
->arr
[0]);
1869 rel2table(&p
->arr
[0], 1);
1870 emul(&p
->arr
[0], &p
->arr
[1]);
1872 rel2table(©
, 0);
1873 emul(©
, &p
->arr
[2]);
1874 eadd(&p
->arr
[2], &p
->arr
[1]);
1875 free_evalue_refs(&p
->arr
[2]);
1876 free_evalue_refs(©
);
1878 free_evalue_refs(&p
->arr
[0]);
1882 } else if (p
->type
== fractional
) {
1883 Vector
*periods
= Vector_Alloc(nparam
);
1884 Vector
*val
= Vector_Alloc(nparam
);
1890 value_set_si(tmp
, 1);
1891 Vector_Set(periods
->p
, 1, nparam
);
1892 Vector_Set(val
->p
, 0, nparam
);
1893 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1896 assert(p
->type
== polynomial
);
1897 assert(p
->size
== 2);
1898 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
1899 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
1902 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1905 evalue_set_si(&res
, 0, 1);
1906 /* Compute the polynomial using Horner's rule */
1907 for (i
=p
->size
-1;i
>1;i
--) {
1908 eadd(&p
->arr
[i
], &res
);
1911 eadd(&p
->arr
[1], &res
);
1913 free_evalue_refs(e
);
1914 free_evalue_refs(&EP
);
1919 Vector_Free(periods
);
1921 } /* evalue_mod2table */
1923 /********************************************************/
1924 /* function in domain */
1925 /* check if the parameters in list_args */
1926 /* verifies the constraints of Domain P */
1927 /********************************************************/
1928 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1931 Value v
; /* value of the constraint of a row when
1932 parameters are instanciated*/
1938 /*P->Constraint constraint matrice of polyhedron P*/
1939 for(row
=0;row
<P
->NbConstraints
;row
++) {
1940 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1941 for(col
=1;col
<P
->Dimension
+1;col
++) {
1942 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1943 value_addto(v
,v
,tmp
);
1945 if (value_notzero_p(P
->Constraint
[row
][0])) {
1947 /*if v is not >=0 then this constraint is not respected */
1948 if (value_neg_p(v
)) {
1952 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1957 /*if v is not = 0 then this constraint is not respected */
1958 if (value_notzero_p(v
))
1963 /*if not return before this point => all
1964 the constraints are respected */
1970 /****************************************************/
1971 /* function compute enode */
1972 /* compute the value of enode p with parameters */
1973 /* list "list_args */
1974 /* compute the polynomial or the periodic */
1975 /****************************************************/
1977 static double compute_enode(enode
*p
, Value
*list_args
) {
1989 if (p
->type
== polynomial
) {
1991 value_assign(param
,list_args
[p
->pos
-1]);
1993 /* Compute the polynomial using Horner's rule */
1994 for (i
=p
->size
-1;i
>0;i
--) {
1995 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1996 res
*=VALUE_TO_DOUBLE(param
);
1998 res
+=compute_evalue(&p
->arr
[0],list_args
);
2000 else if (p
->type
== fractional
) {
2001 double d
= compute_evalue(&p
->arr
[0], list_args
);
2002 d
-= floor(d
+1e-10);
2004 /* Compute the polynomial using Horner's rule */
2005 for (i
=p
->size
-1;i
>1;i
--) {
2006 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2009 res
+=compute_evalue(&p
->arr
[1],list_args
);
2011 else if (p
->type
== flooring
) {
2012 double d
= compute_evalue(&p
->arr
[0], list_args
);
2015 /* Compute the polynomial using Horner's rule */
2016 for (i
=p
->size
-1;i
>1;i
--) {
2017 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2020 res
+=compute_evalue(&p
->arr
[1],list_args
);
2022 else if (p
->type
== periodic
) {
2023 value_assign(param
,list_args
[p
->pos
-1]);
2025 /* Choose the right element of the periodic */
2026 value_absolute(m
,param
);
2027 value_set_si(param
,p
->size
);
2028 value_modulus(m
,m
,param
);
2029 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2031 else if (p
->type
== relation
) {
2032 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2033 res
= compute_evalue(&p
->arr
[1], list_args
);
2034 else if (p
->size
> 2)
2035 res
= compute_evalue(&p
->arr
[2], list_args
);
2037 else if (p
->type
== partition
) {
2038 for (i
= 0; i
< p
->size
/2; ++i
)
2039 if (in_domain(EVALUE_DOMAIN(p
->arr
[2*i
]), list_args
)) {
2040 res
= compute_evalue(&p
->arr
[2*i
+1], list_args
);
2049 } /* compute_enode */
2051 /*************************************************/
2052 /* return the value of Ehrhart Polynomial */
2053 /* It returns a double, because since it is */
2054 /* a recursive function, some intermediate value */
2055 /* might not be integral */
2056 /*************************************************/
2058 double compute_evalue(evalue
*e
,Value
*list_args
) {
2062 if (value_notzero_p(e
->d
)) {
2063 if (value_notone_p(e
->d
))
2064 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2066 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2069 res
= compute_enode(e
->x
.p
,list_args
);
2071 } /* compute_evalue */
2074 /****************************************************/
2075 /* function compute_poly : */
2076 /* Check for the good validity domain */
2077 /* return the number of point in the Polyhedron */
2078 /* in allocated memory */
2079 /* Using the Ehrhart pseudo-polynomial */
2080 /****************************************************/
2081 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2084 /* double d; int i; */
2086 tmp
= (Value
*) malloc (sizeof(Value
));
2087 assert(tmp
!= NULL
);
2089 value_set_si(*tmp
,0);
2092 return(tmp
); /* no ehrhart polynomial */
2093 if(en
->ValidityDomain
) {
2094 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2095 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2100 return(tmp
); /* no Validity Domain */
2102 if(in_domain(en
->ValidityDomain
,list_args
)) {
2104 #ifdef EVAL_EHRHART_DEBUG
2105 Print_Domain(stdout
,en
->ValidityDomain
);
2106 print_evalue(stdout
,&en
->EP
);
2109 /* d = compute_evalue(&en->EP,list_args);
2111 printf("(double)%lf = %d\n", d, i ); */
2112 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2118 value_set_si(*tmp
,0);
2119 return(tmp
); /* no compatible domain with the arguments */
2120 } /* compute_poly */
2122 size_t value_size(Value v
) {
2123 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2124 * sizeof(v
[0]._mp_d
[0]);
2127 size_t domain_size(Polyhedron
*D
)
2130 size_t s
= sizeof(*D
);
2132 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2133 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2134 s
+= value_size(D
->Constraint
[i
][j
]);
2137 for (i = 0; i < D->NbRays; ++i)
2138 for (j = 0; j < D->Dimension+2; ++j)
2139 s += value_size(D->Ray[i][j]);
2142 return D
->next
? s
+domain_size(D
->next
) : s
;
2145 size_t enode_size(enode
*p
) {
2146 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2149 if (p
->type
== partition
)
2150 for (i
= 0; i
< p
->size
/2; ++i
) {
2151 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2152 s
+= evalue_size(&p
->arr
[2*i
+1]);
2155 for (i
= 0; i
< p
->size
; ++i
) {
2156 s
+= evalue_size(&p
->arr
[i
]);
2161 size_t evalue_size(evalue
*e
)
2163 size_t s
= sizeof(*e
);
2164 s
+= value_size(e
->d
);
2165 if (value_notzero_p(e
->d
))
2166 s
+= value_size(e
->x
.n
);
2168 s
+= enode_size(e
->x
.p
);
2172 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2174 evalue
*found
= NULL
;
2179 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2182 value_init(offset
.d
);
2183 value_init(offset
.x
.n
);
2184 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2185 value_lcm(m
, offset
.d
, &offset
.d
);
2186 value_set_si(offset
.x
.n
, 1);
2189 evalue_copy(©
, cst
);
2192 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2194 if (eequal(base
, &e
->x
.p
->arr
[0]))
2195 found
= &e
->x
.p
->arr
[0];
2197 value_set_si(offset
.x
.n
, -2);
2200 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2202 if (eequal(base
, &e
->x
.p
->arr
[0]))
2205 free_evalue_refs(cst
);
2206 free_evalue_refs(&offset
);
2209 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2210 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2215 static evalue
*find_relation_pair(evalue
*e
)
2218 evalue
*found
= NULL
;
2220 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2223 if (e
->x
.p
->type
== fractional
) {
2228 poly_denom(&e
->x
.p
->arr
[0], &m
);
2230 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2231 cst
= &cst
->x
.p
->arr
[0])
2234 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2235 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2240 i
= e
->x
.p
->type
== relation
;
2241 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2242 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2247 void evalue_mod2relation(evalue
*e
) {
2250 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2253 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2254 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2255 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2256 value_clear(e
->x
.p
->arr
[2*i
].d
);
2257 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2259 if (2*i
< e
->x
.p
->size
) {
2260 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2261 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2266 if (e
->x
.p
->size
== 0) {
2268 evalue_set_si(e
, 0, 1);
2274 while ((d
= find_relation_pair(e
)) != NULL
) {
2278 value_init(split
.d
);
2279 value_set_si(split
.d
, 0);
2280 split
.x
.p
= new_enode(relation
, 3, 0);
2281 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2282 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2284 ev
= &split
.x
.p
->arr
[0];
2285 value_set_si(ev
->d
, 0);
2286 ev
->x
.p
= new_enode(fractional
, 3, -1);
2287 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2288 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2289 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2295 free_evalue_refs(&split
);
2299 static int evalue_comp(const void * a
, const void * b
)
2301 const evalue
*e1
= *(const evalue
**)a
;
2302 const evalue
*e2
= *(const evalue
**)b
;
2303 return ecmp(e1
, e2
);
2306 void evalue_combine(evalue
*e
)
2313 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2316 NALLOC(evs
, e
->x
.p
->size
/2);
2317 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2318 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2319 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2320 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2321 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2322 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2323 value_clear(p
->arr
[2*k
].d
);
2324 value_clear(p
->arr
[2*k
+1].d
);
2325 p
->arr
[2*k
] = *(evs
[i
]-1);
2326 p
->arr
[2*k
+1] = *(evs
[i
]);
2329 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2332 value_clear((evs
[i
]-1)->d
);
2336 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2337 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2338 free_evalue_refs(evs
[i
]);
2342 for (i
= 2*k
; i
< p
->size
; ++i
)
2343 value_clear(p
->arr
[i
].d
);
2350 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2352 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2354 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2357 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2358 Polyhedron
*D
, *N
, **P
;
2361 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2368 if (D
->NbEq
<= H
->NbEq
) {
2374 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2375 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2376 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2377 reduce_evalue(&tmp
);
2378 if (value_notzero_p(tmp
.d
) ||
2379 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2382 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2383 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2386 free_evalue_refs(&tmp
);
2392 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2394 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2396 value_clear(e
->x
.p
->arr
[2*i
].d
);
2397 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2399 if (2*i
< e
->x
.p
->size
) {
2400 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2401 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2408 H
= DomainConvex(D
, 0);
2409 E
= DomainDifference(H
, D
, 0);
2411 D
= DomainDifference(H
, E
, 0);
2414 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2418 /* May change coefficients to become non-standard if fiddle is set
2419 * => reduce p afterwards to correct
2421 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2422 Matrix
**R
, int fiddle
)
2426 unsigned dim
= D
->Dimension
;
2427 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2432 assert(p
->type
== fractional
);
2434 value_set_si(T
->p
[1][dim
], 1);
2436 while (value_zero_p(pp
->d
)) {
2437 assert(pp
->x
.p
->type
== polynomial
);
2438 assert(pp
->x
.p
->size
== 2);
2439 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2440 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2441 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2442 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2443 value_substract(pp
->x
.p
->arr
[1].x
.n
,
2444 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2445 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2446 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2447 pp
= &pp
->x
.p
->arr
[0];
2449 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2450 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2451 I
= DomainImage(D
, T
, 0);
2452 H
= DomainConvex(I
, 0);
2461 static int reduce_in_domain(evalue
*e
, Polyhedron
*D
)
2471 if (value_notzero_p(e
->d
))
2476 if (p
->type
== relation
) {
2482 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2483 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2484 equal
= value_eq(min
, max
);
2485 mpz_cdiv_q(min
, min
, d
);
2486 mpz_fdiv_q(max
, max
, d
);
2488 if (bounded
&& value_gt(min
, max
)) {
2494 evalue_set_si(e
, 0, 1);
2497 free_evalue_refs(&(p
->arr
[1]));
2498 free_evalue_refs(&(p
->arr
[0]));
2504 return r
? r
: reduce_in_domain(e
, D
);
2505 } else if (bounded
&& equal
) {
2508 free_evalue_refs(&(p
->arr
[2]));
2511 free_evalue_refs(&(p
->arr
[0]));
2517 return reduce_in_domain(e
, D
);
2518 } else if (bounded
&& value_eq(min
, max
)) {
2519 /* zero for a single value */
2521 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2522 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2523 value_multiply(min
, min
, d
);
2524 value_substract(M
->p
[0][D
->Dimension
+1],
2525 M
->p
[0][D
->Dimension
+1], min
);
2526 E
= DomainAddConstraints(D
, M
, 0);
2532 r
= reduce_in_domain(&p
->arr
[1], E
);
2534 r
|= reduce_in_domain(&p
->arr
[2], D
);
2536 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2544 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2547 i
= p
->type
== relation
? 1 :
2548 p
->type
== fractional
? 1 : 0;
2549 for (; i
<p
->size
; i
++)
2550 r
|= reduce_in_domain(&p
->arr
[i
], D
);
2552 if (p
->type
!= fractional
) {
2553 if (r
&& p
->type
== polynomial
) {
2556 value_set_si(f
.d
, 0);
2557 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2558 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2559 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2560 reorder_terms(p
, &f
);
2571 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2573 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2574 mpz_fdiv_q(min
, min
, d
);
2575 mpz_fdiv_q(max
, max
, d
);
2576 value_substract(d
, max
, min
);
2578 if (bounded
&& value_eq(min
, max
)) {
2581 value_init(inc
.x
.n
);
2582 value_set_si(inc
.d
, 1);
2583 value_oppose(inc
.x
.n
, min
);
2584 eadd(&inc
, &p
->arr
[0]);
2585 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2589 free_evalue_refs(&inc
);
2591 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2594 value_set_si(rem
.d
, 0);
2595 rem
.x
.p
= new_enode(fractional
, 3, -1);
2596 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2597 rem
.x
.p
->arr
[1] = p
->arr
[1];
2598 rem
.x
.p
->arr
[2] = p
->arr
[2];
2599 for (i
= 3; i
< p
->size
; ++i
)
2600 p
->arr
[i
-2] = p
->arr
[i
];
2605 value_init(inc
.x
.n
);
2606 value_set_si(inc
.d
, 1);
2607 value_oppose(inc
.x
.n
, min
);
2611 evalue_copy(&t
, &p
->arr
[0]);
2616 value_set_si(f
.d
, 0);
2617 f
.x
.p
= new_enode(fractional
, 3, -1);
2618 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2619 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2620 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2623 value_init(factor
.d
);
2624 evalue_set_si(&factor
, -1, 1);
2630 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2631 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2637 free_evalue_refs(&inc
);
2638 free_evalue_refs(&t
);
2639 free_evalue_refs(&f
);
2640 free_evalue_refs(&factor
);
2641 free_evalue_refs(&rem
);
2643 reduce_in_domain(e
, D
);
2647 _reduce_evalue(&p
->arr
[0], 0, 1);
2651 value_set_si(f
.d
, 0);
2652 f
.x
.p
= new_enode(fractional
, 3, -1);
2653 value_clear(f
.x
.p
->arr
[0].d
);
2654 f
.x
.p
->arr
[0] = p
->arr
[0];
2655 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2656 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2657 reorder_terms(p
, &f
);
2671 void evalue_range_reduction(evalue
*e
)
2674 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2677 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2678 if (reduce_in_domain(&e
->x
.p
->arr
[2*i
+1],
2679 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2680 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2682 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2683 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2684 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2685 value_clear(e
->x
.p
->arr
[2*i
].d
);
2687 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2688 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2696 Enumeration
* partition2enumeration(evalue
*EP
)
2699 Enumeration
*en
, *res
= NULL
;
2701 if (EVALUE_IS_ZERO(*EP
)) {
2706 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2707 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2710 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2711 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2712 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2720 static int frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2730 if (value_notzero_p(e
->d
))
2735 i
= p
->type
== relation
? 1 :
2736 p
->type
== fractional
? 1 : 0;
2737 for (; i
<p
->size
; i
++)
2738 r
|= frac2floor_in_domain(&p
->arr
[i
], D
);
2740 if (p
->type
!= fractional
) {
2741 if (r
&& p
->type
== polynomial
) {
2744 value_set_si(f
.d
, 0);
2745 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2746 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2747 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2748 reorder_terms(p
, &f
);
2757 I
= polynomial_projection(p
, D
, &d
, &T
, 0);
2760 Polyhedron_Print(stderr, P_VALUE_FMT, I);
2763 assert(I
->NbEq
== 0); /* Should have been reduced */
2766 for (i
= 0; i
< I
->NbConstraints
; ++i
)
2767 if (value_pos_p(I
->Constraint
[i
][1]))
2770 assert(i
< I
->NbConstraints
);
2772 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
2773 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
2774 if (value_neg_p(min
)) {
2776 mpz_fdiv_q(min
, min
, d
);
2777 value_init(offset
.d
);
2778 value_set_si(offset
.d
, 1);
2779 value_init(offset
.x
.n
);
2780 value_oppose(offset
.x
.n
, min
);
2781 eadd(&offset
, &p
->arr
[0]);
2782 free_evalue_refs(&offset
);
2791 value_set_si(fl
.d
, 0);
2792 fl
.x
.p
= new_enode(flooring
, 3, -1);
2793 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2794 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2795 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2797 eadd(&fl
, &p
->arr
[0]);
2798 reorder_terms(p
, &p
->arr
[0]);
2801 free_evalue_refs(&fl
);
2806 void evalue_frac2floor(evalue
*e
)
2809 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2812 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2813 if (frac2floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
2814 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])))
2815 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2818 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2823 int nparam
= D
->Dimension
- nvar
;
2826 nr
= D
->NbConstraints
+ 2;
2827 nc
= D
->Dimension
+ 2 + 1;
2828 C
= Matrix_Alloc(nr
, nc
);
2829 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2830 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
2831 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2832 D
->Dimension
+ 1 - nvar
);
2837 nc
= C
->NbColumns
+ 1;
2838 C
= Matrix_Alloc(nr
, nc
);
2839 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
2840 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
2841 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2842 oldC
->NbColumns
- 1 - nvar
);
2845 value_set_si(C
->p
[nr
-2][0], 1);
2846 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
2847 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
2849 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
2850 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
2856 static void floor2frac_r(evalue
*e
, int nvar
)
2863 if (value_notzero_p(e
->d
))
2868 assert(p
->type
== flooring
);
2869 for (i
= 1; i
< p
->size
; i
++)
2870 floor2frac_r(&p
->arr
[i
], nvar
);
2872 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
2873 assert(pp
->x
.p
->type
== polynomial
);
2874 pp
->x
.p
->pos
-= nvar
;
2878 value_set_si(f
.d
, 0);
2879 f
.x
.p
= new_enode(fractional
, 3, -1);
2880 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2881 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2882 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2884 eadd(&f
, &p
->arr
[0]);
2885 reorder_terms(p
, &p
->arr
[0]);
2888 free_evalue_refs(&f
);
2891 /* Convert flooring back to fractional and shift position
2892 * of the parameters by nvar
2894 static void floor2frac(evalue
*e
, int nvar
)
2896 floor2frac_r(e
, nvar
);
2900 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
2903 int nparam
= D
->Dimension
- nvar
;
2907 D
= Constraints2Polyhedron(C
, 0);
2911 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
2913 /* Double check that D was not unbounded. */
2914 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
2922 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
2929 evalue
*factor
= NULL
;
2932 if (EVALUE_IS_ZERO(*e
))
2936 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
2943 res
= esum_over_domain(e
, nvar
, Q
, C
);
2946 for (Q
= DD
; Q
; Q
= DD
) {
2952 t
= esum_over_domain(e
, nvar
, Q
, C
);
2959 free_evalue_refs(t
);
2966 if (value_notzero_p(e
->d
)) {
2969 t
= esum_over_domain_cst(nvar
, D
, C
);
2971 if (!EVALUE_IS_ONE(*e
))
2977 switch (e
->x
.p
->type
) {
2979 evalue
*pp
= &e
->x
.p
->arr
[0];
2981 if (pp
->x
.p
->pos
> nvar
) {
2982 /* remainder is independent of the summated vars */
2988 floor2frac(&f
, nvar
);
2990 t
= esum_over_domain_cst(nvar
, D
, C
);
2994 free_evalue_refs(&f
);
2999 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3000 poly_denom(pp
, &row
->p
[1 + nvar
]);
3001 value_set_si(row
->p
[0], 1);
3002 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3003 pp
= &pp
->x
.p
->arr
[0]) {
3005 assert(pp
->x
.p
->type
== polynomial
);
3007 if (pos
>= 1 + nvar
)
3009 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3010 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3011 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3013 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3014 value_division(row
->p
[1 + D
->Dimension
+ 1],
3015 row
->p
[1 + D
->Dimension
+ 1],
3017 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3018 row
->p
[1 + D
->Dimension
+ 1],
3020 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3024 int pos
= e
->x
.p
->pos
;
3028 value_init(factor
->d
);
3029 value_set_si(factor
->d
, 0);
3030 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3031 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3032 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3036 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3037 for (i
= 0; i
< D
->NbRays
; ++i
)
3038 if (value_notzero_p(D
->Ray
[i
][pos
]))
3040 assert(i
< D
->NbRays
);
3041 if (value_neg_p(D
->Ray
[i
][pos
])) {
3043 value_init(factor
->d
);
3044 evalue_set_si(factor
, -1, 1);
3046 value_set_si(row
->p
[0], 1);
3047 value_set_si(row
->p
[pos
], 1);
3048 value_set_si(row
->p
[1 + nvar
], -1);
3055 i
= type_offset(e
->x
.p
);
3057 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3062 evalue_copy(&cum
, factor
);
3066 for (; i
< e
->x
.p
->size
; ++i
) {
3070 C
= esum_add_constraint(nvar
, D
, C
, row
);
3076 Vector_Print(stderr, P_VALUE_FMT, row);
3078 Matrix_Print(stderr, P_VALUE_FMT, C);
3080 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3089 free_evalue_refs(t
);
3092 if (factor
&& i
+1 < e
->x
.p
->size
)
3099 free_evalue_refs(factor
);
3100 free_evalue_refs(&cum
);
3112 evalue
*esum(evalue
*e
, int nvar
)
3120 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3121 evalue_copy(res
, e
);
3125 evalue_set_si(res
, 0, 1);
3127 assert(value_zero_p(e
->d
));
3128 assert(e
->x
.p
->type
== partition
);
3130 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3132 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3133 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3135 free_evalue_refs(t
);