5 #include "ev_operations.h"
9 #define ALLOC(p) p = (typeof(p))malloc(sizeof(*p))
10 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
12 void evalue_set_si(evalue
*ev
, int n
, int d
) {
13 value_set_si(ev
->d
, d
);
15 value_set_si(ev
->x
.n
, n
);
18 void evalue_set(evalue
*ev
, Value n
, Value d
) {
19 value_assign(ev
->d
, d
);
21 value_assign(ev
->x
.n
, n
);
24 void aep_evalue(evalue
*e
, int *ref
) {
29 if (value_notzero_p(e
->d
))
30 return; /* a rational number, its already reduced */
32 return; /* hum... an overflow probably occured */
34 /* First check the components of p */
35 for (i
=0;i
<p
->size
;i
++)
36 aep_evalue(&p
->arr
[i
],ref
);
43 p
->pos
= ref
[p
->pos
-1]+1;
49 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
55 if (value_notzero_p(e
->d
))
56 return; /* a rational number, its already reduced */
58 return; /* hum... an overflow probably occured */
61 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
62 for(i
=0;i
<CT
->NbRows
-1;i
++)
63 for(j
=0;j
<CT
->NbColumns
;j
++)
64 if(value_notzero_p(CT
->p
[i
][j
])) {
69 /* Transform the references in e, using ref */
73 } /* addeliminatedparams_evalue */
75 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
76 unsigned MaxRays
, unsigned nparam
)
81 if (CT
->NbRows
== CT
->NbColumns
)
84 if (EVALUE_IS_ZERO(*e
))
87 if (value_notzero_p(e
->d
)) {
90 value_set_si(res
.d
, 0);
91 res
.x
.p
= new_enode(partition
, 2, nparam
);
92 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
93 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
94 value_clear(res
.x
.p
->arr
[1].d
);
102 assert(p
->type
== partition
);
105 for (i
=0; i
<p
->size
/2; i
++) {
106 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
107 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
110 T
= DomainIntersection(D
, CEq
, MaxRays
);
112 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
113 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
117 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
125 assert(value_notzero_p(e1
->d
));
126 assert(value_notzero_p(e2
->d
));
127 value_multiply(m
, e1
->x
.n
, e2
->d
);
128 value_multiply(m2
, e2
->x
.n
, e1
->d
);
131 else if (value_gt(m
, m2
))
141 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
143 if (value_notzero_p(e1
->d
)) {
145 if (value_zero_p(e2
->d
))
147 r
= mod_rational_smaller(e1
, e2
);
148 return r
== -1 ? 0 : r
;
150 if (value_notzero_p(e2
->d
))
152 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
154 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
157 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
159 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
164 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
166 assert(value_zero_p(e1
->d
));
167 assert(value_zero_p(e2
->d
));
168 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
169 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
170 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
173 /* Negative pos means inequality */
174 /* s is negative of substitution if m is not zero */
183 struct fixed_param
*fixed
;
188 static int relations_depth(evalue
*e
)
193 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
194 e
= &e
->x
.p
->arr
[1], ++d
);
198 static void poly_denom(evalue
*p
, Value
*d
)
202 while (value_zero_p(p
->d
)) {
203 assert(p
->x
.p
->type
== polynomial
);
204 assert(p
->x
.p
->size
== 2);
205 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
206 value_lcm(*d
, p
->x
.p
->arr
[1].d
, d
);
209 value_lcm(*d
, p
->d
, d
);
212 #define EVALUE_IS_ONE(ev) (value_one_p((ev).d) && value_one_p((ev).x.n))
214 static void realloc_substitution(struct subst
*s
, int d
)
216 struct fixed_param
*n
;
219 for (i
= 0; i
< s
->n
; ++i
)
226 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
232 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
235 /* May have been reduced already */
236 if (value_notzero_p(m
->d
))
239 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
240 assert(m
->x
.p
->size
== 3);
242 /* fractional was inverted during reduction
243 * invert it back and move constant in
245 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
246 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
247 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
248 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
249 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
250 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
251 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
252 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
253 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
254 value_set_si(m
->x
.p
->arr
[1].d
, 1);
257 /* Oops. Nested identical relations. */
258 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
261 if (s
->n
>= s
->max
) {
262 int d
= relations_depth(r
);
263 realloc_substitution(s
, d
);
267 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
268 assert(p
->x
.p
->size
== 2);
271 assert(value_pos_p(f
->x
.n
));
273 value_init(s
->fixed
[s
->n
].m
);
274 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
275 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
276 value_init(s
->fixed
[s
->n
].d
);
277 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
278 value_init(s
->fixed
[s
->n
].s
.d
);
279 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
285 static int type_offset(enode
*p
)
287 return p
->type
== fractional
? 1 :
288 p
->type
== flooring
? 1 : 0;
291 static void reorder_terms(enode
*p
, evalue
*v
)
294 int offset
= type_offset(p
);
296 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
298 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
299 free_evalue_refs(&(p
->arr
[i
]));
305 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
311 if (value_notzero_p(e
->d
)) {
313 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
314 return; /* a rational number, its already reduced */
318 return; /* hum... an overflow probably occured */
320 /* First reduce the components of p */
321 add
= p
->type
== relation
;
322 for (i
=0; i
<p
->size
; i
++) {
324 add
= add_modulo_substitution(s
, e
);
326 if (i
== 0 && p
->type
==fractional
)
327 _reduce_evalue(&p
->arr
[i
], s
, 1);
329 _reduce_evalue(&p
->arr
[i
], s
, fract
);
331 if (add
&& i
== p
->size
-1) {
333 value_clear(s
->fixed
[s
->n
].m
);
334 value_clear(s
->fixed
[s
->n
].d
);
335 free_evalue_refs(&s
->fixed
[s
->n
].s
);
336 } else if (add
&& i
== 1)
337 s
->fixed
[s
->n
-1].pos
*= -1;
340 if (p
->type
==periodic
) {
342 /* Try to reduce the period */
343 for (i
=1; i
<=(p
->size
)/2; i
++) {
344 if ((p
->size
% i
)==0) {
346 /* Can we reduce the size to i ? */
348 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
349 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
352 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
356 you_lose
: /* OK, lets not do it */
361 /* Try to reduce its strength */
364 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
368 else if (p
->type
==polynomial
) {
369 for (k
= 0; s
&& k
< s
->n
; ++k
) {
370 if (s
->fixed
[k
].pos
== p
->pos
) {
371 int divide
= value_notone_p(s
->fixed
[k
].d
);
374 if (value_notzero_p(s
->fixed
[k
].m
)) {
377 assert(p
->size
== 2);
378 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
380 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
387 value_assign(d
.d
, s
->fixed
[k
].d
);
389 if (value_notzero_p(s
->fixed
[k
].m
))
390 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
392 value_set_si(d
.x
.n
, 1);
395 for (i
=p
->size
-1;i
>=1;i
--) {
396 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
398 emul(&d
, &p
->arr
[i
]);
399 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
400 free_evalue_refs(&(p
->arr
[i
]));
403 _reduce_evalue(&p
->arr
[0], s
, fract
);
406 free_evalue_refs(&d
);
412 /* Try to reduce the degree */
413 for (i
=p
->size
-1;i
>=1;i
--) {
414 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
416 /* Zero coefficient */
417 free_evalue_refs(&(p
->arr
[i
]));
422 /* Try to reduce its strength */
425 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
429 else if (p
->type
==fractional
) {
433 if (value_notzero_p(p
->arr
[0].d
)) {
435 value_assign(v
.d
, p
->arr
[0].d
);
437 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
442 evalue
*pp
= &p
->arr
[0];
443 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
444 assert(pp
->x
.p
->size
== 2);
446 /* search for exact duplicate among the modulo inequalities */
448 f
= &pp
->x
.p
->arr
[1];
449 for (k
= 0; s
&& k
< s
->n
; ++k
) {
450 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
451 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
452 value_eq(s
->fixed
[k
].m
, f
->d
) &&
453 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
460 /* replace { E/m } by { (E-1)/m } + 1/m */
465 evalue_set_si(&extra
, 1, 1);
466 value_assign(extra
.d
, g
);
467 eadd(&extra
, &v
.x
.p
->arr
[1]);
468 free_evalue_refs(&extra
);
470 /* We've been going in circles; stop now */
471 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
472 free_evalue_refs(&v
);
474 evalue_set_si(&v
, 0, 1);
479 value_set_si(v
.d
, 0);
480 v
.x
.p
= new_enode(fractional
, 3, -1);
481 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
482 value_assign(v
.x
.p
->arr
[1].d
, g
);
483 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
484 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
487 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
490 value_division(f
->d
, g
, f
->d
);
491 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
492 value_assign(f
->d
, g
);
493 value_decrement(f
->x
.n
, f
->x
.n
);
494 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
496 Gcd(f
->d
, f
->x
.n
, &g
);
497 value_division(f
->d
, f
->d
, g
);
498 value_division(f
->x
.n
, f
->x
.n
, g
);
507 /* reduction may have made this fractional arg smaller */
508 i
= reorder
? p
->size
: 1;
509 for ( ; i
< p
->size
; ++i
)
510 if (value_zero_p(p
->arr
[i
].d
) &&
511 p
->arr
[i
].x
.p
->type
== fractional
&&
512 !mod_term_smaller(e
, &p
->arr
[i
]))
516 value_set_si(v
.d
, 0);
517 v
.x
.p
= new_enode(fractional
, 3, -1);
518 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
519 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
520 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
530 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
531 pp
= &pp
->x
.p
->arr
[0]) {
532 f
= &pp
->x
.p
->arr
[1];
533 assert(value_pos_p(f
->d
));
534 mpz_mul_ui(twice
, f
->x
.n
, 2);
535 if (value_lt(twice
, f
->d
))
537 if (value_eq(twice
, f
->d
))
545 value_set_si(v
.d
, 0);
546 v
.x
.p
= new_enode(fractional
, 3, -1);
547 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
548 poly_denom(&p
->arr
[0], &twice
);
549 value_assign(v
.x
.p
->arr
[1].d
, twice
);
550 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
551 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
552 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
554 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
555 pp
= &pp
->x
.p
->arr
[0]) {
556 f
= &pp
->x
.p
->arr
[1];
557 value_oppose(f
->x
.n
, f
->x
.n
);
558 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
560 value_division(pp
->d
, twice
, pp
->d
);
561 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
562 value_assign(pp
->d
, twice
);
563 value_oppose(pp
->x
.n
, pp
->x
.n
);
564 value_decrement(pp
->x
.n
, pp
->x
.n
);
565 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
575 reorder_terms(p
, &v
);
576 _reduce_evalue(&p
->arr
[1], s
, fract
);
579 /* Try to reduce the degree */
580 for (i
=p
->size
-1;i
>=2;i
--) {
581 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
583 /* Zero coefficient */
584 free_evalue_refs(&(p
->arr
[i
]));
589 /* Try to reduce its strength */
592 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
593 free_evalue_refs(&(p
->arr
[0]));
597 else if (p
->type
== flooring
) {
598 /* Try to reduce the degree */
599 for (i
=p
->size
-1;i
>=2;i
--) {
600 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
602 /* Zero coefficient */
603 free_evalue_refs(&(p
->arr
[i
]));
608 /* Try to reduce its strength */
611 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
612 free_evalue_refs(&(p
->arr
[0]));
616 else if (p
->type
== relation
) {
617 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
618 free_evalue_refs(&(p
->arr
[2]));
619 free_evalue_refs(&(p
->arr
[0]));
626 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
627 free_evalue_refs(&(p
->arr
[2]));
630 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
631 free_evalue_refs(&(p
->arr
[1]));
632 free_evalue_refs(&(p
->arr
[0]));
633 evalue_set_si(e
, 0, 1);
640 /* Relation was reduced by means of an identical
641 * inequality => remove
643 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
646 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
647 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
649 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
651 free_evalue_refs(&(p
->arr
[2]));
655 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
657 evalue_set_si(e
, 0, 1);
658 free_evalue_refs(&(p
->arr
[1]));
660 free_evalue_refs(&(p
->arr
[0]));
666 } /* reduce_evalue */
668 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
673 for (k
= 0; k
< dim
; ++k
)
674 if (value_notzero_p(row
[k
+1]))
677 Vector_Normalize_Positive(row
+1, dim
+1, k
);
678 assert(s
->n
< s
->max
);
679 value_init(s
->fixed
[s
->n
].d
);
680 value_init(s
->fixed
[s
->n
].m
);
681 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
682 s
->fixed
[s
->n
].pos
= k
+1;
683 value_set_si(s
->fixed
[s
->n
].m
, 0);
684 r
= &s
->fixed
[s
->n
].s
;
686 for (l
= k
+1; l
< dim
; ++l
)
687 if (value_notzero_p(row
[l
+1])) {
688 value_set_si(r
->d
, 0);
689 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
690 value_init(r
->x
.p
->arr
[1].x
.n
);
691 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
692 value_set_si(r
->x
.p
->arr
[1].d
, 1);
696 value_oppose(r
->x
.n
, row
[dim
+1]);
697 value_set_si(r
->d
, 1);
701 void reduce_evalue (evalue
*e
) {
702 struct subst s
= { NULL
, 0, 0 };
704 if (value_notzero_p(e
->d
))
705 return; /* a rational number, its already reduced */
707 if (e
->x
.p
->type
== partition
) {
710 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
711 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
713 /* This shouldn't really happen;
714 * Empty domains should not be added.
721 D
= DomainConvex(D
, 0);
722 if (!D
->next
&& D
->NbEq
) {
726 realloc_substitution(&s
, dim
);
728 int d
= relations_depth(&e
->x
.p
->arr
[2*i
+1]);
730 NALLOC(s
.fixed
, s
.max
);
733 for (j
= 0; j
< D
->NbEq
; ++j
)
734 add_substitution(&s
, D
->Constraint
[j
], dim
);
736 if (D
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
738 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
739 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
741 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
742 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
743 value_clear(e
->x
.p
->arr
[2*i
].d
);
745 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
746 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
751 for (j
= 0; j
< s
.n
; ++j
) {
752 value_clear(s
.fixed
[j
].d
);
753 value_clear(s
.fixed
[j
].m
);
754 free_evalue_refs(&s
.fixed
[j
].s
);
758 if (e
->x
.p
->size
== 0) {
760 evalue_set_si(e
, 0, 1);
763 _reduce_evalue(e
, &s
, 0);
768 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
770 if(value_notzero_p(e
->d
)) {
771 if(value_notone_p(e
->d
)) {
772 value_print(DST
,VALUE_FMT
,e
->x
.n
);
774 value_print(DST
,VALUE_FMT
,e
->d
);
777 value_print(DST
,VALUE_FMT
,e
->x
.n
);
781 print_enode(DST
,e
->x
.p
,pname
);
785 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
790 fprintf(DST
, "NULL");
796 for (i
=0; i
<p
->size
; i
++) {
797 print_evalue(DST
, &p
->arr
[i
], pname
);
801 fprintf(DST
, " }\n");
805 for (i
=p
->size
-1; i
>=0; i
--) {
806 print_evalue(DST
, &p
->arr
[i
], pname
);
807 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
809 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
811 fprintf(DST
, " )\n");
815 for (i
=0; i
<p
->size
; i
++) {
816 print_evalue(DST
, &p
->arr
[i
], pname
);
817 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
819 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
824 for (i
=p
->size
-1; i
>=1; i
--) {
825 print_evalue(DST
, &p
->arr
[i
], pname
);
828 fprintf(DST
, p
->type
== flooring
? "[" : "{");
829 print_evalue(DST
, &p
->arr
[0], pname
);
830 fprintf(DST
, p
->type
== flooring
? "]" : "}");
832 fprintf(DST
, "^%d + ", i
-1);
837 fprintf(DST
, " )\n");
841 print_evalue(DST
, &p
->arr
[0], pname
);
842 fprintf(DST
, "= 0 ] * \n");
843 print_evalue(DST
, &p
->arr
[1], pname
);
845 fprintf(DST
, " +\n [ ");
846 print_evalue(DST
, &p
->arr
[0], pname
);
847 fprintf(DST
, "!= 0 ] * \n");
848 print_evalue(DST
, &p
->arr
[2], pname
);
852 char **names
= pname
;
853 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
854 if (p
->pos
< maxdim
) {
855 NALLOC(names
, maxdim
);
856 for (i
= 0; i
< p
->pos
; ++i
)
858 for ( ; i
< maxdim
; ++i
) {
859 NALLOC(names
[i
], 10);
860 snprintf(names
[i
], 10, "_p%d", i
);
864 for (i
=0; i
<p
->size
/2; i
++) {
865 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
866 print_evalue(DST
, &p
->arr
[2*i
+1], names
);
869 if (p
->pos
< maxdim
) {
870 for (i
= p
->pos
; i
< maxdim
; ++i
)
883 static void eadd_rev(evalue
*e1
, evalue
*res
)
887 evalue_copy(&ev
, e1
);
889 free_evalue_refs(res
);
893 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
897 evalue_copy(&ev
, e1
);
898 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
899 free_evalue_refs(res
);
903 struct section
{ Polyhedron
* D
; evalue E
; };
905 void eadd_partitions (evalue
*e1
,evalue
*res
)
910 s
= (struct section
*)
911 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
912 sizeof(struct section
));
914 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
915 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
916 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
919 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
920 assert(res
->x
.p
->size
>= 2);
921 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
922 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
924 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
926 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
935 value_init(s
[n
].E
.d
);
936 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
940 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
941 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
942 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
944 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
945 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
951 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
952 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
954 value_init(s
[n
].E
.d
);
955 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
956 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
961 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
965 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
968 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
969 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
970 value_clear(res
->x
.p
->arr
[2*i
].d
);
975 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
976 for (j
= 0; j
< n
; ++j
) {
977 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
978 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
979 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
980 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
986 static void explicit_complement(evalue
*res
)
988 enode
*rel
= new_enode(relation
, 3, 0);
990 value_clear(rel
->arr
[0].d
);
991 rel
->arr
[0] = res
->x
.p
->arr
[0];
992 value_clear(rel
->arr
[1].d
);
993 rel
->arr
[1] = res
->x
.p
->arr
[1];
994 value_set_si(rel
->arr
[2].d
, 1);
995 value_init(rel
->arr
[2].x
.n
);
996 value_set_si(rel
->arr
[2].x
.n
, 0);
1001 void eadd(evalue
*e1
,evalue
*res
) {
1004 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1005 /* Add two rational numbers */
1011 value_multiply(m1
,e1
->x
.n
,res
->d
);
1012 value_multiply(m2
,res
->x
.n
,e1
->d
);
1013 value_addto(res
->x
.n
,m1
,m2
);
1014 value_multiply(res
->d
,e1
->d
,res
->d
);
1015 Gcd(res
->x
.n
,res
->d
,&g
);
1016 if (value_notone_p(g
)) {
1017 value_division(res
->d
,res
->d
,g
);
1018 value_division(res
->x
.n
,res
->x
.n
,g
);
1020 value_clear(g
); value_clear(m1
); value_clear(m2
);
1023 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1024 switch (res
->x
.p
->type
) {
1026 /* Add the constant to the constant term of a polynomial*/
1027 eadd(e1
, &res
->x
.p
->arr
[0]);
1030 /* Add the constant to all elements of a periodic number */
1031 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1032 eadd(e1
, &res
->x
.p
->arr
[i
]);
1036 fprintf(stderr
, "eadd: cannot add const with vector\n");
1040 eadd(e1
, &res
->x
.p
->arr
[1]);
1043 assert(EVALUE_IS_ZERO(*e1
));
1044 break; /* Do nothing */
1046 /* Create (zero) complement if needed */
1047 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1048 explicit_complement(res
);
1049 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1050 eadd(e1
, &res
->x
.p
->arr
[i
]);
1056 /* add polynomial or periodic to constant
1057 * you have to exchange e1 and res, before doing addition */
1059 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1063 else { // ((e1->d==0) && (res->d==0))
1064 assert(!((e1
->x
.p
->type
== partition
) ^
1065 (res
->x
.p
->type
== partition
)));
1066 if (e1
->x
.p
->type
== partition
) {
1067 eadd_partitions(e1
, res
);
1070 if (e1
->x
.p
->type
== relation
&&
1071 (res
->x
.p
->type
!= relation
||
1072 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1076 if (res
->x
.p
->type
== relation
) {
1077 if (e1
->x
.p
->type
== relation
&&
1078 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1079 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1080 explicit_complement(res
);
1081 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1082 explicit_complement(e1
);
1083 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1084 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1087 if (res
->x
.p
->size
< 3)
1088 explicit_complement(res
);
1089 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1090 eadd(e1
, &res
->x
.p
->arr
[i
]);
1093 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1094 /* adding to evalues of different type. two cases are possible
1095 * res is periodic and e1 is polynomial, you have to exchange
1096 * e1 and res then to add e1 to the constant term of res */
1097 if (e1
->x
.p
->type
== polynomial
) {
1098 eadd_rev_cst(e1
, res
);
1100 else if (res
->x
.p
->type
== polynomial
) {
1101 /* res is polynomial and e1 is periodic,
1102 add e1 to the constant term of res */
1104 eadd(e1
,&res
->x
.p
->arr
[0]);
1110 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1111 ((res
->x
.p
->type
== fractional
||
1112 res
->x
.p
->type
== flooring
) &&
1113 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1114 /* adding evalues of different position (i.e function of different unknowns
1115 * to case are possible */
1117 switch (res
->x
.p
->type
) {
1120 if(mod_term_smaller(res
, e1
))
1121 eadd(e1
,&res
->x
.p
->arr
[1]);
1123 eadd_rev_cst(e1
, res
);
1125 case polynomial
: // res and e1 are polynomials
1126 // add e1 to the constant term of res
1128 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1129 eadd(e1
,&res
->x
.p
->arr
[0]);
1131 eadd_rev_cst(e1
, res
);
1132 // value_clear(g); value_clear(m1); value_clear(m2);
1134 case periodic
: // res and e1 are pointers to periodic numbers
1135 //add e1 to all elements of res
1137 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1138 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1139 eadd(e1
,&res
->x
.p
->arr
[i
]);
1150 //same type , same pos and same size
1151 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1152 // add any element in e1 to the corresponding element in res
1153 i
= type_offset(res
->x
.p
);
1155 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1156 for (; i
<res
->x
.p
->size
; i
++) {
1157 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1162 /* Sizes are different */
1163 switch(res
->x
.p
->type
) {
1167 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1168 /* new enode and add res to that new node. If you do not do */
1169 /* that, you lose the the upper weight part of e1 ! */
1171 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1174 i
= type_offset(res
->x
.p
);
1176 assert(eequal(&e1
->x
.p
->arr
[0],
1177 &res
->x
.p
->arr
[0]));
1178 for (; i
<e1
->x
.p
->size
; i
++) {
1179 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1186 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1189 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1190 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1191 to add periodicaly elements of e1 to elements of ne, and finaly to
1196 value_init(ex
); value_init(ey
);value_init(ep
);
1199 value_set_si(ex
,e1
->x
.p
->size
);
1200 value_set_si(ey
,res
->x
.p
->size
);
1201 value_assign (ep
,*Lcm(ex
,ey
));
1202 p
=(int)mpz_get_si(ep
);
1203 ne
= (evalue
*) malloc (sizeof(evalue
));
1205 value_set_si( ne
->d
,0);
1207 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1209 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1212 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1215 value_assign(res
->d
, ne
->d
);
1221 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1230 static void emul_rev (evalue
*e1
, evalue
*res
)
1234 evalue_copy(&ev
, e1
);
1236 free_evalue_refs(res
);
1240 static void emul_poly (evalue
*e1
, evalue
*res
)
1242 int i
, j
, o
= type_offset(res
->x
.p
);
1244 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1246 value_set_si(tmp
.d
,0);
1247 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1249 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1250 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1251 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1252 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1255 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1256 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1257 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1260 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1261 emul(&res
->x
.p
->arr
[i
], &ev
);
1262 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1263 free_evalue_refs(&ev
);
1265 free_evalue_refs(res
);
1269 void emul_partitions (evalue
*e1
,evalue
*res
)
1274 s
= (struct section
*)
1275 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1276 sizeof(struct section
));
1278 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1279 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1280 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1283 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1284 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1285 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1286 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1292 /* This code is only needed because the partitions
1293 are not true partitions.
1295 for (k
= 0; k
< n
; ++k
) {
1296 if (DomainIncludes(s
[k
].D
, d
))
1298 if (DomainIncludes(d
, s
[k
].D
)) {
1299 Domain_Free(s
[k
].D
);
1300 free_evalue_refs(&s
[k
].E
);
1311 value_init(s
[n
].E
.d
);
1312 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1313 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1317 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1318 value_clear(res
->x
.p
->arr
[2*i
].d
);
1319 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1324 evalue_set_si(res
, 0, 1);
1326 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1327 for (j
= 0; j
< n
; ++j
) {
1328 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1329 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1330 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1331 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1338 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1340 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1341 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1342 * evalues is not treated here */
1344 void emul (evalue
*e1
, evalue
*res
){
1347 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1348 fprintf(stderr
, "emul: do not proced on evector type !\n");
1352 if (EVALUE_IS_ZERO(*res
))
1355 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1356 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1357 emul_partitions(e1
, res
);
1360 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1361 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1362 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1364 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1365 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1366 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1367 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1368 explicit_complement(res
);
1369 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1370 explicit_complement(e1
);
1371 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1372 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1375 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1376 emul(e1
, &res
->x
.p
->arr
[i
]);
1378 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1379 switch(e1
->x
.p
->type
) {
1381 switch(res
->x
.p
->type
) {
1383 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1384 /* Product of two polynomials of the same variable */
1389 /* Product of two polynomials of different variables */
1391 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1392 for( i
=0; i
<res
->x
.p
->size
; i
++)
1393 emul(e1
, &res
->x
.p
->arr
[i
]);
1402 /* Product of a polynomial and a periodic or fractional */
1409 switch(res
->x
.p
->type
) {
1411 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1412 /* Product of two periodics of the same parameter and period */
1414 for(i
=0; i
<res
->x
.p
->size
;i
++)
1415 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1420 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1421 /* Product of two periodics of the same parameter and different periods */
1425 value_init(x
); value_init(y
);value_init(z
);
1428 value_set_si(x
,e1
->x
.p
->size
);
1429 value_set_si(y
,res
->x
.p
->size
);
1430 value_assign (z
,*Lcm(x
,y
));
1431 lcm
=(int)mpz_get_si(z
);
1432 newp
= (evalue
*) malloc (sizeof(evalue
));
1433 value_init(newp
->d
);
1434 value_set_si( newp
->d
,0);
1435 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1436 for(i
=0;i
<lcm
;i
++) {
1437 evalue_copy(&newp
->x
.p
->arr
[i
],
1438 &res
->x
.p
->arr
[i
%iy
]);
1441 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1443 value_assign(res
->d
,newp
->d
);
1446 value_clear(x
); value_clear(y
);value_clear(z
);
1450 /* Product of two periodics of different parameters */
1452 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1453 for(i
=0; i
<res
->x
.p
->size
; i
++)
1454 emul(e1
, &(res
->x
.p
->arr
[i
]));
1462 /* Product of a periodic and a polynomial */
1464 for(i
=0; i
<res
->x
.p
->size
; i
++)
1465 emul(e1
, &(res
->x
.p
->arr
[i
]));
1472 switch(res
->x
.p
->type
) {
1474 for(i
=0; i
<res
->x
.p
->size
; i
++)
1475 emul(e1
, &(res
->x
.p
->arr
[i
]));
1482 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1483 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1484 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1487 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1488 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1493 value_set_si(d
.x
.n
, 1);
1494 /* { x }^2 == { x }/2 */
1495 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1496 assert(e1
->x
.p
->size
== 3);
1497 assert(res
->x
.p
->size
== 3);
1499 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1501 eadd(&res
->x
.p
->arr
[1], &tmp
);
1502 emul(&e1
->x
.p
->arr
[2], &tmp
);
1503 emul(&e1
->x
.p
->arr
[1], res
);
1504 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1505 free_evalue_refs(&tmp
);
1510 if(mod_term_smaller(res
, e1
))
1511 for(i
=1; i
<res
->x
.p
->size
; i
++)
1512 emul(e1
, &(res
->x
.p
->arr
[i
]));
1527 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1528 /* Product of two rational numbers */
1532 value_multiply(res
->d
,e1
->d
,res
->d
);
1533 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1534 Gcd(res
->x
.n
, res
->d
,&g
);
1535 if (value_notone_p(g
)) {
1536 value_division(res
->d
,res
->d
,g
);
1537 value_division(res
->x
.n
,res
->x
.n
,g
);
1543 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1544 /* Product of an expression (polynomial or peririodic) and a rational number */
1550 /* Product of a rationel number and an expression (polynomial or peririodic) */
1552 i
= type_offset(res
->x
.p
);
1553 for (; i
<res
->x
.p
->size
; i
++)
1554 emul(e1
, &res
->x
.p
->arr
[i
]);
1564 /* Frees mask content ! */
1565 void emask(evalue
*mask
, evalue
*res
) {
1572 if (EVALUE_IS_ZERO(*res
)) {
1573 free_evalue_refs(mask
);
1577 assert(value_zero_p(mask
->d
));
1578 assert(mask
->x
.p
->type
== partition
);
1579 assert(value_zero_p(res
->d
));
1580 assert(res
->x
.p
->type
== partition
);
1581 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1582 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1583 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1584 pos
= res
->x
.p
->pos
;
1586 s
= (struct section
*)
1587 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1588 sizeof(struct section
));
1592 evalue_set_si(&mone
, -1, 1);
1595 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1596 assert(mask
->x
.p
->size
>= 2);
1597 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1598 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1600 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1602 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1611 value_init(s
[n
].E
.d
);
1612 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1616 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1617 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1620 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1621 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1622 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1623 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1625 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1626 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1632 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1633 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1635 value_init(s
[n
].E
.d
);
1636 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1637 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1643 /* Just ignore; this may have been previously masked off */
1645 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1649 free_evalue_refs(&mone
);
1650 free_evalue_refs(mask
);
1651 free_evalue_refs(res
);
1654 evalue_set_si(res
, 0, 1);
1656 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1657 for (j
= 0; j
< n
; ++j
) {
1658 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1659 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1660 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1667 void evalue_copy(evalue
*dst
, evalue
*src
)
1669 value_assign(dst
->d
, src
->d
);
1670 if(value_notzero_p(src
->d
)) {
1671 value_init(dst
->x
.n
);
1672 value_assign(dst
->x
.n
, src
->x
.n
);
1674 dst
->x
.p
= ecopy(src
->x
.p
);
1677 enode
*new_enode(enode_type type
,int size
,int pos
) {
1683 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1686 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1690 for(i
=0; i
<size
; i
++) {
1691 value_init(res
->arr
[i
].d
);
1692 value_set_si(res
->arr
[i
].d
,0);
1693 res
->arr
[i
].x
.p
= 0;
1698 enode
*ecopy(enode
*e
) {
1703 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1704 for(i
=0;i
<e
->size
;++i
) {
1705 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1706 if(value_zero_p(res
->arr
[i
].d
))
1707 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1708 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1709 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1711 value_init(res
->arr
[i
].x
.n
);
1712 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1718 int ecmp(const evalue
*e1
, const evalue
*e2
)
1724 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1728 value_multiply(m
, e1
->x
.n
, e2
->d
);
1729 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1731 if (value_lt(m
, m2
))
1733 else if (value_gt(m
, m2
))
1743 if (value_notzero_p(e1
->d
))
1745 if (value_notzero_p(e2
->d
))
1751 if (p1
->type
!= p2
->type
)
1752 return p1
->type
- p2
->type
;
1753 if (p1
->pos
!= p2
->pos
)
1754 return p1
->pos
- p2
->pos
;
1755 if (p1
->size
!= p2
->size
)
1756 return p1
->size
- p2
->size
;
1758 for (i
= p1
->size
-1; i
>= 0; --i
)
1759 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1765 int eequal(evalue
*e1
,evalue
*e2
) {
1770 if (value_ne(e1
->d
,e2
->d
))
1773 /* e1->d == e2->d */
1774 if (value_notzero_p(e1
->d
)) {
1775 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1778 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1782 /* e1->d == e2->d == 0 */
1785 if (p1
->type
!= p2
->type
) return 0;
1786 if (p1
->size
!= p2
->size
) return 0;
1787 if (p1
->pos
!= p2
->pos
) return 0;
1788 for (i
=0; i
<p1
->size
; i
++)
1789 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1794 void free_evalue_refs(evalue
*e
) {
1799 if (EVALUE_IS_DOMAIN(*e
)) {
1800 Domain_Free(EVALUE_DOMAIN(*e
));
1803 } else if (value_pos_p(e
->d
)) {
1805 /* 'e' stores a constant */
1807 value_clear(e
->x
.n
);
1810 assert(value_zero_p(e
->d
));
1813 if (!p
) return; /* null pointer */
1814 for (i
=0; i
<p
->size
; i
++) {
1815 free_evalue_refs(&(p
->arr
[i
]));
1819 } /* free_evalue_refs */
1821 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1822 Vector
* val
, evalue
*res
)
1824 unsigned nparam
= periods
->Size
;
1827 double d
= compute_evalue(e
, val
->p
);
1828 d
*= VALUE_TO_DOUBLE(m
);
1833 value_assign(res
->d
, m
);
1834 value_init(res
->x
.n
);
1835 value_set_double(res
->x
.n
, d
);
1836 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1839 if (value_one_p(periods
->p
[p
]))
1840 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1845 value_assign(tmp
, periods
->p
[p
]);
1846 value_set_si(res
->d
, 0);
1847 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1849 value_decrement(tmp
, tmp
);
1850 value_assign(val
->p
[p
], tmp
);
1851 mod2table_r(e
, periods
, m
, p
+1, val
,
1852 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1853 } while (value_pos_p(tmp
));
1859 static void rel2table(evalue
*e
, int zero
)
1861 if (value_pos_p(e
->d
)) {
1862 if (value_zero_p(e
->x
.n
) == zero
)
1863 value_set_si(e
->x
.n
, 1);
1865 value_set_si(e
->x
.n
, 0);
1866 value_set_si(e
->d
, 1);
1869 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1870 rel2table(&e
->x
.p
->arr
[i
], zero
);
1874 void evalue_mod2table(evalue
*e
, int nparam
)
1879 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1882 for (i
=0; i
<p
->size
; i
++) {
1883 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1885 if (p
->type
== relation
) {
1890 evalue_copy(©
, &p
->arr
[0]);
1892 rel2table(&p
->arr
[0], 1);
1893 emul(&p
->arr
[0], &p
->arr
[1]);
1895 rel2table(©
, 0);
1896 emul(©
, &p
->arr
[2]);
1897 eadd(&p
->arr
[2], &p
->arr
[1]);
1898 free_evalue_refs(&p
->arr
[2]);
1899 free_evalue_refs(©
);
1901 free_evalue_refs(&p
->arr
[0]);
1905 } else if (p
->type
== fractional
) {
1906 Vector
*periods
= Vector_Alloc(nparam
);
1907 Vector
*val
= Vector_Alloc(nparam
);
1913 value_set_si(tmp
, 1);
1914 Vector_Set(periods
->p
, 1, nparam
);
1915 Vector_Set(val
->p
, 0, nparam
);
1916 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1919 assert(p
->type
== polynomial
);
1920 assert(p
->size
== 2);
1921 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
1922 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
1925 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1928 evalue_set_si(&res
, 0, 1);
1929 /* Compute the polynomial using Horner's rule */
1930 for (i
=p
->size
-1;i
>1;i
--) {
1931 eadd(&p
->arr
[i
], &res
);
1934 eadd(&p
->arr
[1], &res
);
1936 free_evalue_refs(e
);
1937 free_evalue_refs(&EP
);
1942 Vector_Free(periods
);
1944 } /* evalue_mod2table */
1946 /********************************************************/
1947 /* function in domain */
1948 /* check if the parameters in list_args */
1949 /* verifies the constraints of Domain P */
1950 /********************************************************/
1951 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1954 Value v
; /* value of the constraint of a row when
1955 parameters are instanciated*/
1961 /*P->Constraint constraint matrice of polyhedron P*/
1962 for(row
=0;row
<P
->NbConstraints
;row
++) {
1963 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1964 for(col
=1;col
<P
->Dimension
+1;col
++) {
1965 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1966 value_addto(v
,v
,tmp
);
1968 if (value_notzero_p(P
->Constraint
[row
][0])) {
1970 /*if v is not >=0 then this constraint is not respected */
1971 if (value_neg_p(v
)) {
1975 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1980 /*if v is not = 0 then this constraint is not respected */
1981 if (value_notzero_p(v
))
1986 /*if not return before this point => all
1987 the constraints are respected */
1993 /****************************************************/
1994 /* function compute enode */
1995 /* compute the value of enode p with parameters */
1996 /* list "list_args */
1997 /* compute the polynomial or the periodic */
1998 /****************************************************/
2000 static double compute_enode(enode
*p
, Value
*list_args
) {
2012 if (p
->type
== polynomial
) {
2014 value_assign(param
,list_args
[p
->pos
-1]);
2016 /* Compute the polynomial using Horner's rule */
2017 for (i
=p
->size
-1;i
>0;i
--) {
2018 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2019 res
*=VALUE_TO_DOUBLE(param
);
2021 res
+=compute_evalue(&p
->arr
[0],list_args
);
2023 else if (p
->type
== fractional
) {
2024 double d
= compute_evalue(&p
->arr
[0], list_args
);
2025 d
-= floor(d
+1e-10);
2027 /* Compute the polynomial using Horner's rule */
2028 for (i
=p
->size
-1;i
>1;i
--) {
2029 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2032 res
+=compute_evalue(&p
->arr
[1],list_args
);
2034 else if (p
->type
== flooring
) {
2035 double d
= compute_evalue(&p
->arr
[0], list_args
);
2038 /* Compute the polynomial using Horner's rule */
2039 for (i
=p
->size
-1;i
>1;i
--) {
2040 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2043 res
+=compute_evalue(&p
->arr
[1],list_args
);
2045 else if (p
->type
== periodic
) {
2046 value_assign(param
,list_args
[p
->pos
-1]);
2048 /* Choose the right element of the periodic */
2049 value_absolute(m
,param
);
2050 value_set_si(param
,p
->size
);
2051 value_modulus(m
,m
,param
);
2052 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2054 else if (p
->type
== relation
) {
2055 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2056 res
= compute_evalue(&p
->arr
[1], list_args
);
2057 else if (p
->size
> 2)
2058 res
= compute_evalue(&p
->arr
[2], list_args
);
2060 else if (p
->type
== partition
) {
2061 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2062 Value
*vals
= list_args
;
2065 for (i
= 0; i
< dim
; ++i
) {
2066 value_init(vals
[i
]);
2068 value_assign(vals
[i
], list_args
[i
]);
2071 for (i
= 0; i
< p
->size
/2; ++i
)
2072 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2073 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2077 for (i
= 0; i
< dim
; ++i
)
2078 value_clear(vals
[i
]);
2087 } /* compute_enode */
2089 /*************************************************/
2090 /* return the value of Ehrhart Polynomial */
2091 /* It returns a double, because since it is */
2092 /* a recursive function, some intermediate value */
2093 /* might not be integral */
2094 /*************************************************/
2096 double compute_evalue(evalue
*e
,Value
*list_args
) {
2100 if (value_notzero_p(e
->d
)) {
2101 if (value_notone_p(e
->d
))
2102 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2104 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2107 res
= compute_enode(e
->x
.p
,list_args
);
2109 } /* compute_evalue */
2112 /****************************************************/
2113 /* function compute_poly : */
2114 /* Check for the good validity domain */
2115 /* return the number of point in the Polyhedron */
2116 /* in allocated memory */
2117 /* Using the Ehrhart pseudo-polynomial */
2118 /****************************************************/
2119 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2122 /* double d; int i; */
2124 tmp
= (Value
*) malloc (sizeof(Value
));
2125 assert(tmp
!= NULL
);
2127 value_set_si(*tmp
,0);
2130 return(tmp
); /* no ehrhart polynomial */
2131 if(en
->ValidityDomain
) {
2132 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2133 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2138 return(tmp
); /* no Validity Domain */
2140 if(in_domain(en
->ValidityDomain
,list_args
)) {
2142 #ifdef EVAL_EHRHART_DEBUG
2143 Print_Domain(stdout
,en
->ValidityDomain
);
2144 print_evalue(stdout
,&en
->EP
);
2147 /* d = compute_evalue(&en->EP,list_args);
2149 printf("(double)%lf = %d\n", d, i ); */
2150 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2156 value_set_si(*tmp
,0);
2157 return(tmp
); /* no compatible domain with the arguments */
2158 } /* compute_poly */
2160 size_t value_size(Value v
) {
2161 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2162 * sizeof(v
[0]._mp_d
[0]);
2165 size_t domain_size(Polyhedron
*D
)
2168 size_t s
= sizeof(*D
);
2170 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2171 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2172 s
+= value_size(D
->Constraint
[i
][j
]);
2175 for (i = 0; i < D->NbRays; ++i)
2176 for (j = 0; j < D->Dimension+2; ++j)
2177 s += value_size(D->Ray[i][j]);
2180 return D
->next
? s
+domain_size(D
->next
) : s
;
2183 size_t enode_size(enode
*p
) {
2184 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2187 if (p
->type
== partition
)
2188 for (i
= 0; i
< p
->size
/2; ++i
) {
2189 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2190 s
+= evalue_size(&p
->arr
[2*i
+1]);
2193 for (i
= 0; i
< p
->size
; ++i
) {
2194 s
+= evalue_size(&p
->arr
[i
]);
2199 size_t evalue_size(evalue
*e
)
2201 size_t s
= sizeof(*e
);
2202 s
+= value_size(e
->d
);
2203 if (value_notzero_p(e
->d
))
2204 s
+= value_size(e
->x
.n
);
2206 s
+= enode_size(e
->x
.p
);
2210 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2212 evalue
*found
= NULL
;
2217 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2220 value_init(offset
.d
);
2221 value_init(offset
.x
.n
);
2222 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2223 value_lcm(m
, offset
.d
, &offset
.d
);
2224 value_set_si(offset
.x
.n
, 1);
2227 evalue_copy(©
, cst
);
2230 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2232 if (eequal(base
, &e
->x
.p
->arr
[0]))
2233 found
= &e
->x
.p
->arr
[0];
2235 value_set_si(offset
.x
.n
, -2);
2238 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2240 if (eequal(base
, &e
->x
.p
->arr
[0]))
2243 free_evalue_refs(cst
);
2244 free_evalue_refs(&offset
);
2247 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2248 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2253 static evalue
*find_relation_pair(evalue
*e
)
2256 evalue
*found
= NULL
;
2258 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2261 if (e
->x
.p
->type
== fractional
) {
2266 poly_denom(&e
->x
.p
->arr
[0], &m
);
2268 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2269 cst
= &cst
->x
.p
->arr
[0])
2272 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2273 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2278 i
= e
->x
.p
->type
== relation
;
2279 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2280 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2285 void evalue_mod2relation(evalue
*e
) {
2288 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2291 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2292 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2293 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2294 value_clear(e
->x
.p
->arr
[2*i
].d
);
2295 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2297 if (2*i
< e
->x
.p
->size
) {
2298 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2299 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2304 if (e
->x
.p
->size
== 0) {
2306 evalue_set_si(e
, 0, 1);
2312 while ((d
= find_relation_pair(e
)) != NULL
) {
2316 value_init(split
.d
);
2317 value_set_si(split
.d
, 0);
2318 split
.x
.p
= new_enode(relation
, 3, 0);
2319 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2320 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2322 ev
= &split
.x
.p
->arr
[0];
2323 value_set_si(ev
->d
, 0);
2324 ev
->x
.p
= new_enode(fractional
, 3, -1);
2325 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2326 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2327 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2333 free_evalue_refs(&split
);
2337 static int evalue_comp(const void * a
, const void * b
)
2339 const evalue
*e1
= *(const evalue
**)a
;
2340 const evalue
*e2
= *(const evalue
**)b
;
2341 return ecmp(e1
, e2
);
2344 void evalue_combine(evalue
*e
)
2351 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2354 NALLOC(evs
, e
->x
.p
->size
/2);
2355 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2356 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2357 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2358 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2359 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2360 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2361 value_clear(p
->arr
[2*k
].d
);
2362 value_clear(p
->arr
[2*k
+1].d
);
2363 p
->arr
[2*k
] = *(evs
[i
]-1);
2364 p
->arr
[2*k
+1] = *(evs
[i
]);
2367 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2370 value_clear((evs
[i
]-1)->d
);
2374 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2375 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2376 free_evalue_refs(evs
[i
]);
2380 for (i
= 2*k
; i
< p
->size
; ++i
)
2381 value_clear(p
->arr
[i
].d
);
2388 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2390 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2392 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2395 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2396 Polyhedron
*D
, *N
, **P
;
2399 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2406 if (D
->NbEq
<= H
->NbEq
) {
2412 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2413 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2414 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2415 reduce_evalue(&tmp
);
2416 if (value_notzero_p(tmp
.d
) ||
2417 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2420 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2421 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2424 free_evalue_refs(&tmp
);
2430 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2432 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2434 value_clear(e
->x
.p
->arr
[2*i
].d
);
2435 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2437 if (2*i
< e
->x
.p
->size
) {
2438 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2439 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2446 H
= DomainConvex(D
, 0);
2447 E
= DomainDifference(H
, D
, 0);
2449 D
= DomainDifference(H
, E
, 0);
2452 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2456 /* May change coefficients to become non-standard if fiddle is set
2457 * => reduce p afterwards to correct
2459 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2460 Matrix
**R
, int fiddle
)
2464 unsigned dim
= D
->Dimension
;
2465 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2470 assert(p
->type
== fractional
);
2472 value_set_si(T
->p
[1][dim
], 1);
2474 while (value_zero_p(pp
->d
)) {
2475 assert(pp
->x
.p
->type
== polynomial
);
2476 assert(pp
->x
.p
->size
== 2);
2477 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2478 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2479 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2480 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2481 value_substract(pp
->x
.p
->arr
[1].x
.n
,
2482 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2483 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2484 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2485 pp
= &pp
->x
.p
->arr
[0];
2487 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2488 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2489 I
= DomainImage(D
, T
, 0);
2490 H
= DomainConvex(I
, 0);
2499 static int reduce_in_domain(evalue
*e
, Polyhedron
*D
)
2509 if (value_notzero_p(e
->d
))
2514 if (p
->type
== relation
) {
2520 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2521 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2522 equal
= value_eq(min
, max
);
2523 mpz_cdiv_q(min
, min
, d
);
2524 mpz_fdiv_q(max
, max
, d
);
2526 if (bounded
&& value_gt(min
, max
)) {
2532 evalue_set_si(e
, 0, 1);
2535 free_evalue_refs(&(p
->arr
[1]));
2536 free_evalue_refs(&(p
->arr
[0]));
2542 return r
? r
: reduce_in_domain(e
, D
);
2543 } else if (bounded
&& equal
) {
2546 free_evalue_refs(&(p
->arr
[2]));
2549 free_evalue_refs(&(p
->arr
[0]));
2555 return reduce_in_domain(e
, D
);
2556 } else if (bounded
&& value_eq(min
, max
)) {
2557 /* zero for a single value */
2559 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2560 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2561 value_multiply(min
, min
, d
);
2562 value_substract(M
->p
[0][D
->Dimension
+1],
2563 M
->p
[0][D
->Dimension
+1], min
);
2564 E
= DomainAddConstraints(D
, M
, 0);
2570 r
= reduce_in_domain(&p
->arr
[1], E
);
2572 r
|= reduce_in_domain(&p
->arr
[2], D
);
2574 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2582 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2585 i
= p
->type
== relation
? 1 :
2586 p
->type
== fractional
? 1 : 0;
2587 for (; i
<p
->size
; i
++)
2588 r
|= reduce_in_domain(&p
->arr
[i
], D
);
2590 if (p
->type
!= fractional
) {
2591 if (r
&& p
->type
== polynomial
) {
2594 value_set_si(f
.d
, 0);
2595 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2596 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2597 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2598 reorder_terms(p
, &f
);
2609 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2611 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2612 mpz_fdiv_q(min
, min
, d
);
2613 mpz_fdiv_q(max
, max
, d
);
2614 value_substract(d
, max
, min
);
2616 if (bounded
&& value_eq(min
, max
)) {
2619 value_init(inc
.x
.n
);
2620 value_set_si(inc
.d
, 1);
2621 value_oppose(inc
.x
.n
, min
);
2622 eadd(&inc
, &p
->arr
[0]);
2623 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2627 free_evalue_refs(&inc
);
2629 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2636 value_set_si(rem
.d
, 0);
2637 rem
.x
.p
= new_enode(fractional
, 3, -1);
2638 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2639 rem
.x
.p
->arr
[1] = p
->arr
[1];
2640 rem
.x
.p
->arr
[2] = p
->arr
[2];
2641 for (i
= 3; i
< p
->size
; ++i
)
2642 p
->arr
[i
-2] = p
->arr
[i
];
2646 value_init(inc
.x
.n
);
2647 value_set_si(inc
.d
, 1);
2648 value_oppose(inc
.x
.n
, min
);
2651 evalue_copy(&t
, &p
->arr
[0]);
2655 value_set_si(f
.d
, 0);
2656 f
.x
.p
= new_enode(fractional
, 3, -1);
2657 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2658 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2659 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2661 value_init(factor
.d
);
2662 evalue_set_si(&factor
, -1, 1);
2668 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2669 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2675 free_evalue_refs(&inc
);
2676 free_evalue_refs(&t
);
2677 free_evalue_refs(&f
);
2678 free_evalue_refs(&factor
);
2679 free_evalue_refs(&rem
);
2681 reduce_in_domain(e
, D
);
2685 _reduce_evalue(&p
->arr
[0], 0, 1);
2689 value_set_si(f
.d
, 0);
2690 f
.x
.p
= new_enode(fractional
, 3, -1);
2691 value_clear(f
.x
.p
->arr
[0].d
);
2692 f
.x
.p
->arr
[0] = p
->arr
[0];
2693 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2694 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2695 reorder_terms(p
, &f
);
2709 void evalue_range_reduction(evalue
*e
)
2712 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2715 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2716 if (reduce_in_domain(&e
->x
.p
->arr
[2*i
+1],
2717 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2718 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2720 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2721 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2722 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2723 value_clear(e
->x
.p
->arr
[2*i
].d
);
2725 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2726 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2734 Enumeration
* partition2enumeration(evalue
*EP
)
2737 Enumeration
*en
, *res
= NULL
;
2739 if (EVALUE_IS_ZERO(*EP
)) {
2744 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2745 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
2746 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2749 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2750 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2751 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2759 static int frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2769 if (value_notzero_p(e
->d
))
2774 i
= p
->type
== relation
? 1 :
2775 p
->type
== fractional
? 1 : 0;
2776 for (; i
<p
->size
; i
++)
2777 r
|= frac2floor_in_domain(&p
->arr
[i
], D
);
2779 if (p
->type
!= fractional
) {
2780 if (r
&& p
->type
== polynomial
) {
2783 value_set_si(f
.d
, 0);
2784 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2785 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2786 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2787 reorder_terms(p
, &f
);
2796 I
= polynomial_projection(p
, D
, &d
, &T
, 0);
2799 Polyhedron_Print(stderr, P_VALUE_FMT, I);
2802 assert(I
->NbEq
== 0); /* Should have been reduced */
2805 for (i
= 0; i
< I
->NbConstraints
; ++i
)
2806 if (value_pos_p(I
->Constraint
[i
][1]))
2809 assert(i
< I
->NbConstraints
);
2811 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
2812 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
2813 if (value_neg_p(min
)) {
2815 mpz_fdiv_q(min
, min
, d
);
2816 value_init(offset
.d
);
2817 value_set_si(offset
.d
, 1);
2818 value_init(offset
.x
.n
);
2819 value_oppose(offset
.x
.n
, min
);
2820 eadd(&offset
, &p
->arr
[0]);
2821 free_evalue_refs(&offset
);
2830 value_set_si(fl
.d
, 0);
2831 fl
.x
.p
= new_enode(flooring
, 3, -1);
2832 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2833 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2834 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2836 eadd(&fl
, &p
->arr
[0]);
2837 reorder_terms(p
, &p
->arr
[0]);
2840 free_evalue_refs(&fl
);
2845 void evalue_frac2floor(evalue
*e
)
2848 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2851 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2852 if (frac2floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
2853 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])))
2854 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2857 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2862 int nparam
= D
->Dimension
- nvar
;
2865 nr
= D
->NbConstraints
+ 2;
2866 nc
= D
->Dimension
+ 2 + 1;
2867 C
= Matrix_Alloc(nr
, nc
);
2868 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2869 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
2870 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2871 D
->Dimension
+ 1 - nvar
);
2876 nc
= C
->NbColumns
+ 1;
2877 C
= Matrix_Alloc(nr
, nc
);
2878 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
2879 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
2880 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2881 oldC
->NbColumns
- 1 - nvar
);
2884 value_set_si(C
->p
[nr
-2][0], 1);
2885 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
2886 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
2888 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
2889 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
2895 static void floor2frac_r(evalue
*e
, int nvar
)
2902 if (value_notzero_p(e
->d
))
2907 assert(p
->type
== flooring
);
2908 for (i
= 1; i
< p
->size
; i
++)
2909 floor2frac_r(&p
->arr
[i
], nvar
);
2911 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
2912 assert(pp
->x
.p
->type
== polynomial
);
2913 pp
->x
.p
->pos
-= nvar
;
2917 value_set_si(f
.d
, 0);
2918 f
.x
.p
= new_enode(fractional
, 3, -1);
2919 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2920 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2921 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2923 eadd(&f
, &p
->arr
[0]);
2924 reorder_terms(p
, &p
->arr
[0]);
2927 free_evalue_refs(&f
);
2930 /* Convert flooring back to fractional and shift position
2931 * of the parameters by nvar
2933 static void floor2frac(evalue
*e
, int nvar
)
2935 floor2frac_r(e
, nvar
);
2939 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
2942 int nparam
= D
->Dimension
- nvar
;
2946 D
= Constraints2Polyhedron(C
, 0);
2950 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
2952 /* Double check that D was not unbounded. */
2953 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
2961 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
2968 evalue
*factor
= NULL
;
2971 if (EVALUE_IS_ZERO(*e
))
2975 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
2982 res
= esum_over_domain(e
, nvar
, Q
, C
);
2985 for (Q
= DD
; Q
; Q
= DD
) {
2991 t
= esum_over_domain(e
, nvar
, Q
, C
);
2998 free_evalue_refs(t
);
3005 if (value_notzero_p(e
->d
)) {
3008 t
= esum_over_domain_cst(nvar
, D
, C
);
3010 if (!EVALUE_IS_ONE(*e
))
3016 switch (e
->x
.p
->type
) {
3018 evalue
*pp
= &e
->x
.p
->arr
[0];
3020 if (pp
->x
.p
->pos
> nvar
) {
3021 /* remainder is independent of the summated vars */
3027 floor2frac(&f
, nvar
);
3029 t
= esum_over_domain_cst(nvar
, D
, C
);
3033 free_evalue_refs(&f
);
3038 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3039 poly_denom(pp
, &row
->p
[1 + nvar
]);
3040 value_set_si(row
->p
[0], 1);
3041 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3042 pp
= &pp
->x
.p
->arr
[0]) {
3044 assert(pp
->x
.p
->type
== polynomial
);
3046 if (pos
>= 1 + nvar
)
3048 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3049 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3050 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3052 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3053 value_division(row
->p
[1 + D
->Dimension
+ 1],
3054 row
->p
[1 + D
->Dimension
+ 1],
3056 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3057 row
->p
[1 + D
->Dimension
+ 1],
3059 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3063 int pos
= e
->x
.p
->pos
;
3067 value_init(factor
->d
);
3068 value_set_si(factor
->d
, 0);
3069 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3070 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3071 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3075 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3076 for (i
= 0; i
< D
->NbRays
; ++i
)
3077 if (value_notzero_p(D
->Ray
[i
][pos
]))
3079 assert(i
< D
->NbRays
);
3080 if (value_neg_p(D
->Ray
[i
][pos
])) {
3082 value_init(factor
->d
);
3083 evalue_set_si(factor
, -1, 1);
3085 value_set_si(row
->p
[0], 1);
3086 value_set_si(row
->p
[pos
], 1);
3087 value_set_si(row
->p
[1 + nvar
], -1);
3094 i
= type_offset(e
->x
.p
);
3096 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3101 evalue_copy(&cum
, factor
);
3105 for (; i
< e
->x
.p
->size
; ++i
) {
3109 C
= esum_add_constraint(nvar
, D
, C
, row
);
3115 Vector_Print(stderr, P_VALUE_FMT, row);
3117 Matrix_Print(stderr, P_VALUE_FMT, C);
3119 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3128 free_evalue_refs(t
);
3131 if (factor
&& i
+1 < e
->x
.p
->size
)
3138 free_evalue_refs(factor
);
3139 free_evalue_refs(&cum
);
3151 evalue
*esum(evalue
*e
, int nvar
)
3159 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3160 evalue_copy(res
, e
);
3164 evalue_set_si(res
, 0, 1);
3166 assert(value_zero_p(e
->d
));
3167 assert(e
->x
.p
->type
== partition
);
3169 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3171 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3172 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3174 free_evalue_refs(t
);
3183 /* Initial silly implementation */
3184 void eor(evalue
*e1
, evalue
*res
)
3190 evalue_set_si(&mone
, -1, 1);
3192 evalue_copy(&E
, res
);
3198 free_evalue_refs(&E
);
3199 free_evalue_refs(&mone
);