6 #include "ev_operations.h"
10 #ifndef value_pmodulus
11 #define value_pmodulus(ref,val1,val2) (mpz_fdiv_r((ref),(val1),(val2)))
15 #define ALLOC(p) p = (typeof(p))malloc(sizeof(*p))
16 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
18 #define ALLOC(p) p = (void *)malloc(sizeof(*p))
19 #define NALLOC(p,n) p = (void *)malloc((n) * sizeof(*p))
22 void evalue_set_si(evalue
*ev
, int n
, int d
) {
23 value_set_si(ev
->d
, d
);
25 value_set_si(ev
->x
.n
, n
);
28 void evalue_set(evalue
*ev
, Value n
, Value d
) {
29 value_assign(ev
->d
, d
);
31 value_assign(ev
->x
.n
, n
);
34 void aep_evalue(evalue
*e
, int *ref
) {
39 if (value_notzero_p(e
->d
))
40 return; /* a rational number, its already reduced */
42 return; /* hum... an overflow probably occured */
44 /* First check the components of p */
45 for (i
=0;i
<p
->size
;i
++)
46 aep_evalue(&p
->arr
[i
],ref
);
53 p
->pos
= ref
[p
->pos
-1]+1;
59 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
65 if (value_notzero_p(e
->d
))
66 return; /* a rational number, its already reduced */
68 return; /* hum... an overflow probably occured */
71 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
72 for(i
=0;i
<CT
->NbRows
-1;i
++)
73 for(j
=0;j
<CT
->NbColumns
;j
++)
74 if(value_notzero_p(CT
->p
[i
][j
])) {
79 /* Transform the references in e, using ref */
83 } /* addeliminatedparams_evalue */
85 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
86 unsigned MaxRays
, unsigned nparam
)
91 if (CT
->NbRows
== CT
->NbColumns
)
94 if (EVALUE_IS_ZERO(*e
))
97 if (value_notzero_p(e
->d
)) {
100 value_set_si(res
.d
, 0);
101 res
.x
.p
= new_enode(partition
, 2, nparam
);
102 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
103 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
104 value_clear(res
.x
.p
->arr
[1].d
);
105 res
.x
.p
->arr
[1] = *e
;
112 assert(p
->type
== partition
);
115 for (i
=0; i
<p
->size
/2; i
++) {
116 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
117 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
120 T
= DomainIntersection(D
, CEq
, MaxRays
);
122 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
123 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
127 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
135 assert(value_notzero_p(e1
->d
));
136 assert(value_notzero_p(e2
->d
));
137 value_multiply(m
, e1
->x
.n
, e2
->d
);
138 value_multiply(m2
, e2
->x
.n
, e1
->d
);
141 else if (value_gt(m
, m2
))
151 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
153 if (value_notzero_p(e1
->d
)) {
155 if (value_zero_p(e2
->d
))
157 r
= mod_rational_smaller(e1
, e2
);
158 return r
== -1 ? 0 : r
;
160 if (value_notzero_p(e2
->d
))
162 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
164 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
167 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
169 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
174 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
176 assert(value_zero_p(e1
->d
));
177 assert(value_zero_p(e2
->d
));
178 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
179 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
180 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
183 /* Negative pos means inequality */
184 /* s is negative of substitution if m is not zero */
193 struct fixed_param
*fixed
;
198 static int relations_depth(evalue
*e
)
203 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
204 e
= &e
->x
.p
->arr
[1], ++d
);
208 static void poly_denom_not_constant(evalue
**pp
, Value
*d
)
213 while (value_zero_p(p
->d
)) {
214 assert(p
->x
.p
->type
== polynomial
);
215 assert(p
->x
.p
->size
== 2);
216 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
217 value_lcm(*d
, p
->x
.p
->arr
[1].d
, d
);
223 static void poly_denom(evalue
*p
, Value
*d
)
225 poly_denom_not_constant(&p
, d
);
226 value_lcm(*d
, p
->d
, d
);
229 #define EVALUE_IS_ONE(ev) (value_one_p((ev).d) && value_one_p((ev).x.n))
231 static void realloc_substitution(struct subst
*s
, int d
)
233 struct fixed_param
*n
;
236 for (i
= 0; i
< s
->n
; ++i
)
243 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
249 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
252 /* May have been reduced already */
253 if (value_notzero_p(m
->d
))
256 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
257 assert(m
->x
.p
->size
== 3);
259 /* fractional was inverted during reduction
260 * invert it back and move constant in
262 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
263 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
264 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
265 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
266 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
267 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
268 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
269 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
270 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
271 value_set_si(m
->x
.p
->arr
[1].d
, 1);
274 /* Oops. Nested identical relations. */
275 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
278 if (s
->n
>= s
->max
) {
279 int d
= relations_depth(r
);
280 realloc_substitution(s
, d
);
284 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
285 assert(p
->x
.p
->size
== 2);
288 assert(value_pos_p(f
->x
.n
));
290 value_init(s
->fixed
[s
->n
].m
);
291 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
292 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
293 value_init(s
->fixed
[s
->n
].d
);
294 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
295 value_init(s
->fixed
[s
->n
].s
.d
);
296 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
302 static int type_offset(enode
*p
)
304 return p
->type
== fractional
? 1 :
305 p
->type
== flooring
? 1 : 0;
308 static void reorder_terms(enode
*p
, evalue
*v
)
311 int offset
= type_offset(p
);
313 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
315 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
316 free_evalue_refs(&(p
->arr
[i
]));
322 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
328 if (value_notzero_p(e
->d
)) {
330 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
331 return; /* a rational number, its already reduced */
335 return; /* hum... an overflow probably occured */
337 /* First reduce the components of p */
338 add
= p
->type
== relation
;
339 for (i
=0; i
<p
->size
; i
++) {
341 add
= add_modulo_substitution(s
, e
);
343 if (i
== 0 && p
->type
==fractional
)
344 _reduce_evalue(&p
->arr
[i
], s
, 1);
346 _reduce_evalue(&p
->arr
[i
], s
, fract
);
348 if (add
&& i
== p
->size
-1) {
350 value_clear(s
->fixed
[s
->n
].m
);
351 value_clear(s
->fixed
[s
->n
].d
);
352 free_evalue_refs(&s
->fixed
[s
->n
].s
);
353 } else if (add
&& i
== 1)
354 s
->fixed
[s
->n
-1].pos
*= -1;
357 if (p
->type
==periodic
) {
359 /* Try to reduce the period */
360 for (i
=1; i
<=(p
->size
)/2; i
++) {
361 if ((p
->size
% i
)==0) {
363 /* Can we reduce the size to i ? */
365 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
366 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
369 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
373 you_lose
: /* OK, lets not do it */
378 /* Try to reduce its strength */
381 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
385 else if (p
->type
==polynomial
) {
386 for (k
= 0; s
&& k
< s
->n
; ++k
) {
387 if (s
->fixed
[k
].pos
== p
->pos
) {
388 int divide
= value_notone_p(s
->fixed
[k
].d
);
391 if (value_notzero_p(s
->fixed
[k
].m
)) {
394 assert(p
->size
== 2);
395 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
397 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
404 value_assign(d
.d
, s
->fixed
[k
].d
);
406 if (value_notzero_p(s
->fixed
[k
].m
))
407 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
409 value_set_si(d
.x
.n
, 1);
412 for (i
=p
->size
-1;i
>=1;i
--) {
413 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
415 emul(&d
, &p
->arr
[i
]);
416 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
417 free_evalue_refs(&(p
->arr
[i
]));
420 _reduce_evalue(&p
->arr
[0], s
, fract
);
423 free_evalue_refs(&d
);
429 /* Try to reduce the degree */
430 for (i
=p
->size
-1;i
>=1;i
--) {
431 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
433 /* Zero coefficient */
434 free_evalue_refs(&(p
->arr
[i
]));
439 /* Try to reduce its strength */
442 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
446 else if (p
->type
==fractional
) {
450 if (value_notzero_p(p
->arr
[0].d
)) {
452 value_assign(v
.d
, p
->arr
[0].d
);
454 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
459 evalue
*pp
= &p
->arr
[0];
460 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
461 assert(pp
->x
.p
->size
== 2);
463 /* search for exact duplicate among the modulo inequalities */
465 f
= &pp
->x
.p
->arr
[1];
466 for (k
= 0; s
&& k
< s
->n
; ++k
) {
467 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
468 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
469 value_eq(s
->fixed
[k
].m
, f
->d
) &&
470 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
477 /* replace { E/m } by { (E-1)/m } + 1/m */
482 evalue_set_si(&extra
, 1, 1);
483 value_assign(extra
.d
, g
);
484 eadd(&extra
, &v
.x
.p
->arr
[1]);
485 free_evalue_refs(&extra
);
487 /* We've been going in circles; stop now */
488 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
489 free_evalue_refs(&v
);
491 evalue_set_si(&v
, 0, 1);
496 value_set_si(v
.d
, 0);
497 v
.x
.p
= new_enode(fractional
, 3, -1);
498 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
499 value_assign(v
.x
.p
->arr
[1].d
, g
);
500 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
501 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
504 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
507 value_division(f
->d
, g
, f
->d
);
508 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
509 value_assign(f
->d
, g
);
510 value_decrement(f
->x
.n
, f
->x
.n
);
511 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
513 Gcd(f
->d
, f
->x
.n
, &g
);
514 value_division(f
->d
, f
->d
, g
);
515 value_division(f
->x
.n
, f
->x
.n
, g
);
524 /* reduction may have made this fractional arg smaller */
525 i
= reorder
? p
->size
: 1;
526 for ( ; i
< p
->size
; ++i
)
527 if (value_zero_p(p
->arr
[i
].d
) &&
528 p
->arr
[i
].x
.p
->type
== fractional
&&
529 !mod_term_smaller(e
, &p
->arr
[i
]))
533 value_set_si(v
.d
, 0);
534 v
.x
.p
= new_enode(fractional
, 3, -1);
535 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
536 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
537 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
545 evalue
*pp
= &p
->arr
[0];
548 poly_denom_not_constant(&pp
, &m
);
549 mpz_fdiv_r(r
, m
, pp
->d
);
550 if (value_notzero_p(r
)) {
552 value_set_si(v
.d
, 0);
553 v
.x
.p
= new_enode(fractional
, 3, -1);
555 value_multiply(r
, m
, pp
->x
.n
);
556 value_multiply(v
.x
.p
->arr
[1].d
, m
, pp
->d
);
557 value_init(v
.x
.p
->arr
[1].x
.n
);
558 mpz_fdiv_r(v
.x
.p
->arr
[1].x
.n
, r
, pp
->d
);
559 mpz_fdiv_q(r
, r
, pp
->d
);
561 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
562 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
564 while (value_zero_p(pp
->d
))
565 pp
= &pp
->x
.p
->arr
[0];
567 value_assign(pp
->d
, m
);
568 value_assign(pp
->x
.n
, r
);
570 Gcd(pp
->d
, pp
->x
.n
, &r
);
571 value_division(pp
->d
, pp
->d
, r
);
572 value_division(pp
->x
.n
, pp
->x
.n
, r
);
585 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
586 pp
= &pp
->x
.p
->arr
[0]) {
587 f
= &pp
->x
.p
->arr
[1];
588 assert(value_pos_p(f
->d
));
589 mpz_mul_ui(twice
, f
->x
.n
, 2);
590 if (value_lt(twice
, f
->d
))
592 if (value_eq(twice
, f
->d
))
600 value_set_si(v
.d
, 0);
601 v
.x
.p
= new_enode(fractional
, 3, -1);
602 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
603 poly_denom(&p
->arr
[0], &twice
);
604 value_assign(v
.x
.p
->arr
[1].d
, twice
);
605 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
606 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
607 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
609 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
610 pp
= &pp
->x
.p
->arr
[0]) {
611 f
= &pp
->x
.p
->arr
[1];
612 value_oppose(f
->x
.n
, f
->x
.n
);
613 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
615 value_division(pp
->d
, twice
, pp
->d
);
616 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
617 value_assign(pp
->d
, twice
);
618 value_oppose(pp
->x
.n
, pp
->x
.n
);
619 value_decrement(pp
->x
.n
, pp
->x
.n
);
620 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
630 reorder_terms(p
, &v
);
631 _reduce_evalue(&p
->arr
[1], s
, fract
);
634 /* Try to reduce the degree */
635 for (i
=p
->size
-1;i
>=2;i
--) {
636 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
638 /* Zero coefficient */
639 free_evalue_refs(&(p
->arr
[i
]));
644 /* Try to reduce its strength */
647 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
648 free_evalue_refs(&(p
->arr
[0]));
652 else if (p
->type
== flooring
) {
653 /* Try to reduce the degree */
654 for (i
=p
->size
-1;i
>=2;i
--) {
655 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
657 /* Zero coefficient */
658 free_evalue_refs(&(p
->arr
[i
]));
663 /* Try to reduce its strength */
666 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
667 free_evalue_refs(&(p
->arr
[0]));
671 else if (p
->type
== relation
) {
672 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
673 free_evalue_refs(&(p
->arr
[2]));
674 free_evalue_refs(&(p
->arr
[0]));
681 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
682 free_evalue_refs(&(p
->arr
[2]));
685 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
686 free_evalue_refs(&(p
->arr
[1]));
687 free_evalue_refs(&(p
->arr
[0]));
688 evalue_set_si(e
, 0, 1);
695 /* Relation was reduced by means of an identical
696 * inequality => remove
698 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
701 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
702 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
704 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
706 free_evalue_refs(&(p
->arr
[2]));
710 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
712 evalue_set_si(e
, 0, 1);
713 free_evalue_refs(&(p
->arr
[1]));
715 free_evalue_refs(&(p
->arr
[0]));
721 } /* reduce_evalue */
723 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
728 for (k
= 0; k
< dim
; ++k
)
729 if (value_notzero_p(row
[k
+1]))
732 Vector_Normalize_Positive(row
+1, dim
+1, k
);
733 assert(s
->n
< s
->max
);
734 value_init(s
->fixed
[s
->n
].d
);
735 value_init(s
->fixed
[s
->n
].m
);
736 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
737 s
->fixed
[s
->n
].pos
= k
+1;
738 value_set_si(s
->fixed
[s
->n
].m
, 0);
739 r
= &s
->fixed
[s
->n
].s
;
741 for (l
= k
+1; l
< dim
; ++l
)
742 if (value_notzero_p(row
[l
+1])) {
743 value_set_si(r
->d
, 0);
744 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
745 value_init(r
->x
.p
->arr
[1].x
.n
);
746 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
747 value_set_si(r
->x
.p
->arr
[1].d
, 1);
751 value_oppose(r
->x
.n
, row
[dim
+1]);
752 value_set_si(r
->d
, 1);
756 void reduce_evalue (evalue
*e
) {
757 struct subst s
= { NULL
, 0, 0 };
759 if (value_notzero_p(e
->d
))
760 return; /* a rational number, its already reduced */
762 if (e
->x
.p
->type
== partition
) {
765 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
766 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
768 /* This shouldn't really happen;
769 * Empty domains should not be added.
776 D
= DomainConvex(D
, 0);
777 if (!D
->next
&& D
->NbEq
) {
781 realloc_substitution(&s
, dim
);
783 int d
= relations_depth(&e
->x
.p
->arr
[2*i
+1]);
785 NALLOC(s
.fixed
, s
.max
);
788 for (j
= 0; j
< D
->NbEq
; ++j
)
789 add_substitution(&s
, D
->Constraint
[j
], dim
);
791 if (D
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
793 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
794 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
796 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
797 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
798 value_clear(e
->x
.p
->arr
[2*i
].d
);
800 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
801 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
806 for (j
= 0; j
< s
.n
; ++j
) {
807 value_clear(s
.fixed
[j
].d
);
808 value_clear(s
.fixed
[j
].m
);
809 free_evalue_refs(&s
.fixed
[j
].s
);
813 if (e
->x
.p
->size
== 0) {
815 evalue_set_si(e
, 0, 1);
818 _reduce_evalue(e
, &s
, 0);
823 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
825 if(value_notzero_p(e
->d
)) {
826 if(value_notone_p(e
->d
)) {
827 value_print(DST
,VALUE_FMT
,e
->x
.n
);
829 value_print(DST
,VALUE_FMT
,e
->d
);
832 value_print(DST
,VALUE_FMT
,e
->x
.n
);
836 print_enode(DST
,e
->x
.p
,pname
);
840 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
845 fprintf(DST
, "NULL");
851 for (i
=0; i
<p
->size
; i
++) {
852 print_evalue(DST
, &p
->arr
[i
], pname
);
856 fprintf(DST
, " }\n");
860 for (i
=p
->size
-1; i
>=0; i
--) {
861 print_evalue(DST
, &p
->arr
[i
], pname
);
862 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
864 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
866 fprintf(DST
, " )\n");
870 for (i
=0; i
<p
->size
; i
++) {
871 print_evalue(DST
, &p
->arr
[i
], pname
);
872 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
874 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
879 for (i
=p
->size
-1; i
>=1; i
--) {
880 print_evalue(DST
, &p
->arr
[i
], pname
);
883 fprintf(DST
, p
->type
== flooring
? "[" : "{");
884 print_evalue(DST
, &p
->arr
[0], pname
);
885 fprintf(DST
, p
->type
== flooring
? "]" : "}");
887 fprintf(DST
, "^%d + ", i
-1);
892 fprintf(DST
, " )\n");
896 print_evalue(DST
, &p
->arr
[0], pname
);
897 fprintf(DST
, "= 0 ] * \n");
898 print_evalue(DST
, &p
->arr
[1], pname
);
900 fprintf(DST
, " +\n [ ");
901 print_evalue(DST
, &p
->arr
[0], pname
);
902 fprintf(DST
, "!= 0 ] * \n");
903 print_evalue(DST
, &p
->arr
[2], pname
);
907 char **names
= pname
;
908 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
909 if (p
->pos
< maxdim
) {
910 NALLOC(names
, maxdim
);
911 for (i
= 0; i
< p
->pos
; ++i
)
913 for ( ; i
< maxdim
; ++i
) {
914 NALLOC(names
[i
], 10);
915 snprintf(names
[i
], 10, "_p%d", i
);
919 for (i
=0; i
<p
->size
/2; i
++) {
920 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
921 print_evalue(DST
, &p
->arr
[2*i
+1], names
);
924 if (p
->pos
< maxdim
) {
925 for (i
= p
->pos
; i
< maxdim
; ++i
)
938 static void eadd_rev(evalue
*e1
, evalue
*res
)
942 evalue_copy(&ev
, e1
);
944 free_evalue_refs(res
);
948 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
952 evalue_copy(&ev
, e1
);
953 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
954 free_evalue_refs(res
);
958 struct section
{ Polyhedron
* D
; evalue E
; };
960 void eadd_partitions (evalue
*e1
,evalue
*res
)
965 s
= (struct section
*)
966 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
967 sizeof(struct section
));
969 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
970 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
971 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
974 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
975 assert(res
->x
.p
->size
>= 2);
976 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
977 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
979 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
981 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
990 value_init(s
[n
].E
.d
);
991 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
995 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
996 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
997 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
999 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1000 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1006 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1007 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1009 value_init(s
[n
].E
.d
);
1010 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1011 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1016 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1020 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1023 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1024 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1025 value_clear(res
->x
.p
->arr
[2*i
].d
);
1030 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1031 for (j
= 0; j
< n
; ++j
) {
1032 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1033 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1034 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1035 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1041 static void explicit_complement(evalue
*res
)
1043 enode
*rel
= new_enode(relation
, 3, 0);
1045 value_clear(rel
->arr
[0].d
);
1046 rel
->arr
[0] = res
->x
.p
->arr
[0];
1047 value_clear(rel
->arr
[1].d
);
1048 rel
->arr
[1] = res
->x
.p
->arr
[1];
1049 value_set_si(rel
->arr
[2].d
, 1);
1050 value_init(rel
->arr
[2].x
.n
);
1051 value_set_si(rel
->arr
[2].x
.n
, 0);
1056 void eadd(evalue
*e1
,evalue
*res
) {
1059 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1060 /* Add two rational numbers */
1066 value_multiply(m1
,e1
->x
.n
,res
->d
);
1067 value_multiply(m2
,res
->x
.n
,e1
->d
);
1068 value_addto(res
->x
.n
,m1
,m2
);
1069 value_multiply(res
->d
,e1
->d
,res
->d
);
1070 Gcd(res
->x
.n
,res
->d
,&g
);
1071 if (value_notone_p(g
)) {
1072 value_division(res
->d
,res
->d
,g
);
1073 value_division(res
->x
.n
,res
->x
.n
,g
);
1075 value_clear(g
); value_clear(m1
); value_clear(m2
);
1078 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1079 switch (res
->x
.p
->type
) {
1081 /* Add the constant to the constant term of a polynomial*/
1082 eadd(e1
, &res
->x
.p
->arr
[0]);
1085 /* Add the constant to all elements of a periodic number */
1086 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1087 eadd(e1
, &res
->x
.p
->arr
[i
]);
1091 fprintf(stderr
, "eadd: cannot add const with vector\n");
1095 eadd(e1
, &res
->x
.p
->arr
[1]);
1098 assert(EVALUE_IS_ZERO(*e1
));
1099 break; /* Do nothing */
1101 /* Create (zero) complement if needed */
1102 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1103 explicit_complement(res
);
1104 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1105 eadd(e1
, &res
->x
.p
->arr
[i
]);
1111 /* add polynomial or periodic to constant
1112 * you have to exchange e1 and res, before doing addition */
1114 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1118 else { // ((e1->d==0) && (res->d==0))
1119 assert(!((e1
->x
.p
->type
== partition
) ^
1120 (res
->x
.p
->type
== partition
)));
1121 if (e1
->x
.p
->type
== partition
) {
1122 eadd_partitions(e1
, res
);
1125 if (e1
->x
.p
->type
== relation
&&
1126 (res
->x
.p
->type
!= relation
||
1127 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1131 if (res
->x
.p
->type
== relation
) {
1132 if (e1
->x
.p
->type
== relation
&&
1133 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1134 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1135 explicit_complement(res
);
1136 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1137 explicit_complement(e1
);
1138 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1139 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1142 if (res
->x
.p
->size
< 3)
1143 explicit_complement(res
);
1144 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1145 eadd(e1
, &res
->x
.p
->arr
[i
]);
1148 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1149 /* adding to evalues of different type. two cases are possible
1150 * res is periodic and e1 is polynomial, you have to exchange
1151 * e1 and res then to add e1 to the constant term of res */
1152 if (e1
->x
.p
->type
== polynomial
) {
1153 eadd_rev_cst(e1
, res
);
1155 else if (res
->x
.p
->type
== polynomial
) {
1156 /* res is polynomial and e1 is periodic,
1157 add e1 to the constant term of res */
1159 eadd(e1
,&res
->x
.p
->arr
[0]);
1165 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1166 ((res
->x
.p
->type
== fractional
||
1167 res
->x
.p
->type
== flooring
) &&
1168 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1169 /* adding evalues of different position (i.e function of different unknowns
1170 * to case are possible */
1172 switch (res
->x
.p
->type
) {
1175 if(mod_term_smaller(res
, e1
))
1176 eadd(e1
,&res
->x
.p
->arr
[1]);
1178 eadd_rev_cst(e1
, res
);
1180 case polynomial
: // res and e1 are polynomials
1181 // add e1 to the constant term of res
1183 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1184 eadd(e1
,&res
->x
.p
->arr
[0]);
1186 eadd_rev_cst(e1
, res
);
1187 // value_clear(g); value_clear(m1); value_clear(m2);
1189 case periodic
: // res and e1 are pointers to periodic numbers
1190 //add e1 to all elements of res
1192 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1193 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1194 eadd(e1
,&res
->x
.p
->arr
[i
]);
1205 //same type , same pos and same size
1206 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1207 // add any element in e1 to the corresponding element in res
1208 i
= type_offset(res
->x
.p
);
1210 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1211 for (; i
<res
->x
.p
->size
; i
++) {
1212 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1217 /* Sizes are different */
1218 switch(res
->x
.p
->type
) {
1222 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1223 /* new enode and add res to that new node. If you do not do */
1224 /* that, you lose the the upper weight part of e1 ! */
1226 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1229 i
= type_offset(res
->x
.p
);
1231 assert(eequal(&e1
->x
.p
->arr
[0],
1232 &res
->x
.p
->arr
[0]));
1233 for (; i
<e1
->x
.p
->size
; i
++) {
1234 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1241 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1244 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1245 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1246 to add periodicaly elements of e1 to elements of ne, and finaly to
1251 value_init(ex
); value_init(ey
);value_init(ep
);
1254 value_set_si(ex
,e1
->x
.p
->size
);
1255 value_set_si(ey
,res
->x
.p
->size
);
1256 value_assign (ep
,*Lcm(ex
,ey
));
1257 p
=(int)mpz_get_si(ep
);
1258 ne
= (evalue
*) malloc (sizeof(evalue
));
1260 value_set_si( ne
->d
,0);
1262 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1264 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1267 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1270 value_assign(res
->d
, ne
->d
);
1276 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1285 static void emul_rev (evalue
*e1
, evalue
*res
)
1289 evalue_copy(&ev
, e1
);
1291 free_evalue_refs(res
);
1295 static void emul_poly (evalue
*e1
, evalue
*res
)
1297 int i
, j
, o
= type_offset(res
->x
.p
);
1299 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1301 value_set_si(tmp
.d
,0);
1302 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1304 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1305 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1306 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1307 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1310 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1311 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1312 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1315 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1316 emul(&res
->x
.p
->arr
[i
], &ev
);
1317 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1318 free_evalue_refs(&ev
);
1320 free_evalue_refs(res
);
1324 void emul_partitions (evalue
*e1
,evalue
*res
)
1329 s
= (struct section
*)
1330 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1331 sizeof(struct section
));
1333 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1334 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1335 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1338 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1339 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1340 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1341 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1347 /* This code is only needed because the partitions
1348 are not true partitions.
1350 for (k
= 0; k
< n
; ++k
) {
1351 if (DomainIncludes(s
[k
].D
, d
))
1353 if (DomainIncludes(d
, s
[k
].D
)) {
1354 Domain_Free(s
[k
].D
);
1355 free_evalue_refs(&s
[k
].E
);
1366 value_init(s
[n
].E
.d
);
1367 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1368 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1372 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1373 value_clear(res
->x
.p
->arr
[2*i
].d
);
1374 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1379 evalue_set_si(res
, 0, 1);
1381 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1382 for (j
= 0; j
< n
; ++j
) {
1383 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1384 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1385 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1386 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1393 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1395 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1396 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1397 * evalues is not treated here */
1399 void emul (evalue
*e1
, evalue
*res
){
1402 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1403 fprintf(stderr
, "emul: do not proced on evector type !\n");
1407 if (EVALUE_IS_ZERO(*res
))
1410 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1411 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1412 emul_partitions(e1
, res
);
1415 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1416 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1417 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1419 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1420 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1421 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1422 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1423 explicit_complement(res
);
1424 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1425 explicit_complement(e1
);
1426 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1427 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1430 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1431 emul(e1
, &res
->x
.p
->arr
[i
]);
1433 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1434 switch(e1
->x
.p
->type
) {
1436 switch(res
->x
.p
->type
) {
1438 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1439 /* Product of two polynomials of the same variable */
1444 /* Product of two polynomials of different variables */
1446 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1447 for( i
=0; i
<res
->x
.p
->size
; i
++)
1448 emul(e1
, &res
->x
.p
->arr
[i
]);
1457 /* Product of a polynomial and a periodic or fractional */
1464 switch(res
->x
.p
->type
) {
1466 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1467 /* Product of two periodics of the same parameter and period */
1469 for(i
=0; i
<res
->x
.p
->size
;i
++)
1470 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1475 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1476 /* Product of two periodics of the same parameter and different periods */
1480 value_init(x
); value_init(y
);value_init(z
);
1483 value_set_si(x
,e1
->x
.p
->size
);
1484 value_set_si(y
,res
->x
.p
->size
);
1485 value_assign (z
,*Lcm(x
,y
));
1486 lcm
=(int)mpz_get_si(z
);
1487 newp
= (evalue
*) malloc (sizeof(evalue
));
1488 value_init(newp
->d
);
1489 value_set_si( newp
->d
,0);
1490 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1491 for(i
=0;i
<lcm
;i
++) {
1492 evalue_copy(&newp
->x
.p
->arr
[i
],
1493 &res
->x
.p
->arr
[i
%iy
]);
1496 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1498 value_assign(res
->d
,newp
->d
);
1501 value_clear(x
); value_clear(y
);value_clear(z
);
1505 /* Product of two periodics of different parameters */
1507 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1508 for(i
=0; i
<res
->x
.p
->size
; i
++)
1509 emul(e1
, &(res
->x
.p
->arr
[i
]));
1517 /* Product of a periodic and a polynomial */
1519 for(i
=0; i
<res
->x
.p
->size
; i
++)
1520 emul(e1
, &(res
->x
.p
->arr
[i
]));
1527 switch(res
->x
.p
->type
) {
1529 for(i
=0; i
<res
->x
.p
->size
; i
++)
1530 emul(e1
, &(res
->x
.p
->arr
[i
]));
1537 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1538 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1539 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1542 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1543 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1548 value_set_si(d
.x
.n
, 1);
1549 /* { x }^2 == { x }/2 */
1550 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1551 assert(e1
->x
.p
->size
== 3);
1552 assert(res
->x
.p
->size
== 3);
1554 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1556 eadd(&res
->x
.p
->arr
[1], &tmp
);
1557 emul(&e1
->x
.p
->arr
[2], &tmp
);
1558 emul(&e1
->x
.p
->arr
[1], res
);
1559 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1560 free_evalue_refs(&tmp
);
1565 if(mod_term_smaller(res
, e1
))
1566 for(i
=1; i
<res
->x
.p
->size
; i
++)
1567 emul(e1
, &(res
->x
.p
->arr
[i
]));
1582 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1583 /* Product of two rational numbers */
1587 value_multiply(res
->d
,e1
->d
,res
->d
);
1588 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1589 Gcd(res
->x
.n
, res
->d
,&g
);
1590 if (value_notone_p(g
)) {
1591 value_division(res
->d
,res
->d
,g
);
1592 value_division(res
->x
.n
,res
->x
.n
,g
);
1598 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1599 /* Product of an expression (polynomial or peririodic) and a rational number */
1605 /* Product of a rationel number and an expression (polynomial or peririodic) */
1607 i
= type_offset(res
->x
.p
);
1608 for (; i
<res
->x
.p
->size
; i
++)
1609 emul(e1
, &res
->x
.p
->arr
[i
]);
1619 /* Frees mask content ! */
1620 void emask(evalue
*mask
, evalue
*res
) {
1627 if (EVALUE_IS_ZERO(*res
)) {
1628 free_evalue_refs(mask
);
1632 assert(value_zero_p(mask
->d
));
1633 assert(mask
->x
.p
->type
== partition
);
1634 assert(value_zero_p(res
->d
));
1635 assert(res
->x
.p
->type
== partition
);
1636 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1637 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1638 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1639 pos
= res
->x
.p
->pos
;
1641 s
= (struct section
*)
1642 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1643 sizeof(struct section
));
1647 evalue_set_si(&mone
, -1, 1);
1650 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1651 assert(mask
->x
.p
->size
>= 2);
1652 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1653 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1655 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1657 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1666 value_init(s
[n
].E
.d
);
1667 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1671 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1672 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1675 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1676 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1677 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1678 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1680 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1681 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1687 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1688 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1690 value_init(s
[n
].E
.d
);
1691 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1692 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1698 /* Just ignore; this may have been previously masked off */
1700 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1704 free_evalue_refs(&mone
);
1705 free_evalue_refs(mask
);
1706 free_evalue_refs(res
);
1709 evalue_set_si(res
, 0, 1);
1711 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1712 for (j
= 0; j
< n
; ++j
) {
1713 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1714 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1715 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1722 void evalue_copy(evalue
*dst
, evalue
*src
)
1724 value_assign(dst
->d
, src
->d
);
1725 if(value_notzero_p(src
->d
)) {
1726 value_init(dst
->x
.n
);
1727 value_assign(dst
->x
.n
, src
->x
.n
);
1729 dst
->x
.p
= ecopy(src
->x
.p
);
1732 enode
*new_enode(enode_type type
,int size
,int pos
) {
1738 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1741 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1745 for(i
=0; i
<size
; i
++) {
1746 value_init(res
->arr
[i
].d
);
1747 value_set_si(res
->arr
[i
].d
,0);
1748 res
->arr
[i
].x
.p
= 0;
1753 enode
*ecopy(enode
*e
) {
1758 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1759 for(i
=0;i
<e
->size
;++i
) {
1760 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1761 if(value_zero_p(res
->arr
[i
].d
))
1762 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1763 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1764 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1766 value_init(res
->arr
[i
].x
.n
);
1767 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1773 int ecmp(const evalue
*e1
, const evalue
*e2
)
1779 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1783 value_multiply(m
, e1
->x
.n
, e2
->d
);
1784 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1786 if (value_lt(m
, m2
))
1788 else if (value_gt(m
, m2
))
1798 if (value_notzero_p(e1
->d
))
1800 if (value_notzero_p(e2
->d
))
1806 if (p1
->type
!= p2
->type
)
1807 return p1
->type
- p2
->type
;
1808 if (p1
->pos
!= p2
->pos
)
1809 return p1
->pos
- p2
->pos
;
1810 if (p1
->size
!= p2
->size
)
1811 return p1
->size
- p2
->size
;
1813 for (i
= p1
->size
-1; i
>= 0; --i
)
1814 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1820 int eequal(evalue
*e1
,evalue
*e2
) {
1825 if (value_ne(e1
->d
,e2
->d
))
1828 /* e1->d == e2->d */
1829 if (value_notzero_p(e1
->d
)) {
1830 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1833 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1837 /* e1->d == e2->d == 0 */
1840 if (p1
->type
!= p2
->type
) return 0;
1841 if (p1
->size
!= p2
->size
) return 0;
1842 if (p1
->pos
!= p2
->pos
) return 0;
1843 for (i
=0; i
<p1
->size
; i
++)
1844 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1849 void free_evalue_refs(evalue
*e
) {
1854 if (EVALUE_IS_DOMAIN(*e
)) {
1855 Domain_Free(EVALUE_DOMAIN(*e
));
1858 } else if (value_pos_p(e
->d
)) {
1860 /* 'e' stores a constant */
1862 value_clear(e
->x
.n
);
1865 assert(value_zero_p(e
->d
));
1868 if (!p
) return; /* null pointer */
1869 for (i
=0; i
<p
->size
; i
++) {
1870 free_evalue_refs(&(p
->arr
[i
]));
1874 } /* free_evalue_refs */
1876 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1877 Vector
* val
, evalue
*res
)
1879 unsigned nparam
= periods
->Size
;
1882 double d
= compute_evalue(e
, val
->p
);
1883 d
*= VALUE_TO_DOUBLE(m
);
1888 value_assign(res
->d
, m
);
1889 value_init(res
->x
.n
);
1890 value_set_double(res
->x
.n
, d
);
1891 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1894 if (value_one_p(periods
->p
[p
]))
1895 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1900 value_assign(tmp
, periods
->p
[p
]);
1901 value_set_si(res
->d
, 0);
1902 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1904 value_decrement(tmp
, tmp
);
1905 value_assign(val
->p
[p
], tmp
);
1906 mod2table_r(e
, periods
, m
, p
+1, val
,
1907 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1908 } while (value_pos_p(tmp
));
1914 static void rel2table(evalue
*e
, int zero
)
1916 if (value_pos_p(e
->d
)) {
1917 if (value_zero_p(e
->x
.n
) == zero
)
1918 value_set_si(e
->x
.n
, 1);
1920 value_set_si(e
->x
.n
, 0);
1921 value_set_si(e
->d
, 1);
1924 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1925 rel2table(&e
->x
.p
->arr
[i
], zero
);
1929 void evalue_mod2table(evalue
*e
, int nparam
)
1934 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1937 for (i
=0; i
<p
->size
; i
++) {
1938 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1940 if (p
->type
== relation
) {
1945 evalue_copy(©
, &p
->arr
[0]);
1947 rel2table(&p
->arr
[0], 1);
1948 emul(&p
->arr
[0], &p
->arr
[1]);
1950 rel2table(©
, 0);
1951 emul(©
, &p
->arr
[2]);
1952 eadd(&p
->arr
[2], &p
->arr
[1]);
1953 free_evalue_refs(&p
->arr
[2]);
1954 free_evalue_refs(©
);
1956 free_evalue_refs(&p
->arr
[0]);
1960 } else if (p
->type
== fractional
) {
1961 Vector
*periods
= Vector_Alloc(nparam
);
1962 Vector
*val
= Vector_Alloc(nparam
);
1968 value_set_si(tmp
, 1);
1969 Vector_Set(periods
->p
, 1, nparam
);
1970 Vector_Set(val
->p
, 0, nparam
);
1971 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1974 assert(p
->type
== polynomial
);
1975 assert(p
->size
== 2);
1976 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
1977 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
1979 value_lcm(tmp
, ev
->d
, &tmp
);
1981 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1984 evalue_set_si(&res
, 0, 1);
1985 /* Compute the polynomial using Horner's rule */
1986 for (i
=p
->size
-1;i
>1;i
--) {
1987 eadd(&p
->arr
[i
], &res
);
1990 eadd(&p
->arr
[1], &res
);
1992 free_evalue_refs(e
);
1993 free_evalue_refs(&EP
);
1998 Vector_Free(periods
);
2000 } /* evalue_mod2table */
2002 /********************************************************/
2003 /* function in domain */
2004 /* check if the parameters in list_args */
2005 /* verifies the constraints of Domain P */
2006 /********************************************************/
2007 int in_domain(Polyhedron
*P
, Value
*list_args
) {
2010 Value v
; /* value of the constraint of a row when
2011 parameters are instanciated*/
2017 /*P->Constraint constraint matrice of polyhedron P*/
2018 for(row
=0;row
<P
->NbConstraints
;row
++) {
2019 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2020 for(col
=1;col
<P
->Dimension
+1;col
++) {
2021 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
2022 value_addto(v
,v
,tmp
);
2024 if (value_notzero_p(P
->Constraint
[row
][0])) {
2026 /*if v is not >=0 then this constraint is not respected */
2027 if (value_neg_p(v
)) {
2031 return P
->next
? in_domain(P
->next
, list_args
) : 0;
2036 /*if v is not = 0 then this constraint is not respected */
2037 if (value_notzero_p(v
))
2042 /*if not return before this point => all
2043 the constraints are respected */
2049 /****************************************************/
2050 /* function compute enode */
2051 /* compute the value of enode p with parameters */
2052 /* list "list_args */
2053 /* compute the polynomial or the periodic */
2054 /****************************************************/
2056 static double compute_enode(enode
*p
, Value
*list_args
) {
2068 if (p
->type
== polynomial
) {
2070 value_assign(param
,list_args
[p
->pos
-1]);
2072 /* Compute the polynomial using Horner's rule */
2073 for (i
=p
->size
-1;i
>0;i
--) {
2074 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2075 res
*=VALUE_TO_DOUBLE(param
);
2077 res
+=compute_evalue(&p
->arr
[0],list_args
);
2079 else if (p
->type
== fractional
) {
2080 double d
= compute_evalue(&p
->arr
[0], list_args
);
2081 d
-= floor(d
+1e-10);
2083 /* Compute the polynomial using Horner's rule */
2084 for (i
=p
->size
-1;i
>1;i
--) {
2085 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2088 res
+=compute_evalue(&p
->arr
[1],list_args
);
2090 else if (p
->type
== flooring
) {
2091 double d
= compute_evalue(&p
->arr
[0], list_args
);
2094 /* Compute the polynomial using Horner's rule */
2095 for (i
=p
->size
-1;i
>1;i
--) {
2096 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2099 res
+=compute_evalue(&p
->arr
[1],list_args
);
2101 else if (p
->type
== periodic
) {
2102 value_assign(m
,list_args
[p
->pos
-1]);
2104 /* Choose the right element of the periodic */
2105 value_set_si(param
,p
->size
);
2106 value_pmodulus(m
,m
,param
);
2107 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2109 else if (p
->type
== relation
) {
2110 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2111 res
= compute_evalue(&p
->arr
[1], list_args
);
2112 else if (p
->size
> 2)
2113 res
= compute_evalue(&p
->arr
[2], list_args
);
2115 else if (p
->type
== partition
) {
2116 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2117 Value
*vals
= list_args
;
2120 for (i
= 0; i
< dim
; ++i
) {
2121 value_init(vals
[i
]);
2123 value_assign(vals
[i
], list_args
[i
]);
2126 for (i
= 0; i
< p
->size
/2; ++i
)
2127 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2128 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2132 for (i
= 0; i
< dim
; ++i
)
2133 value_clear(vals
[i
]);
2142 } /* compute_enode */
2144 /*************************************************/
2145 /* return the value of Ehrhart Polynomial */
2146 /* It returns a double, because since it is */
2147 /* a recursive function, some intermediate value */
2148 /* might not be integral */
2149 /*************************************************/
2151 double compute_evalue(evalue
*e
,Value
*list_args
) {
2155 if (value_notzero_p(e
->d
)) {
2156 if (value_notone_p(e
->d
))
2157 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2159 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2162 res
= compute_enode(e
->x
.p
,list_args
);
2164 } /* compute_evalue */
2167 /****************************************************/
2168 /* function compute_poly : */
2169 /* Check for the good validity domain */
2170 /* return the number of point in the Polyhedron */
2171 /* in allocated memory */
2172 /* Using the Ehrhart pseudo-polynomial */
2173 /****************************************************/
2174 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2177 /* double d; int i; */
2179 tmp
= (Value
*) malloc (sizeof(Value
));
2180 assert(tmp
!= NULL
);
2182 value_set_si(*tmp
,0);
2185 return(tmp
); /* no ehrhart polynomial */
2186 if(en
->ValidityDomain
) {
2187 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2188 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2193 return(tmp
); /* no Validity Domain */
2195 if(in_domain(en
->ValidityDomain
,list_args
)) {
2197 #ifdef EVAL_EHRHART_DEBUG
2198 Print_Domain(stdout
,en
->ValidityDomain
);
2199 print_evalue(stdout
,&en
->EP
);
2202 /* d = compute_evalue(&en->EP,list_args);
2204 printf("(double)%lf = %d\n", d, i ); */
2205 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2211 value_set_si(*tmp
,0);
2212 return(tmp
); /* no compatible domain with the arguments */
2213 } /* compute_poly */
2215 size_t value_size(Value v
) {
2216 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2217 * sizeof(v
[0]._mp_d
[0]);
2220 size_t domain_size(Polyhedron
*D
)
2223 size_t s
= sizeof(*D
);
2225 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2226 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2227 s
+= value_size(D
->Constraint
[i
][j
]);
2230 for (i = 0; i < D->NbRays; ++i)
2231 for (j = 0; j < D->Dimension+2; ++j)
2232 s += value_size(D->Ray[i][j]);
2235 return D
->next
? s
+domain_size(D
->next
) : s
;
2238 size_t enode_size(enode
*p
) {
2239 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2242 if (p
->type
== partition
)
2243 for (i
= 0; i
< p
->size
/2; ++i
) {
2244 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2245 s
+= evalue_size(&p
->arr
[2*i
+1]);
2248 for (i
= 0; i
< p
->size
; ++i
) {
2249 s
+= evalue_size(&p
->arr
[i
]);
2254 size_t evalue_size(evalue
*e
)
2256 size_t s
= sizeof(*e
);
2257 s
+= value_size(e
->d
);
2258 if (value_notzero_p(e
->d
))
2259 s
+= value_size(e
->x
.n
);
2261 s
+= enode_size(e
->x
.p
);
2265 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2267 evalue
*found
= NULL
;
2272 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2275 value_init(offset
.d
);
2276 value_init(offset
.x
.n
);
2277 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2278 value_lcm(m
, offset
.d
, &offset
.d
);
2279 value_set_si(offset
.x
.n
, 1);
2282 evalue_copy(©
, cst
);
2285 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2287 if (eequal(base
, &e
->x
.p
->arr
[0]))
2288 found
= &e
->x
.p
->arr
[0];
2290 value_set_si(offset
.x
.n
, -2);
2293 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2295 if (eequal(base
, &e
->x
.p
->arr
[0]))
2298 free_evalue_refs(cst
);
2299 free_evalue_refs(&offset
);
2302 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2303 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2308 static evalue
*find_relation_pair(evalue
*e
)
2311 evalue
*found
= NULL
;
2313 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2316 if (e
->x
.p
->type
== fractional
) {
2321 poly_denom(&e
->x
.p
->arr
[0], &m
);
2323 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2324 cst
= &cst
->x
.p
->arr
[0])
2327 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2328 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2333 i
= e
->x
.p
->type
== relation
;
2334 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2335 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2340 void evalue_mod2relation(evalue
*e
) {
2343 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2346 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2347 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2348 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2349 value_clear(e
->x
.p
->arr
[2*i
].d
);
2350 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2352 if (2*i
< e
->x
.p
->size
) {
2353 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2354 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2359 if (e
->x
.p
->size
== 0) {
2361 evalue_set_si(e
, 0, 1);
2367 while ((d
= find_relation_pair(e
)) != NULL
) {
2371 value_init(split
.d
);
2372 value_set_si(split
.d
, 0);
2373 split
.x
.p
= new_enode(relation
, 3, 0);
2374 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2375 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2377 ev
= &split
.x
.p
->arr
[0];
2378 value_set_si(ev
->d
, 0);
2379 ev
->x
.p
= new_enode(fractional
, 3, -1);
2380 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2381 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2382 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2388 free_evalue_refs(&split
);
2392 static int evalue_comp(const void * a
, const void * b
)
2394 const evalue
*e1
= *(const evalue
**)a
;
2395 const evalue
*e2
= *(const evalue
**)b
;
2396 return ecmp(e1
, e2
);
2399 void evalue_combine(evalue
*e
)
2406 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2409 NALLOC(evs
, e
->x
.p
->size
/2);
2410 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2411 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2412 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2413 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2414 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2415 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2416 value_clear(p
->arr
[2*k
].d
);
2417 value_clear(p
->arr
[2*k
+1].d
);
2418 p
->arr
[2*k
] = *(evs
[i
]-1);
2419 p
->arr
[2*k
+1] = *(evs
[i
]);
2422 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2425 value_clear((evs
[i
]-1)->d
);
2429 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2430 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2431 free_evalue_refs(evs
[i
]);
2435 for (i
= 2*k
; i
< p
->size
; ++i
)
2436 value_clear(p
->arr
[i
].d
);
2443 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2445 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2447 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2450 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2451 Polyhedron
*D
, *N
, **P
;
2454 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2461 if (D
->NbEq
<= H
->NbEq
) {
2467 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2468 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2469 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2470 reduce_evalue(&tmp
);
2471 if (value_notzero_p(tmp
.d
) ||
2472 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2475 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2476 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2479 free_evalue_refs(&tmp
);
2485 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2487 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2489 value_clear(e
->x
.p
->arr
[2*i
].d
);
2490 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2492 if (2*i
< e
->x
.p
->size
) {
2493 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2494 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2501 H
= DomainConvex(D
, 0);
2502 E
= DomainDifference(H
, D
, 0);
2504 D
= DomainDifference(H
, E
, 0);
2507 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2511 /* May change coefficients to become non-standard if fiddle is set
2512 * => reduce p afterwards to correct
2514 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2515 Matrix
**R
, int fiddle
)
2519 unsigned dim
= D
->Dimension
;
2520 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2525 assert(p
->type
== fractional
);
2527 value_set_si(T
->p
[1][dim
], 1);
2529 while (value_zero_p(pp
->d
)) {
2530 assert(pp
->x
.p
->type
== polynomial
);
2531 assert(pp
->x
.p
->size
== 2);
2532 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2533 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2534 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2535 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2536 value_substract(pp
->x
.p
->arr
[1].x
.n
,
2537 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2538 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2539 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2540 pp
= &pp
->x
.p
->arr
[0];
2542 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2543 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2544 I
= DomainImage(D
, T
, 0);
2545 H
= DomainConvex(I
, 0);
2554 static int reduce_in_domain(evalue
*e
, Polyhedron
*D
)
2564 if (value_notzero_p(e
->d
))
2569 if (p
->type
== relation
) {
2575 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2576 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2577 equal
= value_eq(min
, max
);
2578 mpz_cdiv_q(min
, min
, d
);
2579 mpz_fdiv_q(max
, max
, d
);
2581 if (bounded
&& value_gt(min
, max
)) {
2587 evalue_set_si(e
, 0, 1);
2590 free_evalue_refs(&(p
->arr
[1]));
2591 free_evalue_refs(&(p
->arr
[0]));
2597 return r
? r
: reduce_in_domain(e
, D
);
2598 } else if (bounded
&& equal
) {
2601 free_evalue_refs(&(p
->arr
[2]));
2604 free_evalue_refs(&(p
->arr
[0]));
2610 return reduce_in_domain(e
, D
);
2611 } else if (bounded
&& value_eq(min
, max
)) {
2612 /* zero for a single value */
2614 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2615 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2616 value_multiply(min
, min
, d
);
2617 value_substract(M
->p
[0][D
->Dimension
+1],
2618 M
->p
[0][D
->Dimension
+1], min
);
2619 E
= DomainAddConstraints(D
, M
, 0);
2625 r
= reduce_in_domain(&p
->arr
[1], E
);
2627 r
|= reduce_in_domain(&p
->arr
[2], D
);
2629 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2637 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2640 i
= p
->type
== relation
? 1 :
2641 p
->type
== fractional
? 1 : 0;
2642 for (; i
<p
->size
; i
++)
2643 r
|= reduce_in_domain(&p
->arr
[i
], D
);
2645 if (p
->type
!= fractional
) {
2646 if (r
&& p
->type
== polynomial
) {
2649 value_set_si(f
.d
, 0);
2650 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2651 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2652 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2653 reorder_terms(p
, &f
);
2664 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2666 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2667 mpz_fdiv_q(min
, min
, d
);
2668 mpz_fdiv_q(max
, max
, d
);
2669 value_substract(d
, max
, min
);
2671 if (bounded
&& value_eq(min
, max
)) {
2674 value_init(inc
.x
.n
);
2675 value_set_si(inc
.d
, 1);
2676 value_oppose(inc
.x
.n
, min
);
2677 eadd(&inc
, &p
->arr
[0]);
2678 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2682 free_evalue_refs(&inc
);
2684 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2691 value_set_si(rem
.d
, 0);
2692 rem
.x
.p
= new_enode(fractional
, 3, -1);
2693 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2694 rem
.x
.p
->arr
[1] = p
->arr
[1];
2695 rem
.x
.p
->arr
[2] = p
->arr
[2];
2696 for (i
= 3; i
< p
->size
; ++i
)
2697 p
->arr
[i
-2] = p
->arr
[i
];
2701 value_init(inc
.x
.n
);
2702 value_set_si(inc
.d
, 1);
2703 value_oppose(inc
.x
.n
, min
);
2706 evalue_copy(&t
, &p
->arr
[0]);
2710 value_set_si(f
.d
, 0);
2711 f
.x
.p
= new_enode(fractional
, 3, -1);
2712 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2713 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2714 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2716 value_init(factor
.d
);
2717 evalue_set_si(&factor
, -1, 1);
2723 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2724 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2730 free_evalue_refs(&inc
);
2731 free_evalue_refs(&t
);
2732 free_evalue_refs(&f
);
2733 free_evalue_refs(&factor
);
2734 free_evalue_refs(&rem
);
2736 reduce_in_domain(e
, D
);
2740 _reduce_evalue(&p
->arr
[0], 0, 1);
2744 value_set_si(f
.d
, 0);
2745 f
.x
.p
= new_enode(fractional
, 3, -1);
2746 value_clear(f
.x
.p
->arr
[0].d
);
2747 f
.x
.p
->arr
[0] = p
->arr
[0];
2748 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2749 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2750 reorder_terms(p
, &f
);
2764 void evalue_range_reduction(evalue
*e
)
2767 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2770 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2771 if (reduce_in_domain(&e
->x
.p
->arr
[2*i
+1],
2772 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2773 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2775 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2776 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2777 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2778 value_clear(e
->x
.p
->arr
[2*i
].d
);
2780 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2781 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2789 Enumeration
* partition2enumeration(evalue
*EP
)
2792 Enumeration
*en
, *res
= NULL
;
2794 if (EVALUE_IS_ZERO(*EP
)) {
2799 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2800 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
2801 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2804 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2805 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2806 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2814 static int frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2824 if (value_notzero_p(e
->d
))
2829 i
= p
->type
== relation
? 1 :
2830 p
->type
== fractional
? 1 : 0;
2831 for (; i
<p
->size
; i
++)
2832 r
|= frac2floor_in_domain(&p
->arr
[i
], D
);
2834 if (p
->type
!= fractional
) {
2835 if (r
&& p
->type
== polynomial
) {
2838 value_set_si(f
.d
, 0);
2839 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2840 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2841 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2842 reorder_terms(p
, &f
);
2851 I
= polynomial_projection(p
, D
, &d
, &T
, 0);
2854 Polyhedron_Print(stderr, P_VALUE_FMT, I);
2857 assert(I
->NbEq
== 0); /* Should have been reduced */
2860 for (i
= 0; i
< I
->NbConstraints
; ++i
)
2861 if (value_pos_p(I
->Constraint
[i
][1]))
2864 assert(i
< I
->NbConstraints
);
2866 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
2867 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
2868 if (value_neg_p(min
)) {
2870 mpz_fdiv_q(min
, min
, d
);
2871 value_init(offset
.d
);
2872 value_set_si(offset
.d
, 1);
2873 value_init(offset
.x
.n
);
2874 value_oppose(offset
.x
.n
, min
);
2875 eadd(&offset
, &p
->arr
[0]);
2876 free_evalue_refs(&offset
);
2885 value_set_si(fl
.d
, 0);
2886 fl
.x
.p
= new_enode(flooring
, 3, -1);
2887 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2888 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2889 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2891 eadd(&fl
, &p
->arr
[0]);
2892 reorder_terms(p
, &p
->arr
[0]);
2895 free_evalue_refs(&fl
);
2900 void evalue_frac2floor(evalue
*e
)
2903 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2906 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2907 if (frac2floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
2908 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])))
2909 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2912 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2917 int nparam
= D
->Dimension
- nvar
;
2920 nr
= D
->NbConstraints
+ 2;
2921 nc
= D
->Dimension
+ 2 + 1;
2922 C
= Matrix_Alloc(nr
, nc
);
2923 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2924 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
2925 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2926 D
->Dimension
+ 1 - nvar
);
2931 nc
= C
->NbColumns
+ 1;
2932 C
= Matrix_Alloc(nr
, nc
);
2933 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
2934 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
2935 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2936 oldC
->NbColumns
- 1 - nvar
);
2939 value_set_si(C
->p
[nr
-2][0], 1);
2940 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
2941 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
2943 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
2944 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
2950 static void floor2frac_r(evalue
*e
, int nvar
)
2957 if (value_notzero_p(e
->d
))
2962 assert(p
->type
== flooring
);
2963 for (i
= 1; i
< p
->size
; i
++)
2964 floor2frac_r(&p
->arr
[i
], nvar
);
2966 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
2967 assert(pp
->x
.p
->type
== polynomial
);
2968 pp
->x
.p
->pos
-= nvar
;
2972 value_set_si(f
.d
, 0);
2973 f
.x
.p
= new_enode(fractional
, 3, -1);
2974 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2975 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2976 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2978 eadd(&f
, &p
->arr
[0]);
2979 reorder_terms(p
, &p
->arr
[0]);
2982 free_evalue_refs(&f
);
2985 /* Convert flooring back to fractional and shift position
2986 * of the parameters by nvar
2988 static void floor2frac(evalue
*e
, int nvar
)
2990 floor2frac_r(e
, nvar
);
2994 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
2997 int nparam
= D
->Dimension
- nvar
;
3001 D
= Constraints2Polyhedron(C
, 0);
3005 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3007 /* Double check that D was not unbounded. */
3008 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3016 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3023 evalue
*factor
= NULL
;
3026 if (EVALUE_IS_ZERO(*e
))
3030 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
3037 res
= esum_over_domain(e
, nvar
, Q
, C
);
3040 for (Q
= DD
; Q
; Q
= DD
) {
3046 t
= esum_over_domain(e
, nvar
, Q
, C
);
3053 free_evalue_refs(t
);
3060 if (value_notzero_p(e
->d
)) {
3063 t
= esum_over_domain_cst(nvar
, D
, C
);
3065 if (!EVALUE_IS_ONE(*e
))
3071 switch (e
->x
.p
->type
) {
3073 evalue
*pp
= &e
->x
.p
->arr
[0];
3075 if (pp
->x
.p
->pos
> nvar
) {
3076 /* remainder is independent of the summated vars */
3082 floor2frac(&f
, nvar
);
3084 t
= esum_over_domain_cst(nvar
, D
, C
);
3088 free_evalue_refs(&f
);
3093 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3094 poly_denom(pp
, &row
->p
[1 + nvar
]);
3095 value_set_si(row
->p
[0], 1);
3096 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3097 pp
= &pp
->x
.p
->arr
[0]) {
3099 assert(pp
->x
.p
->type
== polynomial
);
3101 if (pos
>= 1 + nvar
)
3103 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3104 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3105 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3107 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3108 value_division(row
->p
[1 + D
->Dimension
+ 1],
3109 row
->p
[1 + D
->Dimension
+ 1],
3111 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3112 row
->p
[1 + D
->Dimension
+ 1],
3114 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3118 int pos
= e
->x
.p
->pos
;
3122 value_init(factor
->d
);
3123 value_set_si(factor
->d
, 0);
3124 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3125 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3126 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3130 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3131 for (i
= 0; i
< D
->NbRays
; ++i
)
3132 if (value_notzero_p(D
->Ray
[i
][pos
]))
3134 assert(i
< D
->NbRays
);
3135 if (value_neg_p(D
->Ray
[i
][pos
])) {
3137 value_init(factor
->d
);
3138 evalue_set_si(factor
, -1, 1);
3140 value_set_si(row
->p
[0], 1);
3141 value_set_si(row
->p
[pos
], 1);
3142 value_set_si(row
->p
[1 + nvar
], -1);
3149 i
= type_offset(e
->x
.p
);
3151 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3156 evalue_copy(&cum
, factor
);
3160 for (; i
< e
->x
.p
->size
; ++i
) {
3164 C
= esum_add_constraint(nvar
, D
, C
, row
);
3170 Vector_Print(stderr, P_VALUE_FMT, row);
3172 Matrix_Print(stderr, P_VALUE_FMT, C);
3174 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3183 free_evalue_refs(t
);
3186 if (factor
&& i
+1 < e
->x
.p
->size
)
3193 free_evalue_refs(factor
);
3194 free_evalue_refs(&cum
);
3206 evalue
*esum(evalue
*e
, int nvar
)
3214 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3215 evalue_copy(res
, e
);
3219 evalue_set_si(res
, 0, 1);
3221 assert(value_zero_p(e
->d
));
3222 assert(e
->x
.p
->type
== partition
);
3224 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3226 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3227 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3229 free_evalue_refs(t
);
3238 /* Initial silly implementation */
3239 void eor(evalue
*e1
, evalue
*res
)
3245 evalue_set_si(&mone
, -1, 1);
3247 evalue_copy(&E
, res
);
3253 free_evalue_refs(&E
);
3254 free_evalue_refs(&mone
);