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 char **names
= pname
;
852 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
853 if (p
->pos
< maxdim
) {
854 NALLOC(names
, maxdim
);
855 for (i
= 0; i
< p
->pos
; ++i
)
857 for ( ; i
< maxdim
; ++i
) {
858 NALLOC(names
[i
], 10);
859 snprintf(names
[i
], 10, "_p%d", i
);
863 for (i
=0; i
<p
->size
/2; i
++) {
864 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
865 print_evalue(DST
, &p
->arr
[2*i
+1], names
);
868 if (p
->pos
< maxdim
) {
869 for (i
= p
->pos
; i
< maxdim
; ++i
)
882 static void eadd_rev(evalue
*e1
, evalue
*res
)
886 evalue_copy(&ev
, e1
);
888 free_evalue_refs(res
);
892 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
896 evalue_copy(&ev
, e1
);
897 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
898 free_evalue_refs(res
);
902 struct section
{ Polyhedron
* D
; evalue E
; };
904 void eadd_partitions (evalue
*e1
,evalue
*res
)
909 s
= (struct section
*)
910 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
911 sizeof(struct section
));
913 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
914 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
917 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
918 assert(res
->x
.p
->size
>= 2);
919 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
920 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
922 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
924 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
933 value_init(s
[n
].E
.d
);
934 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
938 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
939 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
940 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
942 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
943 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
949 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
950 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
952 value_init(s
[n
].E
.d
);
953 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
954 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
959 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
963 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
966 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
967 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
968 value_clear(res
->x
.p
->arr
[2*i
].d
);
973 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
974 for (j
= 0; j
< n
; ++j
) {
975 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
976 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
977 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
978 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
984 static void explicit_complement(evalue
*res
)
986 enode
*rel
= new_enode(relation
, 3, 0);
988 value_clear(rel
->arr
[0].d
);
989 rel
->arr
[0] = res
->x
.p
->arr
[0];
990 value_clear(rel
->arr
[1].d
);
991 rel
->arr
[1] = res
->x
.p
->arr
[1];
992 value_set_si(rel
->arr
[2].d
, 1);
993 value_init(rel
->arr
[2].x
.n
);
994 value_set_si(rel
->arr
[2].x
.n
, 0);
999 void eadd(evalue
*e1
,evalue
*res
) {
1002 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1003 /* Add two rational numbers */
1009 value_multiply(m1
,e1
->x
.n
,res
->d
);
1010 value_multiply(m2
,res
->x
.n
,e1
->d
);
1011 value_addto(res
->x
.n
,m1
,m2
);
1012 value_multiply(res
->d
,e1
->d
,res
->d
);
1013 Gcd(res
->x
.n
,res
->d
,&g
);
1014 if (value_notone_p(g
)) {
1015 value_division(res
->d
,res
->d
,g
);
1016 value_division(res
->x
.n
,res
->x
.n
,g
);
1018 value_clear(g
); value_clear(m1
); value_clear(m2
);
1021 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1022 switch (res
->x
.p
->type
) {
1024 /* Add the constant to the constant term of a polynomial*/
1025 eadd(e1
, &res
->x
.p
->arr
[0]);
1028 /* Add the constant to all elements of a periodic number */
1029 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1030 eadd(e1
, &res
->x
.p
->arr
[i
]);
1034 fprintf(stderr
, "eadd: cannot add const with vector\n");
1038 eadd(e1
, &res
->x
.p
->arr
[1]);
1041 assert(EVALUE_IS_ZERO(*e1
));
1042 break; /* Do nothing */
1044 /* Create (zero) complement if needed */
1045 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1046 explicit_complement(res
);
1047 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1048 eadd(e1
, &res
->x
.p
->arr
[i
]);
1054 /* add polynomial or periodic to constant
1055 * you have to exchange e1 and res, before doing addition */
1057 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1061 else { // ((e1->d==0) && (res->d==0))
1062 assert(!((e1
->x
.p
->type
== partition
) ^
1063 (res
->x
.p
->type
== partition
)));
1064 if (e1
->x
.p
->type
== partition
) {
1065 eadd_partitions(e1
, res
);
1068 if (e1
->x
.p
->type
== relation
&&
1069 (res
->x
.p
->type
!= relation
||
1070 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1074 if (res
->x
.p
->type
== relation
) {
1075 if (e1
->x
.p
->type
== relation
&&
1076 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1077 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1078 explicit_complement(res
);
1079 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1080 explicit_complement(e1
);
1081 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1082 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1085 if (res
->x
.p
->size
< 3)
1086 explicit_complement(res
);
1087 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1088 eadd(e1
, &res
->x
.p
->arr
[i
]);
1091 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1092 /* adding to evalues of different type. two cases are possible
1093 * res is periodic and e1 is polynomial, you have to exchange
1094 * e1 and res then to add e1 to the constant term of res */
1095 if (e1
->x
.p
->type
== polynomial
) {
1096 eadd_rev_cst(e1
, res
);
1098 else if (res
->x
.p
->type
== polynomial
) {
1099 /* res is polynomial and e1 is periodic,
1100 add e1 to the constant term of res */
1102 eadd(e1
,&res
->x
.p
->arr
[0]);
1108 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1109 ((res
->x
.p
->type
== fractional
||
1110 res
->x
.p
->type
== flooring
) &&
1111 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1112 /* adding evalues of different position (i.e function of different unknowns
1113 * to case are possible */
1115 switch (res
->x
.p
->type
) {
1118 if(mod_term_smaller(res
, e1
))
1119 eadd(e1
,&res
->x
.p
->arr
[1]);
1121 eadd_rev_cst(e1
, res
);
1123 case polynomial
: // res and e1 are polynomials
1124 // add e1 to the constant term of res
1126 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1127 eadd(e1
,&res
->x
.p
->arr
[0]);
1129 eadd_rev_cst(e1
, res
);
1130 // value_clear(g); value_clear(m1); value_clear(m2);
1132 case periodic
: // res and e1 are pointers to periodic numbers
1133 //add e1 to all elements of res
1135 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1136 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1137 eadd(e1
,&res
->x
.p
->arr
[i
]);
1148 //same type , same pos and same size
1149 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1150 // add any element in e1 to the corresponding element in res
1151 i
= type_offset(res
->x
.p
);
1153 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1154 for (; i
<res
->x
.p
->size
; i
++) {
1155 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1160 /* Sizes are different */
1161 switch(res
->x
.p
->type
) {
1165 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1166 /* new enode and add res to that new node. If you do not do */
1167 /* that, you lose the the upper weight part of e1 ! */
1169 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1172 i
= type_offset(res
->x
.p
);
1174 assert(eequal(&e1
->x
.p
->arr
[0],
1175 &res
->x
.p
->arr
[0]));
1176 for (; i
<e1
->x
.p
->size
; i
++) {
1177 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1184 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1187 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1188 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1189 to add periodicaly elements of e1 to elements of ne, and finaly to
1194 value_init(ex
); value_init(ey
);value_init(ep
);
1197 value_set_si(ex
,e1
->x
.p
->size
);
1198 value_set_si(ey
,res
->x
.p
->size
);
1199 value_assign (ep
,*Lcm(ex
,ey
));
1200 p
=(int)mpz_get_si(ep
);
1201 ne
= (evalue
*) malloc (sizeof(evalue
));
1203 value_set_si( ne
->d
,0);
1205 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1207 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1210 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1213 value_assign(res
->d
, ne
->d
);
1219 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1228 static void emul_rev (evalue
*e1
, evalue
*res
)
1232 evalue_copy(&ev
, e1
);
1234 free_evalue_refs(res
);
1238 static void emul_poly (evalue
*e1
, evalue
*res
)
1240 int i
, j
, o
= type_offset(res
->x
.p
);
1242 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1244 value_set_si(tmp
.d
,0);
1245 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1247 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1248 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1249 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1250 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1253 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1254 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1255 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1258 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1259 emul(&res
->x
.p
->arr
[i
], &ev
);
1260 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1261 free_evalue_refs(&ev
);
1263 free_evalue_refs(res
);
1267 void emul_partitions (evalue
*e1
,evalue
*res
)
1272 s
= (struct section
*)
1273 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1274 sizeof(struct section
));
1276 fprintf(stderr
, "%d %d\n", e1
->x
.p
->pos
, res
->x
.p
->pos
);
1277 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1278 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1281 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1282 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1283 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1284 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1290 /* This code is only needed because the partitions
1291 are not true partitions.
1293 for (k
= 0; k
< n
; ++k
) {
1294 if (DomainIncludes(s
[k
].D
, d
))
1296 if (DomainIncludes(d
, s
[k
].D
)) {
1297 Domain_Free(s
[k
].D
);
1298 free_evalue_refs(&s
[k
].E
);
1309 value_init(s
[n
].E
.d
);
1310 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1311 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1315 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1316 value_clear(res
->x
.p
->arr
[2*i
].d
);
1317 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1322 evalue_set_si(res
, 0, 1);
1324 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1325 for (j
= 0; j
< n
; ++j
) {
1326 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1327 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1328 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1329 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1336 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1338 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1339 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1340 * evalues is not treated here */
1342 void emul (evalue
*e1
, evalue
*res
){
1345 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1346 fprintf(stderr
, "emul: do not proced on evector type !\n");
1350 if (EVALUE_IS_ZERO(*res
))
1353 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1354 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1355 emul_partitions(e1
, res
);
1358 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1359 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1360 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1362 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1363 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1364 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1365 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1366 explicit_complement(res
);
1367 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1368 explicit_complement(e1
);
1369 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1370 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1373 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1374 emul(e1
, &res
->x
.p
->arr
[i
]);
1376 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1377 switch(e1
->x
.p
->type
) {
1379 switch(res
->x
.p
->type
) {
1381 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1382 /* Product of two polynomials of the same variable */
1387 /* Product of two polynomials of different variables */
1389 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1390 for( i
=0; i
<res
->x
.p
->size
; i
++)
1391 emul(e1
, &res
->x
.p
->arr
[i
]);
1400 /* Product of a polynomial and a periodic or fractional */
1407 switch(res
->x
.p
->type
) {
1409 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1410 /* Product of two periodics of the same parameter and period */
1412 for(i
=0; i
<res
->x
.p
->size
;i
++)
1413 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1418 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1419 /* Product of two periodics of the same parameter and different periods */
1423 value_init(x
); value_init(y
);value_init(z
);
1426 value_set_si(x
,e1
->x
.p
->size
);
1427 value_set_si(y
,res
->x
.p
->size
);
1428 value_assign (z
,*Lcm(x
,y
));
1429 lcm
=(int)mpz_get_si(z
);
1430 newp
= (evalue
*) malloc (sizeof(evalue
));
1431 value_init(newp
->d
);
1432 value_set_si( newp
->d
,0);
1433 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1434 for(i
=0;i
<lcm
;i
++) {
1435 evalue_copy(&newp
->x
.p
->arr
[i
],
1436 &res
->x
.p
->arr
[i
%iy
]);
1439 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1441 value_assign(res
->d
,newp
->d
);
1444 value_clear(x
); value_clear(y
);value_clear(z
);
1448 /* Product of two periodics of different parameters */
1450 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1451 for(i
=0; i
<res
->x
.p
->size
; i
++)
1452 emul(e1
, &(res
->x
.p
->arr
[i
]));
1460 /* Product of a periodic and a polynomial */
1462 for(i
=0; i
<res
->x
.p
->size
; i
++)
1463 emul(e1
, &(res
->x
.p
->arr
[i
]));
1470 switch(res
->x
.p
->type
) {
1472 for(i
=0; i
<res
->x
.p
->size
; i
++)
1473 emul(e1
, &(res
->x
.p
->arr
[i
]));
1480 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1481 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1482 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1485 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1486 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1490 value_set_si(d
.x
.n
, 1);
1492 /* { x }^2 == { x }/2 */
1493 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1494 assert(e1
->x
.p
->size
== 3);
1495 assert(res
->x
.p
->size
== 3);
1497 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1499 eadd(&res
->x
.p
->arr
[1], &tmp
);
1500 emul(&e1
->x
.p
->arr
[2], &tmp
);
1501 emul(&e1
->x
.p
->arr
[1], res
);
1502 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1503 free_evalue_refs(&tmp
);
1508 if(mod_term_smaller(res
, e1
))
1509 for(i
=1; i
<res
->x
.p
->size
; i
++)
1510 emul(e1
, &(res
->x
.p
->arr
[i
]));
1525 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1526 /* Product of two rational numbers */
1530 value_multiply(res
->d
,e1
->d
,res
->d
);
1531 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1532 Gcd(res
->x
.n
, res
->d
,&g
);
1533 if (value_notone_p(g
)) {
1534 value_division(res
->d
,res
->d
,g
);
1535 value_division(res
->x
.n
,res
->x
.n
,g
);
1541 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1542 /* Product of an expression (polynomial or peririodic) and a rational number */
1548 /* Product of a rationel number and an expression (polynomial or peririodic) */
1550 i
= type_offset(res
->x
.p
);
1551 for (; i
<res
->x
.p
->size
; i
++)
1552 emul(e1
, &res
->x
.p
->arr
[i
]);
1562 /* Frees mask content ! */
1563 void emask(evalue
*mask
, evalue
*res
) {
1570 if (EVALUE_IS_ZERO(*res
)) {
1571 free_evalue_refs(mask
);
1575 assert(value_zero_p(mask
->d
));
1576 assert(mask
->x
.p
->type
== partition
);
1577 assert(value_zero_p(res
->d
));
1578 assert(res
->x
.p
->type
== partition
);
1579 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1580 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1581 pos
= res
->x
.p
->pos
;
1583 s
= (struct section
*)
1584 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1585 sizeof(struct section
));
1589 evalue_set_si(&mone
, -1, 1);
1592 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1593 assert(mask
->x
.p
->size
>= 2);
1594 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1595 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1597 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1599 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1608 value_init(s
[n
].E
.d
);
1609 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1613 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1614 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1617 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1618 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1619 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1620 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1622 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1623 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1629 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1630 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1632 value_init(s
[n
].E
.d
);
1633 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1634 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1640 /* Just ignore; this may have been previously masked off */
1642 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1646 free_evalue_refs(&mone
);
1647 free_evalue_refs(mask
);
1648 free_evalue_refs(res
);
1651 evalue_set_si(res
, 0, 1);
1653 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1654 for (j
= 0; j
< n
; ++j
) {
1655 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1656 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1657 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1664 void evalue_copy(evalue
*dst
, evalue
*src
)
1666 value_assign(dst
->d
, src
->d
);
1667 if(value_notzero_p(src
->d
)) {
1668 value_init(dst
->x
.n
);
1669 value_assign(dst
->x
.n
, src
->x
.n
);
1671 dst
->x
.p
= ecopy(src
->x
.p
);
1674 enode
*new_enode(enode_type type
,int size
,int pos
) {
1680 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1683 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1687 for(i
=0; i
<size
; i
++) {
1688 value_init(res
->arr
[i
].d
);
1689 value_set_si(res
->arr
[i
].d
,0);
1690 res
->arr
[i
].x
.p
= 0;
1695 enode
*ecopy(enode
*e
) {
1700 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1701 for(i
=0;i
<e
->size
;++i
) {
1702 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1703 if(value_zero_p(res
->arr
[i
].d
))
1704 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1705 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1706 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1708 value_init(res
->arr
[i
].x
.n
);
1709 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1715 int ecmp(const evalue
*e1
, const evalue
*e2
)
1721 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1725 value_multiply(m
, e1
->x
.n
, e2
->d
);
1726 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1728 if (value_lt(m
, m2
))
1730 else if (value_gt(m
, m2
))
1740 if (value_notzero_p(e1
->d
))
1742 if (value_notzero_p(e2
->d
))
1748 if (p1
->type
!= p2
->type
)
1749 return p1
->type
- p2
->type
;
1750 if (p1
->pos
!= p2
->pos
)
1751 return p1
->pos
- p2
->pos
;
1752 if (p1
->size
!= p2
->size
)
1753 return p1
->size
- p2
->size
;
1755 for (i
= p1
->size
-1; i
>= 0; --i
)
1756 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1762 int eequal(evalue
*e1
,evalue
*e2
) {
1767 if (value_ne(e1
->d
,e2
->d
))
1770 /* e1->d == e2->d */
1771 if (value_notzero_p(e1
->d
)) {
1772 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1775 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1779 /* e1->d == e2->d == 0 */
1782 if (p1
->type
!= p2
->type
) return 0;
1783 if (p1
->size
!= p2
->size
) return 0;
1784 if (p1
->pos
!= p2
->pos
) return 0;
1785 for (i
=0; i
<p1
->size
; i
++)
1786 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1791 void free_evalue_refs(evalue
*e
) {
1796 if (EVALUE_IS_DOMAIN(*e
)) {
1797 Domain_Free(EVALUE_DOMAIN(*e
));
1800 } else if (value_pos_p(e
->d
)) {
1802 /* 'e' stores a constant */
1804 value_clear(e
->x
.n
);
1807 assert(value_zero_p(e
->d
));
1810 if (!p
) return; /* null pointer */
1811 for (i
=0; i
<p
->size
; i
++) {
1812 free_evalue_refs(&(p
->arr
[i
]));
1816 } /* free_evalue_refs */
1818 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1819 Vector
* val
, evalue
*res
)
1821 unsigned nparam
= periods
->Size
;
1824 double d
= compute_evalue(e
, val
->p
);
1825 d
*= VALUE_TO_DOUBLE(m
);
1830 value_assign(res
->d
, m
);
1831 value_init(res
->x
.n
);
1832 value_set_double(res
->x
.n
, d
);
1833 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1836 if (value_one_p(periods
->p
[p
]))
1837 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1842 value_assign(tmp
, periods
->p
[p
]);
1843 value_set_si(res
->d
, 0);
1844 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1846 value_decrement(tmp
, tmp
);
1847 value_assign(val
->p
[p
], tmp
);
1848 mod2table_r(e
, periods
, m
, p
+1, val
,
1849 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1850 } while (value_pos_p(tmp
));
1856 static void rel2table(evalue
*e
, int zero
)
1858 if (value_pos_p(e
->d
)) {
1859 if (value_zero_p(e
->x
.n
) == zero
)
1860 value_set_si(e
->x
.n
, 1);
1862 value_set_si(e
->x
.n
, 0);
1863 value_set_si(e
->d
, 1);
1866 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1867 rel2table(&e
->x
.p
->arr
[i
], zero
);
1871 void evalue_mod2table(evalue
*e
, int nparam
)
1876 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1879 for (i
=0; i
<p
->size
; i
++) {
1880 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1882 if (p
->type
== relation
) {
1887 evalue_copy(©
, &p
->arr
[0]);
1889 rel2table(&p
->arr
[0], 1);
1890 emul(&p
->arr
[0], &p
->arr
[1]);
1892 rel2table(©
, 0);
1893 emul(©
, &p
->arr
[2]);
1894 eadd(&p
->arr
[2], &p
->arr
[1]);
1895 free_evalue_refs(&p
->arr
[2]);
1896 free_evalue_refs(©
);
1898 free_evalue_refs(&p
->arr
[0]);
1902 } else if (p
->type
== fractional
) {
1903 Vector
*periods
= Vector_Alloc(nparam
);
1904 Vector
*val
= Vector_Alloc(nparam
);
1910 value_set_si(tmp
, 1);
1911 Vector_Set(periods
->p
, 1, nparam
);
1912 Vector_Set(val
->p
, 0, nparam
);
1913 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1916 assert(p
->type
== polynomial
);
1917 assert(p
->size
== 2);
1918 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
1919 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
1922 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1925 evalue_set_si(&res
, 0, 1);
1926 /* Compute the polynomial using Horner's rule */
1927 for (i
=p
->size
-1;i
>1;i
--) {
1928 eadd(&p
->arr
[i
], &res
);
1931 eadd(&p
->arr
[1], &res
);
1933 free_evalue_refs(e
);
1934 free_evalue_refs(&EP
);
1939 Vector_Free(periods
);
1941 } /* evalue_mod2table */
1943 /********************************************************/
1944 /* function in domain */
1945 /* check if the parameters in list_args */
1946 /* verifies the constraints of Domain P */
1947 /********************************************************/
1948 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1951 Value v
; /* value of the constraint of a row when
1952 parameters are instanciated*/
1958 /*P->Constraint constraint matrice of polyhedron P*/
1959 for(row
=0;row
<P
->NbConstraints
;row
++) {
1960 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1961 for(col
=1;col
<P
->Dimension
+1;col
++) {
1962 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1963 value_addto(v
,v
,tmp
);
1965 if (value_notzero_p(P
->Constraint
[row
][0])) {
1967 /*if v is not >=0 then this constraint is not respected */
1968 if (value_neg_p(v
)) {
1972 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1977 /*if v is not = 0 then this constraint is not respected */
1978 if (value_notzero_p(v
))
1983 /*if not return before this point => all
1984 the constraints are respected */
1990 /****************************************************/
1991 /* function compute enode */
1992 /* compute the value of enode p with parameters */
1993 /* list "list_args */
1994 /* compute the polynomial or the periodic */
1995 /****************************************************/
1997 static double compute_enode(enode
*p
, Value
*list_args
) {
2009 if (p
->type
== polynomial
) {
2011 value_assign(param
,list_args
[p
->pos
-1]);
2013 /* Compute the polynomial using Horner's rule */
2014 for (i
=p
->size
-1;i
>0;i
--) {
2015 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2016 res
*=VALUE_TO_DOUBLE(param
);
2018 res
+=compute_evalue(&p
->arr
[0],list_args
);
2020 else if (p
->type
== fractional
) {
2021 double d
= compute_evalue(&p
->arr
[0], list_args
);
2022 d
-= floor(d
+1e-10);
2024 /* Compute the polynomial using Horner's rule */
2025 for (i
=p
->size
-1;i
>1;i
--) {
2026 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2029 res
+=compute_evalue(&p
->arr
[1],list_args
);
2031 else if (p
->type
== flooring
) {
2032 double d
= compute_evalue(&p
->arr
[0], list_args
);
2035 /* Compute the polynomial using Horner's rule */
2036 for (i
=p
->size
-1;i
>1;i
--) {
2037 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2040 res
+=compute_evalue(&p
->arr
[1],list_args
);
2042 else if (p
->type
== periodic
) {
2043 value_assign(param
,list_args
[p
->pos
-1]);
2045 /* Choose the right element of the periodic */
2046 value_absolute(m
,param
);
2047 value_set_si(param
,p
->size
);
2048 value_modulus(m
,m
,param
);
2049 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2051 else if (p
->type
== relation
) {
2052 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2053 res
= compute_evalue(&p
->arr
[1], list_args
);
2054 else if (p
->size
> 2)
2055 res
= compute_evalue(&p
->arr
[2], list_args
);
2057 else if (p
->type
== partition
) {
2058 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2062 for (i
= 0; i
< dim
; ++i
) {
2063 value_init(vals
[i
]);
2065 value_assign(vals
[i
], list_args
[i
]);
2068 for (i
= 0; i
< p
->size
/2; ++i
)
2069 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2070 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2074 for (i
= 0; i
< dim
; ++i
)
2075 value_clear(vals
[i
]);
2084 } /* compute_enode */
2086 /*************************************************/
2087 /* return the value of Ehrhart Polynomial */
2088 /* It returns a double, because since it is */
2089 /* a recursive function, some intermediate value */
2090 /* might not be integral */
2091 /*************************************************/
2093 double compute_evalue(evalue
*e
,Value
*list_args
) {
2097 if (value_notzero_p(e
->d
)) {
2098 if (value_notone_p(e
->d
))
2099 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2101 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2104 res
= compute_enode(e
->x
.p
,list_args
);
2106 } /* compute_evalue */
2109 /****************************************************/
2110 /* function compute_poly : */
2111 /* Check for the good validity domain */
2112 /* return the number of point in the Polyhedron */
2113 /* in allocated memory */
2114 /* Using the Ehrhart pseudo-polynomial */
2115 /****************************************************/
2116 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2119 /* double d; int i; */
2121 tmp
= (Value
*) malloc (sizeof(Value
));
2122 assert(tmp
!= NULL
);
2124 value_set_si(*tmp
,0);
2127 return(tmp
); /* no ehrhart polynomial */
2128 if(en
->ValidityDomain
) {
2129 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2130 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2135 return(tmp
); /* no Validity Domain */
2137 if(in_domain(en
->ValidityDomain
,list_args
)) {
2139 #ifdef EVAL_EHRHART_DEBUG
2140 Print_Domain(stdout
,en
->ValidityDomain
);
2141 print_evalue(stdout
,&en
->EP
);
2144 /* d = compute_evalue(&en->EP,list_args);
2146 printf("(double)%lf = %d\n", d, i ); */
2147 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2153 value_set_si(*tmp
,0);
2154 return(tmp
); /* no compatible domain with the arguments */
2155 } /* compute_poly */
2157 size_t value_size(Value v
) {
2158 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2159 * sizeof(v
[0]._mp_d
[0]);
2162 size_t domain_size(Polyhedron
*D
)
2165 size_t s
= sizeof(*D
);
2167 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2168 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2169 s
+= value_size(D
->Constraint
[i
][j
]);
2172 for (i = 0; i < D->NbRays; ++i)
2173 for (j = 0; j < D->Dimension+2; ++j)
2174 s += value_size(D->Ray[i][j]);
2177 return D
->next
? s
+domain_size(D
->next
) : s
;
2180 size_t enode_size(enode
*p
) {
2181 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2184 if (p
->type
== partition
)
2185 for (i
= 0; i
< p
->size
/2; ++i
) {
2186 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2187 s
+= evalue_size(&p
->arr
[2*i
+1]);
2190 for (i
= 0; i
< p
->size
; ++i
) {
2191 s
+= evalue_size(&p
->arr
[i
]);
2196 size_t evalue_size(evalue
*e
)
2198 size_t s
= sizeof(*e
);
2199 s
+= value_size(e
->d
);
2200 if (value_notzero_p(e
->d
))
2201 s
+= value_size(e
->x
.n
);
2203 s
+= enode_size(e
->x
.p
);
2207 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2209 evalue
*found
= NULL
;
2214 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2217 value_init(offset
.d
);
2218 value_init(offset
.x
.n
);
2219 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2220 value_lcm(m
, offset
.d
, &offset
.d
);
2221 value_set_si(offset
.x
.n
, 1);
2224 evalue_copy(©
, cst
);
2227 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2229 if (eequal(base
, &e
->x
.p
->arr
[0]))
2230 found
= &e
->x
.p
->arr
[0];
2232 value_set_si(offset
.x
.n
, -2);
2235 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2237 if (eequal(base
, &e
->x
.p
->arr
[0]))
2240 free_evalue_refs(cst
);
2241 free_evalue_refs(&offset
);
2244 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2245 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2250 static evalue
*find_relation_pair(evalue
*e
)
2253 evalue
*found
= NULL
;
2255 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2258 if (e
->x
.p
->type
== fractional
) {
2263 poly_denom(&e
->x
.p
->arr
[0], &m
);
2265 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2266 cst
= &cst
->x
.p
->arr
[0])
2269 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2270 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2275 i
= e
->x
.p
->type
== relation
;
2276 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2277 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2282 void evalue_mod2relation(evalue
*e
) {
2285 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2288 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2289 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2290 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2291 value_clear(e
->x
.p
->arr
[2*i
].d
);
2292 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2294 if (2*i
< e
->x
.p
->size
) {
2295 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2296 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2301 if (e
->x
.p
->size
== 0) {
2303 evalue_set_si(e
, 0, 1);
2309 while ((d
= find_relation_pair(e
)) != NULL
) {
2313 value_init(split
.d
);
2314 value_set_si(split
.d
, 0);
2315 split
.x
.p
= new_enode(relation
, 3, 0);
2316 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2317 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2319 ev
= &split
.x
.p
->arr
[0];
2320 value_set_si(ev
->d
, 0);
2321 ev
->x
.p
= new_enode(fractional
, 3, -1);
2322 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2323 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2324 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2330 free_evalue_refs(&split
);
2334 static int evalue_comp(const void * a
, const void * b
)
2336 const evalue
*e1
= *(const evalue
**)a
;
2337 const evalue
*e2
= *(const evalue
**)b
;
2338 return ecmp(e1
, e2
);
2341 void evalue_combine(evalue
*e
)
2348 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2351 NALLOC(evs
, e
->x
.p
->size
/2);
2352 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2353 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2354 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2355 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2356 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2357 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2358 value_clear(p
->arr
[2*k
].d
);
2359 value_clear(p
->arr
[2*k
+1].d
);
2360 p
->arr
[2*k
] = *(evs
[i
]-1);
2361 p
->arr
[2*k
+1] = *(evs
[i
]);
2364 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2367 value_clear((evs
[i
]-1)->d
);
2371 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2372 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2373 free_evalue_refs(evs
[i
]);
2377 for (i
= 2*k
; i
< p
->size
; ++i
)
2378 value_clear(p
->arr
[i
].d
);
2385 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2387 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2389 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2392 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2393 Polyhedron
*D
, *N
, **P
;
2396 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2403 if (D
->NbEq
<= H
->NbEq
) {
2409 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2410 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2411 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2412 reduce_evalue(&tmp
);
2413 if (value_notzero_p(tmp
.d
) ||
2414 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2417 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2418 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2421 free_evalue_refs(&tmp
);
2427 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2429 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2431 value_clear(e
->x
.p
->arr
[2*i
].d
);
2432 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2434 if (2*i
< e
->x
.p
->size
) {
2435 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2436 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2443 H
= DomainConvex(D
, 0);
2444 E
= DomainDifference(H
, D
, 0);
2446 D
= DomainDifference(H
, E
, 0);
2449 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2453 /* May change coefficients to become non-standard if fiddle is set
2454 * => reduce p afterwards to correct
2456 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2457 Matrix
**R
, int fiddle
)
2461 unsigned dim
= D
->Dimension
;
2462 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2467 assert(p
->type
== fractional
);
2469 value_set_si(T
->p
[1][dim
], 1);
2471 while (value_zero_p(pp
->d
)) {
2472 assert(pp
->x
.p
->type
== polynomial
);
2473 assert(pp
->x
.p
->size
== 2);
2474 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2475 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2476 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2477 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2478 value_substract(pp
->x
.p
->arr
[1].x
.n
,
2479 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2480 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2481 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2482 pp
= &pp
->x
.p
->arr
[0];
2484 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2485 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2486 I
= DomainImage(D
, T
, 0);
2487 H
= DomainConvex(I
, 0);
2496 static int reduce_in_domain(evalue
*e
, Polyhedron
*D
)
2506 if (value_notzero_p(e
->d
))
2511 if (p
->type
== relation
) {
2517 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2518 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2519 equal
= value_eq(min
, max
);
2520 mpz_cdiv_q(min
, min
, d
);
2521 mpz_fdiv_q(max
, max
, d
);
2523 if (bounded
&& value_gt(min
, max
)) {
2529 evalue_set_si(e
, 0, 1);
2532 free_evalue_refs(&(p
->arr
[1]));
2533 free_evalue_refs(&(p
->arr
[0]));
2539 return r
? r
: reduce_in_domain(e
, D
);
2540 } else if (bounded
&& equal
) {
2543 free_evalue_refs(&(p
->arr
[2]));
2546 free_evalue_refs(&(p
->arr
[0]));
2552 return reduce_in_domain(e
, D
);
2553 } else if (bounded
&& value_eq(min
, max
)) {
2554 /* zero for a single value */
2556 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2557 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2558 value_multiply(min
, min
, d
);
2559 value_substract(M
->p
[0][D
->Dimension
+1],
2560 M
->p
[0][D
->Dimension
+1], min
);
2561 E
= DomainAddConstraints(D
, M
, 0);
2567 r
= reduce_in_domain(&p
->arr
[1], E
);
2569 r
|= reduce_in_domain(&p
->arr
[2], D
);
2571 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2579 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2582 i
= p
->type
== relation
? 1 :
2583 p
->type
== fractional
? 1 : 0;
2584 for (; i
<p
->size
; i
++)
2585 r
|= reduce_in_domain(&p
->arr
[i
], D
);
2587 if (p
->type
!= fractional
) {
2588 if (r
&& p
->type
== polynomial
) {
2591 value_set_si(f
.d
, 0);
2592 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2593 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2594 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2595 reorder_terms(p
, &f
);
2606 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2608 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2609 mpz_fdiv_q(min
, min
, d
);
2610 mpz_fdiv_q(max
, max
, d
);
2611 value_substract(d
, max
, min
);
2613 if (bounded
&& value_eq(min
, max
)) {
2616 value_init(inc
.x
.n
);
2617 value_set_si(inc
.d
, 1);
2618 value_oppose(inc
.x
.n
, min
);
2619 eadd(&inc
, &p
->arr
[0]);
2620 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2624 free_evalue_refs(&inc
);
2626 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2629 value_set_si(rem
.d
, 0);
2630 rem
.x
.p
= new_enode(fractional
, 3, -1);
2631 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2632 rem
.x
.p
->arr
[1] = p
->arr
[1];
2633 rem
.x
.p
->arr
[2] = p
->arr
[2];
2634 for (i
= 3; i
< p
->size
; ++i
)
2635 p
->arr
[i
-2] = p
->arr
[i
];
2640 value_init(inc
.x
.n
);
2641 value_set_si(inc
.d
, 1);
2642 value_oppose(inc
.x
.n
, min
);
2646 evalue_copy(&t
, &p
->arr
[0]);
2651 value_set_si(f
.d
, 0);
2652 f
.x
.p
= new_enode(fractional
, 3, -1);
2653 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2654 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2655 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2658 value_init(factor
.d
);
2659 evalue_set_si(&factor
, -1, 1);
2665 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2666 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2672 free_evalue_refs(&inc
);
2673 free_evalue_refs(&t
);
2674 free_evalue_refs(&f
);
2675 free_evalue_refs(&factor
);
2676 free_evalue_refs(&rem
);
2678 reduce_in_domain(e
, D
);
2682 _reduce_evalue(&p
->arr
[0], 0, 1);
2686 value_set_si(f
.d
, 0);
2687 f
.x
.p
= new_enode(fractional
, 3, -1);
2688 value_clear(f
.x
.p
->arr
[0].d
);
2689 f
.x
.p
->arr
[0] = p
->arr
[0];
2690 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2691 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2692 reorder_terms(p
, &f
);
2706 void evalue_range_reduction(evalue
*e
)
2709 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2712 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2713 if (reduce_in_domain(&e
->x
.p
->arr
[2*i
+1],
2714 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2715 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2717 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2718 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2719 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2720 value_clear(e
->x
.p
->arr
[2*i
].d
);
2722 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2723 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2731 Enumeration
* partition2enumeration(evalue
*EP
)
2734 Enumeration
*en
, *res
= NULL
;
2736 if (EVALUE_IS_ZERO(*EP
)) {
2741 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2742 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
2743 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2746 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2747 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2748 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2756 static int frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2766 if (value_notzero_p(e
->d
))
2771 i
= p
->type
== relation
? 1 :
2772 p
->type
== fractional
? 1 : 0;
2773 for (; i
<p
->size
; i
++)
2774 r
|= frac2floor_in_domain(&p
->arr
[i
], D
);
2776 if (p
->type
!= fractional
) {
2777 if (r
&& p
->type
== polynomial
) {
2780 value_set_si(f
.d
, 0);
2781 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2782 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2783 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2784 reorder_terms(p
, &f
);
2793 I
= polynomial_projection(p
, D
, &d
, &T
, 0);
2796 Polyhedron_Print(stderr, P_VALUE_FMT, I);
2799 assert(I
->NbEq
== 0); /* Should have been reduced */
2802 for (i
= 0; i
< I
->NbConstraints
; ++i
)
2803 if (value_pos_p(I
->Constraint
[i
][1]))
2806 assert(i
< I
->NbConstraints
);
2808 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
2809 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
2810 if (value_neg_p(min
)) {
2812 mpz_fdiv_q(min
, min
, d
);
2813 value_init(offset
.d
);
2814 value_set_si(offset
.d
, 1);
2815 value_init(offset
.x
.n
);
2816 value_oppose(offset
.x
.n
, min
);
2817 eadd(&offset
, &p
->arr
[0]);
2818 free_evalue_refs(&offset
);
2827 value_set_si(fl
.d
, 0);
2828 fl
.x
.p
= new_enode(flooring
, 3, -1);
2829 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2830 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2831 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2833 eadd(&fl
, &p
->arr
[0]);
2834 reorder_terms(p
, &p
->arr
[0]);
2837 free_evalue_refs(&fl
);
2842 void evalue_frac2floor(evalue
*e
)
2845 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2848 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2849 if (frac2floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
2850 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])))
2851 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2854 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2859 int nparam
= D
->Dimension
- nvar
;
2862 nr
= D
->NbConstraints
+ 2;
2863 nc
= D
->Dimension
+ 2 + 1;
2864 C
= Matrix_Alloc(nr
, nc
);
2865 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2866 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
2867 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2868 D
->Dimension
+ 1 - nvar
);
2873 nc
= C
->NbColumns
+ 1;
2874 C
= Matrix_Alloc(nr
, nc
);
2875 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
2876 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
2877 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2878 oldC
->NbColumns
- 1 - nvar
);
2881 value_set_si(C
->p
[nr
-2][0], 1);
2882 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
2883 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
2885 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
2886 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
2892 static void floor2frac_r(evalue
*e
, int nvar
)
2899 if (value_notzero_p(e
->d
))
2904 assert(p
->type
== flooring
);
2905 for (i
= 1; i
< p
->size
; i
++)
2906 floor2frac_r(&p
->arr
[i
], nvar
);
2908 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
2909 assert(pp
->x
.p
->type
== polynomial
);
2910 pp
->x
.p
->pos
-= nvar
;
2914 value_set_si(f
.d
, 0);
2915 f
.x
.p
= new_enode(fractional
, 3, -1);
2916 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2917 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2918 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2920 eadd(&f
, &p
->arr
[0]);
2921 reorder_terms(p
, &p
->arr
[0]);
2924 free_evalue_refs(&f
);
2927 /* Convert flooring back to fractional and shift position
2928 * of the parameters by nvar
2930 static void floor2frac(evalue
*e
, int nvar
)
2932 floor2frac_r(e
, nvar
);
2936 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
2939 int nparam
= D
->Dimension
- nvar
;
2943 D
= Constraints2Polyhedron(C
, 0);
2947 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
2949 /* Double check that D was not unbounded. */
2950 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
2958 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
2965 evalue
*factor
= NULL
;
2968 if (EVALUE_IS_ZERO(*e
))
2972 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
2979 res
= esum_over_domain(e
, nvar
, Q
, C
);
2982 for (Q
= DD
; Q
; Q
= DD
) {
2988 t
= esum_over_domain(e
, nvar
, Q
, C
);
2995 free_evalue_refs(t
);
3002 if (value_notzero_p(e
->d
)) {
3005 t
= esum_over_domain_cst(nvar
, D
, C
);
3007 if (!EVALUE_IS_ONE(*e
))
3013 switch (e
->x
.p
->type
) {
3015 evalue
*pp
= &e
->x
.p
->arr
[0];
3017 if (pp
->x
.p
->pos
> nvar
) {
3018 /* remainder is independent of the summated vars */
3024 floor2frac(&f
, nvar
);
3026 t
= esum_over_domain_cst(nvar
, D
, C
);
3030 free_evalue_refs(&f
);
3035 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3036 poly_denom(pp
, &row
->p
[1 + nvar
]);
3037 value_set_si(row
->p
[0], 1);
3038 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3039 pp
= &pp
->x
.p
->arr
[0]) {
3041 assert(pp
->x
.p
->type
== polynomial
);
3043 if (pos
>= 1 + nvar
)
3045 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3046 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3047 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3049 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3050 value_division(row
->p
[1 + D
->Dimension
+ 1],
3051 row
->p
[1 + D
->Dimension
+ 1],
3053 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3054 row
->p
[1 + D
->Dimension
+ 1],
3056 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3060 int pos
= e
->x
.p
->pos
;
3064 value_init(factor
->d
);
3065 value_set_si(factor
->d
, 0);
3066 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3067 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3068 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3072 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3073 for (i
= 0; i
< D
->NbRays
; ++i
)
3074 if (value_notzero_p(D
->Ray
[i
][pos
]))
3076 assert(i
< D
->NbRays
);
3077 if (value_neg_p(D
->Ray
[i
][pos
])) {
3079 value_init(factor
->d
);
3080 evalue_set_si(factor
, -1, 1);
3082 value_set_si(row
->p
[0], 1);
3083 value_set_si(row
->p
[pos
], 1);
3084 value_set_si(row
->p
[1 + nvar
], -1);
3091 i
= type_offset(e
->x
.p
);
3093 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3098 evalue_copy(&cum
, factor
);
3102 for (; i
< e
->x
.p
->size
; ++i
) {
3106 C
= esum_add_constraint(nvar
, D
, C
, row
);
3112 Vector_Print(stderr, P_VALUE_FMT, row);
3114 Matrix_Print(stderr, P_VALUE_FMT, C);
3116 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3125 free_evalue_refs(t
);
3128 if (factor
&& i
+1 < e
->x
.p
->size
)
3135 free_evalue_refs(factor
);
3136 free_evalue_refs(&cum
);
3148 evalue
*esum(evalue
*e
, int nvar
)
3156 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3157 evalue_copy(res
, e
);
3161 evalue_set_si(res
, 0, 1);
3163 assert(value_zero_p(e
->d
));
3164 assert(e
->x
.p
->type
== partition
);
3166 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3168 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3169 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3171 free_evalue_refs(t
);