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
,
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, -1);
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
);
104 for (i
=0; i
<p
->size
/2; i
++) {
105 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
106 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
109 T
= DomainIntersection(D
, CEq
, MaxRays
);
111 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
112 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
116 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
124 assert(value_notzero_p(e1
->d
));
125 assert(value_notzero_p(e2
->d
));
126 value_multiply(m
, e1
->x
.n
, e2
->d
);
127 value_multiply(m2
, e2
->x
.n
, e1
->d
);
130 else if (value_gt(m
, m2
))
140 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
142 if (value_notzero_p(e1
->d
)) {
143 if (value_zero_p(e2
->d
))
145 int r
= mod_rational_smaller(e1
, e2
);
146 return r
== -1 ? 0 : r
;
148 if (value_notzero_p(e2
->d
))
150 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
152 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
155 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
157 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
162 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
164 assert(value_zero_p(e1
->d
));
165 assert(value_zero_p(e2
->d
));
166 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
167 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
168 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
171 /* Negative pos means inequality */
172 /* s is negative of substitution if m is not zero */
181 struct fixed_param
*fixed
;
186 static int relations_depth(evalue
*e
)
191 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
192 e
= &e
->x
.p
->arr
[1], ++d
);
196 static void Lcm3(Value i
, Value j
, Value
*res
)
202 value_multiply(*res
,i
,j
);
203 value_division(*res
, *res
, aux
);
207 static void poly_denom(evalue
*p
, Value
*d
)
211 while (value_zero_p(p
->d
)) {
212 assert(p
->x
.p
->type
== polynomial
);
213 assert(p
->x
.p
->size
== 2);
214 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
215 Lcm3(*d
, p
->x
.p
->arr
[1].d
, d
);
221 #define EVALUE_IS_ONE(ev) (value_one_p((ev).d) && value_one_p((ev).x.n))
223 static void realloc_substitution(struct subst
*s
, int d
)
225 struct fixed_param
*n
;
228 for (i
= 0; i
< s
->n
; ++i
)
235 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
241 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
244 /* May have been reduced already */
245 if (value_notzero_p(m
->d
))
248 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
249 assert(m
->x
.p
->size
== 3);
251 /* fractional was inverted during reduction
252 * invert it back and move constant in
254 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
255 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
256 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
257 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
258 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
259 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
260 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
261 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
262 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
263 value_set_si(m
->x
.p
->arr
[1].d
, 1);
266 /* Oops. Nested identical relations. */
267 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
270 if (s
->n
>= s
->max
) {
271 int d
= relations_depth(r
);
272 realloc_substitution(s
, d
);
276 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
277 assert(p
->x
.p
->size
== 2);
280 assert(value_pos_p(f
->x
.n
));
282 value_init(s
->fixed
[s
->n
].m
);
283 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
284 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
285 value_init(s
->fixed
[s
->n
].d
);
286 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
287 value_init(s
->fixed
[s
->n
].s
.d
);
288 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
294 static int type_offset(enode
*p
)
296 return p
->type
== fractional
? 1 :
297 p
->type
== flooring
? 1 : 0;
300 static void reorder_terms(enode
*p
, evalue
*v
)
303 int offset
= type_offset(p
);
305 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
307 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
308 free_evalue_refs(&(p
->arr
[i
]));
314 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
320 if (value_notzero_p(e
->d
)) {
322 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
323 return; /* a rational number, its already reduced */
327 return; /* hum... an overflow probably occured */
329 /* First reduce the components of p */
330 add
= p
->type
== relation
;
331 for (i
=0; i
<p
->size
; i
++) {
333 add
= add_modulo_substitution(s
, e
);
335 if (i
== 0 && p
->type
==fractional
)
336 _reduce_evalue(&p
->arr
[i
], s
, 1);
338 _reduce_evalue(&p
->arr
[i
], s
, fract
);
340 if (add
&& i
== p
->size
-1) {
342 value_clear(s
->fixed
[s
->n
].m
);
343 value_clear(s
->fixed
[s
->n
].d
);
344 free_evalue_refs(&s
->fixed
[s
->n
].s
);
345 } else if (add
&& i
== 1)
346 s
->fixed
[s
->n
-1].pos
*= -1;
349 if (p
->type
==periodic
) {
351 /* Try to reduce the period */
352 for (i
=1; i
<=(p
->size
)/2; i
++) {
353 if ((p
->size
% i
)==0) {
355 /* Can we reduce the size to i ? */
357 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
358 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
361 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
365 you_lose
: /* OK, lets not do it */
370 /* Try to reduce its strength */
373 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
377 else if (p
->type
==polynomial
) {
378 for (k
= 0; s
&& k
< s
->n
; ++k
) {
379 if (s
->fixed
[k
].pos
== p
->pos
) {
380 int divide
= value_notone_p(s
->fixed
[k
].d
);
383 if (value_notzero_p(s
->fixed
[k
].m
)) {
386 assert(p
->size
== 2);
387 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
389 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
396 value_assign(d
.d
, s
->fixed
[k
].d
);
398 if (value_notzero_p(s
->fixed
[k
].m
))
399 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
401 value_set_si(d
.x
.n
, 1);
404 for (i
=p
->size
-1;i
>=1;i
--) {
405 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
407 emul(&d
, &p
->arr
[i
]);
408 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
409 free_evalue_refs(&(p
->arr
[i
]));
412 _reduce_evalue(&p
->arr
[0], s
, fract
);
415 free_evalue_refs(&d
);
421 /* Try to reduce the degree */
422 for (i
=p
->size
-1;i
>=1;i
--) {
423 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
425 /* Zero coefficient */
426 free_evalue_refs(&(p
->arr
[i
]));
431 /* Try to reduce its strength */
434 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
438 else if (p
->type
==fractional
) {
442 if (value_notzero_p(p
->arr
[0].d
)) {
444 value_assign(v
.d
, p
->arr
[0].d
);
446 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
451 evalue
*pp
= &p
->arr
[0];
452 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
453 assert(pp
->x
.p
->size
== 2);
455 /* search for exact duplicate among the modulo inequalities */
457 f
= &pp
->x
.p
->arr
[1];
458 for (k
= 0; s
&& k
< s
->n
; ++k
) {
459 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
460 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
461 value_eq(s
->fixed
[k
].m
, f
->d
) &&
462 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
469 /* replace { E/m } by { (E-1)/m } + 1/m */
474 evalue_set_si(&extra
, 1, 1);
475 value_assign(extra
.d
, g
);
476 eadd(&extra
, &v
.x
.p
->arr
[1]);
477 free_evalue_refs(&extra
);
479 /* We've been going in circles; stop now */
480 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
481 free_evalue_refs(&v
);
483 evalue_set_si(&v
, 0, 1);
488 value_set_si(v
.d
, 0);
489 v
.x
.p
= new_enode(fractional
, 3, -1);
490 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
491 value_assign(v
.x
.p
->arr
[1].d
, g
);
492 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
493 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
496 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
499 value_division(f
->d
, g
, f
->d
);
500 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
501 value_assign(f
->d
, g
);
502 value_decrement(f
->x
.n
, f
->x
.n
);
503 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
505 Gcd(f
->d
, f
->x
.n
, &g
);
506 value_division(f
->d
, f
->d
, g
);
507 value_division(f
->x
.n
, f
->x
.n
, g
);
516 /* reduction may have made this fractional arg smaller */
517 i
= reorder
? p
->size
: 1;
518 for ( ; i
< p
->size
; ++i
)
519 if (value_zero_p(p
->arr
[i
].d
) &&
520 p
->arr
[i
].x
.p
->type
== fractional
&&
521 !mod_term_smaller(e
, &p
->arr
[i
]))
525 value_set_si(v
.d
, 0);
526 v
.x
.p
= new_enode(fractional
, 3, -1);
527 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
528 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
529 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
539 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
540 pp
= &pp
->x
.p
->arr
[0]) {
541 f
= &pp
->x
.p
->arr
[1];
542 assert(value_pos_p(f
->d
));
543 mpz_mul_ui(twice
, f
->x
.n
, 2);
544 if (value_lt(twice
, f
->d
))
546 if (value_eq(twice
, f
->d
))
554 value_set_si(v
.d
, 0);
555 v
.x
.p
= new_enode(fractional
, 3, -1);
556 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
557 poly_denom(&p
->arr
[0], &twice
);
558 value_assign(v
.x
.p
->arr
[1].d
, twice
);
559 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
560 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
561 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
563 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
564 pp
= &pp
->x
.p
->arr
[0]) {
565 f
= &pp
->x
.p
->arr
[1];
566 value_oppose(f
->x
.n
, f
->x
.n
);
567 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
569 value_division(pp
->d
, twice
, pp
->d
);
570 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
571 value_assign(pp
->d
, twice
);
572 value_oppose(pp
->x
.n
, pp
->x
.n
);
573 value_decrement(pp
->x
.n
, pp
->x
.n
);
574 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
584 reorder_terms(p
, &v
);
585 _reduce_evalue(&p
->arr
[1], s
, fract
);
588 /* Try to reduce the degree */
589 for (i
=p
->size
-1;i
>=2;i
--) {
590 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
592 /* Zero coefficient */
593 free_evalue_refs(&(p
->arr
[i
]));
598 /* Try to reduce its strength */
601 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
602 free_evalue_refs(&(p
->arr
[0]));
606 else if (p
->type
== flooring
) {
607 /* Try to reduce the degree */
608 for (i
=p
->size
-1;i
>=2;i
--) {
609 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
611 /* Zero coefficient */
612 free_evalue_refs(&(p
->arr
[i
]));
617 /* Try to reduce its strength */
620 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
621 free_evalue_refs(&(p
->arr
[0]));
625 else if (p
->type
== relation
) {
626 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
627 free_evalue_refs(&(p
->arr
[2]));
628 free_evalue_refs(&(p
->arr
[0]));
635 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
636 free_evalue_refs(&(p
->arr
[2]));
639 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
640 free_evalue_refs(&(p
->arr
[1]));
641 free_evalue_refs(&(p
->arr
[0]));
642 evalue_set_si(e
, 0, 1);
649 /* Relation was reduced by means of an identical
650 * inequality => remove
652 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
655 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
656 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
658 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
660 free_evalue_refs(&(p
->arr
[2]));
664 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
666 evalue_set_si(e
, 0, 1);
667 free_evalue_refs(&(p
->arr
[1]));
669 free_evalue_refs(&(p
->arr
[0]));
675 } /* reduce_evalue */
677 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
682 for (k
= 0; k
< dim
; ++k
)
683 if (value_notzero_p(row
[k
+1]))
686 Vector_Normalize_Positive(row
+1, dim
+1, k
);
687 assert(s
->n
< s
->max
);
688 value_init(s
->fixed
[s
->n
].d
);
689 value_init(s
->fixed
[s
->n
].m
);
690 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
691 s
->fixed
[s
->n
].pos
= k
+1;
692 value_set_si(s
->fixed
[s
->n
].m
, 0);
693 r
= &s
->fixed
[s
->n
].s
;
695 for (l
= k
+1; l
< dim
; ++l
)
696 if (value_notzero_p(row
[l
+1])) {
697 value_set_si(r
->d
, 0);
698 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
699 value_init(r
->x
.p
->arr
[1].x
.n
);
700 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
701 value_set_si(r
->x
.p
->arr
[1].d
, 1);
705 value_oppose(r
->x
.n
, row
[dim
+1]);
706 value_set_si(r
->d
, 1);
710 void reduce_evalue (evalue
*e
) {
711 struct subst s
= { NULL
, 0, 0 };
713 if (value_notzero_p(e
->d
))
714 return; /* a rational number, its already reduced */
716 if (e
->x
.p
->type
== partition
) {
719 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
721 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
722 /* This shouldn't really happen;
723 * Empty domains should not be added.
730 D
= DomainConvex(D
, 0);
731 if (!D
->next
&& D
->NbEq
) {
735 realloc_substitution(&s
, dim
);
737 int d
= relations_depth(&e
->x
.p
->arr
[2*i
+1]);
739 NALLOC(s
.fixed
, s
.max
);
742 for (j
= 0; j
< D
->NbEq
; ++j
)
743 add_substitution(&s
, D
->Constraint
[j
], dim
);
745 if (D
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
747 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
748 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
750 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
751 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
752 value_clear(e
->x
.p
->arr
[2*i
].d
);
754 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
755 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
760 for (j
= 0; j
< s
.n
; ++j
) {
761 value_clear(s
.fixed
[j
].d
);
762 value_clear(s
.fixed
[j
].m
);
763 free_evalue_refs(&s
.fixed
[j
].s
);
767 if (e
->x
.p
->size
== 0) {
769 evalue_set_si(e
, 0, 1);
772 _reduce_evalue(e
, &s
, 0);
777 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
779 if(value_notzero_p(e
->d
)) {
780 if(value_notone_p(e
->d
)) {
781 value_print(DST
,VALUE_FMT
,e
->x
.n
);
783 value_print(DST
,VALUE_FMT
,e
->d
);
786 value_print(DST
,VALUE_FMT
,e
->x
.n
);
790 print_enode(DST
,e
->x
.p
,pname
);
794 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
799 fprintf(DST
, "NULL");
805 for (i
=0; i
<p
->size
; i
++) {
806 print_evalue(DST
, &p
->arr
[i
], pname
);
810 fprintf(DST
, " }\n");
814 for (i
=p
->size
-1; i
>=0; i
--) {
815 print_evalue(DST
, &p
->arr
[i
], pname
);
816 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
818 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
820 fprintf(DST
, " )\n");
824 for (i
=0; i
<p
->size
; i
++) {
825 print_evalue(DST
, &p
->arr
[i
], pname
);
826 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
828 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
833 for (i
=p
->size
-1; i
>=1; i
--) {
834 print_evalue(DST
, &p
->arr
[i
], pname
);
837 fprintf(DST
, p
->type
== flooring
? "[" : "{");
838 print_evalue(DST
, &p
->arr
[0], pname
);
839 fprintf(DST
, p
->type
== flooring
? "]" : "}");
841 fprintf(DST
, "^%d + ", i
-1);
846 fprintf(DST
, " )\n");
850 print_evalue(DST
, &p
->arr
[0], pname
);
851 fprintf(DST
, "= 0 ] * \n");
852 print_evalue(DST
, &p
->arr
[1], pname
);
854 fprintf(DST
, " +\n [ ");
855 print_evalue(DST
, &p
->arr
[0], pname
);
856 fprintf(DST
, "!= 0 ] * \n");
857 print_evalue(DST
, &p
->arr
[2], pname
);
861 for (i
=0; i
<p
->size
/2; i
++) {
862 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), pname
);
863 print_evalue(DST
, &p
->arr
[2*i
+1], pname
);
872 static void eadd_rev(evalue
*e1
, evalue
*res
)
876 evalue_copy(&ev
, e1
);
878 free_evalue_refs(res
);
882 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
886 evalue_copy(&ev
, e1
);
887 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
888 free_evalue_refs(res
);
892 struct section
{ Polyhedron
* D
; evalue E
; };
894 void eadd_partitions (evalue
*e1
,evalue
*res
)
899 s
= (struct section
*)
900 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
901 sizeof(struct section
));
905 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
906 assert(res
->x
.p
->size
>= 2);
907 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
908 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
910 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
912 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
921 value_init(s
[n
].E
.d
);
922 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
926 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
927 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
928 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
930 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
931 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
937 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
938 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
940 value_init(s
[n
].E
.d
);
941 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
942 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
947 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
951 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
954 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
955 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
956 value_clear(res
->x
.p
->arr
[2*i
].d
);
961 res
->x
.p
= new_enode(partition
, 2*n
, -1);
962 for (j
= 0; j
< n
; ++j
) {
963 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
964 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
965 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
966 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
972 static void explicit_complement(evalue
*res
)
974 enode
*rel
= new_enode(relation
, 3, 0);
976 value_clear(rel
->arr
[0].d
);
977 rel
->arr
[0] = res
->x
.p
->arr
[0];
978 value_clear(rel
->arr
[1].d
);
979 rel
->arr
[1] = res
->x
.p
->arr
[1];
980 value_set_si(rel
->arr
[2].d
, 1);
981 value_init(rel
->arr
[2].x
.n
);
982 value_set_si(rel
->arr
[2].x
.n
, 0);
987 void eadd(evalue
*e1
,evalue
*res
) {
990 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
991 /* Add two rational numbers */
997 value_multiply(m1
,e1
->x
.n
,res
->d
);
998 value_multiply(m2
,res
->x
.n
,e1
->d
);
999 value_addto(res
->x
.n
,m1
,m2
);
1000 value_multiply(res
->d
,e1
->d
,res
->d
);
1001 Gcd(res
->x
.n
,res
->d
,&g
);
1002 if (value_notone_p(g
)) {
1003 value_division(res
->d
,res
->d
,g
);
1004 value_division(res
->x
.n
,res
->x
.n
,g
);
1006 value_clear(g
); value_clear(m1
); value_clear(m2
);
1009 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1010 switch (res
->x
.p
->type
) {
1012 /* Add the constant to the constant term of a polynomial*/
1013 eadd(e1
, &res
->x
.p
->arr
[0]);
1016 /* Add the constant to all elements of a periodic number */
1017 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1018 eadd(e1
, &res
->x
.p
->arr
[i
]);
1022 fprintf(stderr
, "eadd: cannot add const with vector\n");
1026 eadd(e1
, &res
->x
.p
->arr
[1]);
1029 assert(EVALUE_IS_ZERO(*e1
));
1030 break; /* Do nothing */
1032 /* Create (zero) complement if needed */
1033 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1034 explicit_complement(res
);
1035 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1036 eadd(e1
, &res
->x
.p
->arr
[i
]);
1042 /* add polynomial or periodic to constant
1043 * you have to exchange e1 and res, before doing addition */
1045 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1049 else { // ((e1->d==0) && (res->d==0))
1050 assert(!((e1
->x
.p
->type
== partition
) ^
1051 (res
->x
.p
->type
== partition
)));
1052 if (e1
->x
.p
->type
== partition
) {
1053 eadd_partitions(e1
, res
);
1056 if (e1
->x
.p
->type
== relation
&&
1057 (res
->x
.p
->type
!= relation
||
1058 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1062 if (res
->x
.p
->type
== relation
) {
1063 if (e1
->x
.p
->type
== relation
&&
1064 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1065 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1066 explicit_complement(res
);
1067 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1068 explicit_complement(e1
);
1069 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1070 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1073 if (res
->x
.p
->size
< 3)
1074 explicit_complement(res
);
1075 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1076 eadd(e1
, &res
->x
.p
->arr
[i
]);
1079 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1080 /* adding to evalues of different type. two cases are possible
1081 * res is periodic and e1 is polynomial, you have to exchange
1082 * e1 and res then to add e1 to the constant term of res */
1083 if (e1
->x
.p
->type
== polynomial
) {
1084 eadd_rev_cst(e1
, res
);
1086 else if (res
->x
.p
->type
== polynomial
) {
1087 /* res is polynomial and e1 is periodic,
1088 add e1 to the constant term of res */
1090 eadd(e1
,&res
->x
.p
->arr
[0]);
1096 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1097 ((res
->x
.p
->type
== fractional
||
1098 res
->x
.p
->type
== flooring
) &&
1099 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1100 /* adding evalues of different position (i.e function of different unknowns
1101 * to case are possible */
1103 switch (res
->x
.p
->type
) {
1106 if(mod_term_smaller(res
, e1
))
1107 eadd(e1
,&res
->x
.p
->arr
[1]);
1109 eadd_rev_cst(e1
, res
);
1111 case polynomial
: // res and e1 are polynomials
1112 // add e1 to the constant term of res
1114 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1115 eadd(e1
,&res
->x
.p
->arr
[0]);
1117 eadd_rev_cst(e1
, res
);
1118 // value_clear(g); value_clear(m1); value_clear(m2);
1120 case periodic
: // res and e1 are pointers to periodic numbers
1121 //add e1 to all elements of res
1123 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1124 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1125 eadd(e1
,&res
->x
.p
->arr
[i
]);
1136 //same type , same pos and same size
1137 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1138 // add any element in e1 to the corresponding element in res
1139 i
= type_offset(res
->x
.p
);
1141 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1142 for (; i
<res
->x
.p
->size
; i
++) {
1143 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1148 /* Sizes are different */
1149 switch(res
->x
.p
->type
) {
1153 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1154 /* new enode and add res to that new node. If you do not do */
1155 /* that, you lose the the upper weight part of e1 ! */
1157 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1160 i
= type_offset(res
->x
.p
);
1162 assert(eequal(&e1
->x
.p
->arr
[0],
1163 &res
->x
.p
->arr
[0]));
1164 for (; i
<e1
->x
.p
->size
; i
++) {
1165 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1172 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1175 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1176 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1177 to add periodicaly elements of e1 to elements of ne, and finaly to
1182 value_init(ex
); value_init(ey
);value_init(ep
);
1185 value_set_si(ex
,e1
->x
.p
->size
);
1186 value_set_si(ey
,res
->x
.p
->size
);
1187 value_assign (ep
,*Lcm(ex
,ey
));
1188 p
=(int)mpz_get_si(ep
);
1189 ne
= (evalue
*) malloc (sizeof(evalue
));
1191 value_set_si( ne
->d
,0);
1193 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1195 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1198 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1201 value_assign(res
->d
, ne
->d
);
1207 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1216 static void emul_rev (evalue
*e1
, evalue
*res
)
1220 evalue_copy(&ev
, e1
);
1222 free_evalue_refs(res
);
1226 static void emul_poly (evalue
*e1
, evalue
*res
)
1228 int i
, j
, o
= type_offset(res
->x
.p
);
1230 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1232 value_set_si(tmp
.d
,0);
1233 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1235 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1236 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1237 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1238 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1241 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1242 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1243 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1246 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1247 emul(&res
->x
.p
->arr
[i
], &ev
);
1248 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1249 free_evalue_refs(&ev
);
1251 free_evalue_refs(res
);
1255 void emul_partitions (evalue
*e1
,evalue
*res
)
1260 s
= (struct section
*)
1261 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1262 sizeof(struct section
));
1266 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1267 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1268 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1269 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1275 /* This code is only needed because the partitions
1276 are not true partitions.
1278 for (k
= 0; k
< n
; ++k
) {
1279 if (DomainIncludes(s
[k
].D
, d
))
1281 if (DomainIncludes(d
, s
[k
].D
)) {
1282 Domain_Free(s
[k
].D
);
1283 free_evalue_refs(&s
[k
].E
);
1294 value_init(s
[n
].E
.d
);
1295 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1296 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1300 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1301 value_clear(res
->x
.p
->arr
[2*i
].d
);
1302 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1307 evalue_set_si(res
, 0, 1);
1309 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1310 for (j
= 0; j
< n
; ++j
) {
1311 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1312 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1313 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1314 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1321 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1323 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1324 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1325 * evalues is not treated here */
1327 void emul (evalue
*e1
, evalue
*res
){
1330 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1331 fprintf(stderr
, "emul: do not proced on evector type !\n");
1335 if (EVALUE_IS_ZERO(*res
))
1338 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1339 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1340 emul_partitions(e1
, res
);
1343 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1344 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1345 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1347 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1348 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1349 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1350 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1351 explicit_complement(res
);
1352 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1353 explicit_complement(e1
);
1354 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1355 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1358 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1359 emul(e1
, &res
->x
.p
->arr
[i
]);
1361 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1362 switch(e1
->x
.p
->type
) {
1364 switch(res
->x
.p
->type
) {
1366 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1367 /* Product of two polynomials of the same variable */
1372 /* Product of two polynomials of different variables */
1374 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1375 for( i
=0; i
<res
->x
.p
->size
; i
++)
1376 emul(e1
, &res
->x
.p
->arr
[i
]);
1385 /* Product of a polynomial and a periodic or fractional */
1392 switch(res
->x
.p
->type
) {
1394 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1395 /* Product of two periodics of the same parameter and period */
1397 for(i
=0; i
<res
->x
.p
->size
;i
++)
1398 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1403 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1404 /* Product of two periodics of the same parameter and different periods */
1408 value_init(x
); value_init(y
);value_init(z
);
1411 value_set_si(x
,e1
->x
.p
->size
);
1412 value_set_si(y
,res
->x
.p
->size
);
1413 value_assign (z
,*Lcm(x
,y
));
1414 lcm
=(int)mpz_get_si(z
);
1415 newp
= (evalue
*) malloc (sizeof(evalue
));
1416 value_init(newp
->d
);
1417 value_set_si( newp
->d
,0);
1418 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1419 for(i
=0;i
<lcm
;i
++) {
1420 evalue_copy(&newp
->x
.p
->arr
[i
],
1421 &res
->x
.p
->arr
[i
%iy
]);
1424 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1426 value_assign(res
->d
,newp
->d
);
1429 value_clear(x
); value_clear(y
);value_clear(z
);
1433 /* Product of two periodics of different parameters */
1435 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1436 for(i
=0; i
<res
->x
.p
->size
; i
++)
1437 emul(e1
, &(res
->x
.p
->arr
[i
]));
1445 /* Product of a periodic and a polynomial */
1447 for(i
=0; i
<res
->x
.p
->size
; i
++)
1448 emul(e1
, &(res
->x
.p
->arr
[i
]));
1455 switch(res
->x
.p
->type
) {
1457 for(i
=0; i
<res
->x
.p
->size
; i
++)
1458 emul(e1
, &(res
->x
.p
->arr
[i
]));
1465 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1466 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1467 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1470 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1471 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1475 value_set_si(d
.x
.n
, 1);
1477 /* { x }^2 == { x }/2 */
1478 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1479 assert(e1
->x
.p
->size
== 3);
1480 assert(res
->x
.p
->size
== 3);
1482 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1484 eadd(&res
->x
.p
->arr
[1], &tmp
);
1485 emul(&e1
->x
.p
->arr
[2], &tmp
);
1486 emul(&e1
->x
.p
->arr
[1], res
);
1487 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1488 free_evalue_refs(&tmp
);
1493 if(mod_term_smaller(res
, e1
))
1494 for(i
=1; i
<res
->x
.p
->size
; i
++)
1495 emul(e1
, &(res
->x
.p
->arr
[i
]));
1510 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1511 /* Product of two rational numbers */
1515 value_multiply(res
->d
,e1
->d
,res
->d
);
1516 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1517 Gcd(res
->x
.n
, res
->d
,&g
);
1518 if (value_notone_p(g
)) {
1519 value_division(res
->d
,res
->d
,g
);
1520 value_division(res
->x
.n
,res
->x
.n
,g
);
1526 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1527 /* Product of an expression (polynomial or peririodic) and a rational number */
1533 /* Product of a rationel number and an expression (polynomial or peririodic) */
1535 i
= type_offset(res
->x
.p
);
1536 for (; i
<res
->x
.p
->size
; i
++)
1537 emul(e1
, &res
->x
.p
->arr
[i
]);
1547 /* Frees mask content ! */
1548 void emask(evalue
*mask
, evalue
*res
) {
1554 if (EVALUE_IS_ZERO(*res
)) {
1555 free_evalue_refs(mask
);
1559 assert(value_zero_p(mask
->d
));
1560 assert(mask
->x
.p
->type
== partition
);
1561 assert(value_zero_p(res
->d
));
1562 assert(res
->x
.p
->type
== partition
);
1564 s
= (struct section
*)
1565 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1566 sizeof(struct section
));
1570 evalue_set_si(&mone
, -1, 1);
1573 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1574 assert(mask
->x
.p
->size
>= 2);
1575 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1576 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1578 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1580 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1589 value_init(s
[n
].E
.d
);
1590 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1594 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1595 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1598 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1599 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1600 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1601 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1603 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1604 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1610 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1611 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1613 value_init(s
[n
].E
.d
);
1614 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1615 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1621 /* Just ignore; this may have been previously masked off */
1623 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1627 free_evalue_refs(&mone
);
1628 free_evalue_refs(mask
);
1629 free_evalue_refs(res
);
1632 evalue_set_si(res
, 0, 1);
1634 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1635 for (j
= 0; j
< n
; ++j
) {
1636 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1637 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1638 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1645 void evalue_copy(evalue
*dst
, evalue
*src
)
1647 value_assign(dst
->d
, src
->d
);
1648 if(value_notzero_p(src
->d
)) {
1649 value_init(dst
->x
.n
);
1650 value_assign(dst
->x
.n
, src
->x
.n
);
1652 dst
->x
.p
= ecopy(src
->x
.p
);
1655 enode
*new_enode(enode_type type
,int size
,int pos
) {
1661 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1664 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1668 for(i
=0; i
<size
; i
++) {
1669 value_init(res
->arr
[i
].d
);
1670 value_set_si(res
->arr
[i
].d
,0);
1671 res
->arr
[i
].x
.p
= 0;
1676 enode
*ecopy(enode
*e
) {
1681 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1682 for(i
=0;i
<e
->size
;++i
) {
1683 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1684 if(value_zero_p(res
->arr
[i
].d
))
1685 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1686 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1687 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1689 value_init(res
->arr
[i
].x
.n
);
1690 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1696 int ecmp(const evalue
*e1
, const evalue
*e2
)
1702 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1706 value_multiply(m
, e1
->x
.n
, e2
->d
);
1707 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1709 if (value_lt(m
, m2
))
1711 else if (value_gt(m
, m2
))
1721 if (value_notzero_p(e1
->d
))
1723 if (value_notzero_p(e2
->d
))
1729 if (p1
->type
!= p2
->type
)
1730 return p1
->type
- p2
->type
;
1731 if (p1
->pos
!= p2
->pos
)
1732 return p1
->pos
- p2
->pos
;
1733 if (p1
->size
!= p2
->size
)
1734 return p1
->size
- p2
->size
;
1736 for (i
= p1
->size
-1; i
>= 0; --i
)
1737 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1743 int eequal(evalue
*e1
,evalue
*e2
) {
1748 if (value_ne(e1
->d
,e2
->d
))
1751 /* e1->d == e2->d */
1752 if (value_notzero_p(e1
->d
)) {
1753 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1756 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1760 /* e1->d == e2->d == 0 */
1763 if (p1
->type
!= p2
->type
) return 0;
1764 if (p1
->size
!= p2
->size
) return 0;
1765 if (p1
->pos
!= p2
->pos
) return 0;
1766 for (i
=0; i
<p1
->size
; i
++)
1767 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1772 void free_evalue_refs(evalue
*e
) {
1777 if (EVALUE_IS_DOMAIN(*e
)) {
1778 Domain_Free(EVALUE_DOMAIN(*e
));
1781 } else if (value_pos_p(e
->d
)) {
1783 /* 'e' stores a constant */
1785 value_clear(e
->x
.n
);
1788 assert(value_zero_p(e
->d
));
1791 if (!p
) return; /* null pointer */
1792 for (i
=0; i
<p
->size
; i
++) {
1793 free_evalue_refs(&(p
->arr
[i
]));
1797 } /* free_evalue_refs */
1799 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1800 Vector
* val
, evalue
*res
)
1802 unsigned nparam
= periods
->Size
;
1805 double d
= compute_evalue(e
, val
->p
);
1806 d
*= VALUE_TO_DOUBLE(m
);
1811 value_assign(res
->d
, m
);
1812 value_init(res
->x
.n
);
1813 value_set_double(res
->x
.n
, d
);
1814 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1817 if (value_one_p(periods
->p
[p
]))
1818 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1823 value_assign(tmp
, periods
->p
[p
]);
1824 value_set_si(res
->d
, 0);
1825 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1827 value_decrement(tmp
, tmp
);
1828 value_assign(val
->p
[p
], tmp
);
1829 mod2table_r(e
, periods
, m
, p
+1, val
,
1830 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1831 } while (value_pos_p(tmp
));
1837 static void rel2table(evalue
*e
, int zero
)
1839 if (value_pos_p(e
->d
)) {
1840 if (value_zero_p(e
->x
.n
) == zero
)
1841 value_set_si(e
->x
.n
, 1);
1843 value_set_si(e
->x
.n
, 0);
1844 value_set_si(e
->d
, 1);
1847 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1848 rel2table(&e
->x
.p
->arr
[i
], zero
);
1852 void evalue_mod2table(evalue
*e
, int nparam
)
1857 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1860 for (i
=0; i
<p
->size
; i
++) {
1861 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1863 if (p
->type
== relation
) {
1868 evalue_copy(©
, &p
->arr
[0]);
1870 rel2table(&p
->arr
[0], 1);
1871 emul(&p
->arr
[0], &p
->arr
[1]);
1873 rel2table(©
, 0);
1874 emul(©
, &p
->arr
[2]);
1875 eadd(&p
->arr
[2], &p
->arr
[1]);
1876 free_evalue_refs(&p
->arr
[2]);
1877 free_evalue_refs(©
);
1879 free_evalue_refs(&p
->arr
[0]);
1883 } else if (p
->type
== fractional
) {
1884 Vector
*periods
= Vector_Alloc(nparam
);
1885 Vector
*val
= Vector_Alloc(nparam
);
1891 value_set_si(tmp
, 1);
1892 Vector_Set(periods
->p
, 1, nparam
);
1893 Vector_Set(val
->p
, 0, nparam
);
1894 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1897 assert(p
->type
== polynomial
);
1898 assert(p
->size
== 2);
1899 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
1900 Lcm3(tmp
, p
->arr
[1].d
, &tmp
);
1903 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1906 evalue_set_si(&res
, 0, 1);
1907 /* Compute the polynomial using Horner's rule */
1908 for (i
=p
->size
-1;i
>1;i
--) {
1909 eadd(&p
->arr
[i
], &res
);
1912 eadd(&p
->arr
[1], &res
);
1914 free_evalue_refs(e
);
1915 free_evalue_refs(&EP
);
1920 Vector_Free(periods
);
1922 } /* evalue_mod2table */
1924 /********************************************************/
1925 /* function in domain */
1926 /* check if the parameters in list_args */
1927 /* verifies the constraints of Domain P */
1928 /********************************************************/
1929 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1932 Value v
; /* value of the constraint of a row when
1933 parameters are instanciated*/
1939 /*P->Constraint constraint matrice of polyhedron P*/
1940 for(row
=0;row
<P
->NbConstraints
;row
++) {
1941 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1942 for(col
=1;col
<P
->Dimension
+1;col
++) {
1943 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1944 value_addto(v
,v
,tmp
);
1946 if (value_notzero_p(P
->Constraint
[row
][0])) {
1948 /*if v is not >=0 then this constraint is not respected */
1949 if (value_neg_p(v
)) {
1953 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1958 /*if v is not = 0 then this constraint is not respected */
1959 if (value_notzero_p(v
))
1964 /*if not return before this point => all
1965 the constraints are respected */
1971 /****************************************************/
1972 /* function compute enode */
1973 /* compute the value of enode p with parameters */
1974 /* list "list_args */
1975 /* compute the polynomial or the periodic */
1976 /****************************************************/
1978 static double compute_enode(enode
*p
, Value
*list_args
) {
1990 if (p
->type
== polynomial
) {
1992 value_assign(param
,list_args
[p
->pos
-1]);
1994 /* Compute the polynomial using Horner's rule */
1995 for (i
=p
->size
-1;i
>0;i
--) {
1996 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1997 res
*=VALUE_TO_DOUBLE(param
);
1999 res
+=compute_evalue(&p
->arr
[0],list_args
);
2001 else if (p
->type
== fractional
) {
2002 double d
= compute_evalue(&p
->arr
[0], list_args
);
2003 d
-= floor(d
+1e-10);
2005 /* Compute the polynomial using Horner's rule */
2006 for (i
=p
->size
-1;i
>1;i
--) {
2007 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2010 res
+=compute_evalue(&p
->arr
[1],list_args
);
2012 else if (p
->type
== flooring
) {
2013 double d
= compute_evalue(&p
->arr
[0], list_args
);
2016 /* Compute the polynomial using Horner's rule */
2017 for (i
=p
->size
-1;i
>1;i
--) {
2018 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2021 res
+=compute_evalue(&p
->arr
[1],list_args
);
2023 else if (p
->type
== periodic
) {
2024 value_assign(param
,list_args
[p
->pos
-1]);
2026 /* Choose the right element of the periodic */
2027 value_absolute(m
,param
);
2028 value_set_si(param
,p
->size
);
2029 value_modulus(m
,m
,param
);
2030 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2032 else if (p
->type
== relation
) {
2033 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2034 res
= compute_evalue(&p
->arr
[1], list_args
);
2035 else if (p
->size
> 2)
2036 res
= compute_evalue(&p
->arr
[2], list_args
);
2038 else if (p
->type
== partition
) {
2039 for (i
= 0; i
< p
->size
/2; ++i
)
2040 if (in_domain(EVALUE_DOMAIN(p
->arr
[2*i
]), list_args
)) {
2041 res
= compute_evalue(&p
->arr
[2*i
+1], list_args
);
2050 } /* compute_enode */
2052 /*************************************************/
2053 /* return the value of Ehrhart Polynomial */
2054 /* It returns a double, because since it is */
2055 /* a recursive function, some intermediate value */
2056 /* might not be integral */
2057 /*************************************************/
2059 double compute_evalue(evalue
*e
,Value
*list_args
) {
2063 if (value_notzero_p(e
->d
)) {
2064 if (value_notone_p(e
->d
))
2065 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2067 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2070 res
= compute_enode(e
->x
.p
,list_args
);
2072 } /* compute_evalue */
2075 /****************************************************/
2076 /* function compute_poly : */
2077 /* Check for the good validity domain */
2078 /* return the number of point in the Polyhedron */
2079 /* in allocated memory */
2080 /* Using the Ehrhart pseudo-polynomial */
2081 /****************************************************/
2082 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2085 /* double d; int i; */
2087 tmp
= (Value
*) malloc (sizeof(Value
));
2088 assert(tmp
!= NULL
);
2090 value_set_si(*tmp
,0);
2093 return(tmp
); /* no ehrhart polynomial */
2094 if(en
->ValidityDomain
) {
2095 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2096 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2101 return(tmp
); /* no Validity Domain */
2103 if(in_domain(en
->ValidityDomain
,list_args
)) {
2105 #ifdef EVAL_EHRHART_DEBUG
2106 Print_Domain(stdout
,en
->ValidityDomain
);
2107 print_evalue(stdout
,&en
->EP
);
2110 /* d = compute_evalue(&en->EP,list_args);
2112 printf("(double)%lf = %d\n", d, i ); */
2113 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2119 value_set_si(*tmp
,0);
2120 return(tmp
); /* no compatible domain with the arguments */
2121 } /* compute_poly */
2123 size_t value_size(Value v
) {
2124 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2125 * sizeof(v
[0]._mp_d
[0]);
2128 size_t domain_size(Polyhedron
*D
)
2131 size_t s
= sizeof(*D
);
2133 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2134 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2135 s
+= value_size(D
->Constraint
[i
][j
]);
2138 for (i = 0; i < D->NbRays; ++i)
2139 for (j = 0; j < D->Dimension+2; ++j)
2140 s += value_size(D->Ray[i][j]);
2143 return D
->next
? s
+domain_size(D
->next
) : s
;
2146 size_t enode_size(enode
*p
) {
2147 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2150 if (p
->type
== partition
)
2151 for (i
= 0; i
< p
->size
/2; ++i
) {
2152 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2153 s
+= evalue_size(&p
->arr
[2*i
+1]);
2156 for (i
= 0; i
< p
->size
; ++i
) {
2157 s
+= evalue_size(&p
->arr
[i
]);
2162 size_t evalue_size(evalue
*e
)
2164 size_t s
= sizeof(*e
);
2165 s
+= value_size(e
->d
);
2166 if (value_notzero_p(e
->d
))
2167 s
+= value_size(e
->x
.n
);
2169 s
+= enode_size(e
->x
.p
);
2173 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2175 evalue
*found
= NULL
;
2180 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2183 value_init(offset
.d
);
2184 value_init(offset
.x
.n
);
2185 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2186 Lcm3(m
, offset
.d
, &offset
.d
);
2187 value_set_si(offset
.x
.n
, 1);
2190 evalue_copy(©
, cst
);
2193 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2195 if (eequal(base
, &e
->x
.p
->arr
[0]))
2196 found
= &e
->x
.p
->arr
[0];
2198 value_set_si(offset
.x
.n
, -2);
2201 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2203 if (eequal(base
, &e
->x
.p
->arr
[0]))
2206 free_evalue_refs(cst
);
2207 free_evalue_refs(&offset
);
2210 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2211 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2216 static evalue
*find_relation_pair(evalue
*e
)
2219 evalue
*found
= NULL
;
2221 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2224 if (e
->x
.p
->type
== fractional
) {
2229 poly_denom(&e
->x
.p
->arr
[0], &m
);
2231 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2232 cst
= &cst
->x
.p
->arr
[0])
2235 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2236 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2241 i
= e
->x
.p
->type
== relation
;
2242 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2243 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2248 void evalue_mod2relation(evalue
*e
) {
2251 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2254 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2255 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2256 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2257 value_clear(e
->x
.p
->arr
[2*i
].d
);
2258 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2260 if (2*i
< e
->x
.p
->size
) {
2261 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2262 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2267 if (e
->x
.p
->size
== 0) {
2269 evalue_set_si(e
, 0, 1);
2275 while ((d
= find_relation_pair(e
)) != NULL
) {
2279 value_init(split
.d
);
2280 value_set_si(split
.d
, 0);
2281 split
.x
.p
= new_enode(relation
, 3, 0);
2282 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2283 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2285 ev
= &split
.x
.p
->arr
[0];
2286 value_set_si(ev
->d
, 0);
2287 ev
->x
.p
= new_enode(fractional
, 3, -1);
2288 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2289 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2290 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2296 free_evalue_refs(&split
);
2300 static int evalue_comp(const void * a
, const void * b
)
2302 const evalue
*e1
= *(const evalue
**)a
;
2303 const evalue
*e2
= *(const evalue
**)b
;
2304 return ecmp(e1
, e2
);
2307 void evalue_combine(evalue
*e
)
2314 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2317 NALLOC(evs
, e
->x
.p
->size
/2);
2318 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2319 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2320 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2321 p
= new_enode(partition
, e
->x
.p
->size
, -1);
2322 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2323 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2324 value_clear(p
->arr
[2*k
].d
);
2325 value_clear(p
->arr
[2*k
+1].d
);
2326 p
->arr
[2*k
] = *(evs
[i
]-1);
2327 p
->arr
[2*k
+1] = *(evs
[i
]);
2330 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2333 value_clear((evs
[i
]-1)->d
);
2337 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2338 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2339 free_evalue_refs(evs
[i
]);
2343 for (i
= 2*k
; i
< p
->size
; ++i
)
2344 value_clear(p
->arr
[i
].d
);
2351 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2353 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2355 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2358 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2359 Polyhedron
*D
, *N
, **P
;
2362 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2369 if (D
->NbEq
<= H
->NbEq
) {
2375 tmp
.x
.p
= new_enode(partition
, 2, -1);
2376 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2377 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2378 reduce_evalue(&tmp
);
2379 if (value_notzero_p(tmp
.d
) ||
2380 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2383 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2384 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2387 free_evalue_refs(&tmp
);
2393 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2395 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2397 value_clear(e
->x
.p
->arr
[2*i
].d
);
2398 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2400 if (2*i
< e
->x
.p
->size
) {
2401 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2402 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2409 H
= DomainConvex(D
, 0);
2410 E
= DomainDifference(H
, D
, 0);
2412 D
= DomainDifference(H
, E
, 0);
2415 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2419 /* May change coefficients to become non-standard if fiddle is set
2420 * => reduce p afterwards to correct
2422 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2423 Matrix
**R
, int fiddle
)
2427 unsigned dim
= D
->Dimension
;
2428 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2433 assert(p
->type
== fractional
);
2435 value_set_si(T
->p
[1][dim
], 1);
2437 while (value_zero_p(pp
->d
)) {
2438 assert(pp
->x
.p
->type
== polynomial
);
2439 assert(pp
->x
.p
->size
== 2);
2440 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2441 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2442 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2443 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2444 value_substract(pp
->x
.p
->arr
[1].x
.n
,
2445 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2446 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2447 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2448 pp
= &pp
->x
.p
->arr
[0];
2450 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2451 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2452 I
= DomainImage(D
, T
, 0);
2453 H
= DomainConvex(I
, 0);
2462 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 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 (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
);
2508 free_evalue_refs(&(p
->arr
[2]));
2511 free_evalue_refs(&(p
->arr
[0]));
2517 return reduce_in_domain(e
, D
);
2518 } else if (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 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 (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 (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
) {
3131 char *test
[] = { "A", "B", "C", "D", "E", "F", "G" };
3133 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3134 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3135 Polyhedron_Print(stderr
, P_VALUE_FMT
, EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3136 print_evalue(stderr
, t
, test
);
3138 free_evalue_refs(t
);