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 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
83 assert(value_notzero_p(e1
->d
));
84 assert(value_notzero_p(e2
->d
));
85 value_multiply(m
, e1
->x
.n
, e2
->d
);
86 value_multiply(m2
, e2
->x
.n
, e1
->d
);
89 else if (value_gt(m
, m2
))
99 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
101 if (value_notzero_p(e1
->d
)) {
102 if (value_zero_p(e2
->d
))
104 int r
= mod_rational_smaller(e1
, e2
);
105 return r
== -1 ? 0 : r
;
107 if (value_notzero_p(e2
->d
))
109 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
111 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
114 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
116 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
121 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
123 assert(value_zero_p(e1
->d
));
124 assert(value_zero_p(e2
->d
));
125 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
126 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
127 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
130 /* Negative pos means inequality */
131 /* s is negative of substitution if m is not zero */
140 struct fixed_param
*fixed
;
145 static int relations_depth(evalue
*e
)
150 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
151 e
= &e
->x
.p
->arr
[1], ++d
);
155 static void Lcm3(Value i
, Value j
, Value
*res
)
161 value_multiply(*res
,i
,j
);
162 value_division(*res
, *res
, aux
);
166 static void poly_denom(evalue
*p
, Value
*d
)
170 while (value_zero_p(p
->d
)) {
171 assert(p
->x
.p
->type
== polynomial
);
172 assert(p
->x
.p
->size
== 2);
173 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
174 Lcm3(*d
, p
->x
.p
->arr
[1].d
, d
);
180 #define EVALUE_IS_ONE(ev) (value_one_p((ev).d) && value_one_p((ev).x.n))
182 static void realloc_substitution(struct subst
*s
, int d
)
184 struct fixed_param
*n
;
187 for (i
= 0; i
< s
->n
; ++i
)
194 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
200 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
203 /* May have been reduced already */
204 if (value_notzero_p(m
->d
))
207 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
208 assert(m
->x
.p
->size
== 3);
210 /* fractional was inverted during reduction
211 * invert it back and move constant in
213 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
214 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
215 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
216 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
217 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
218 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
219 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
220 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
221 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
222 value_set_si(m
->x
.p
->arr
[1].d
, 1);
225 /* Oops. Nested identical relations. */
226 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
229 if (s
->n
>= s
->max
) {
230 int d
= relations_depth(r
);
231 realloc_substitution(s
, d
);
235 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
236 assert(p
->x
.p
->size
== 2);
239 assert(value_pos_p(f
->x
.n
));
241 value_init(s
->fixed
[s
->n
].m
);
242 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
243 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
244 value_init(s
->fixed
[s
->n
].d
);
245 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
246 value_init(s
->fixed
[s
->n
].s
.d
);
247 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
253 static int type_offset(enode
*p
)
255 return p
->type
== fractional
? 1 :
256 p
->type
== flooring
? 1 : 0;
259 static void reorder_terms(enode
*p
, evalue
*v
)
262 int offset
= type_offset(p
);
264 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
266 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
267 free_evalue_refs(&(p
->arr
[i
]));
273 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
279 if (value_notzero_p(e
->d
)) {
281 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
282 return; /* a rational number, its already reduced */
286 return; /* hum... an overflow probably occured */
288 /* First reduce the components of p */
289 add
= p
->type
== relation
;
290 for (i
=0; i
<p
->size
; i
++) {
292 add
= add_modulo_substitution(s
, e
);
294 if (i
== 0 && p
->type
==fractional
)
295 _reduce_evalue(&p
->arr
[i
], s
, 1);
297 _reduce_evalue(&p
->arr
[i
], s
, fract
);
299 if (add
&& i
== p
->size
-1) {
301 value_clear(s
->fixed
[s
->n
].m
);
302 value_clear(s
->fixed
[s
->n
].d
);
303 free_evalue_refs(&s
->fixed
[s
->n
].s
);
304 } else if (add
&& i
== 1)
305 s
->fixed
[s
->n
-1].pos
*= -1;
308 if (p
->type
==periodic
) {
310 /* Try to reduce the period */
311 for (i
=1; i
<=(p
->size
)/2; i
++) {
312 if ((p
->size
% i
)==0) {
314 /* Can we reduce the size to i ? */
316 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
317 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
320 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
324 you_lose
: /* OK, lets not do it */
329 /* Try to reduce its strength */
332 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
336 else if (p
->type
==polynomial
) {
337 for (k
= 0; s
&& k
< s
->n
; ++k
) {
338 if (s
->fixed
[k
].pos
== p
->pos
) {
339 int divide
= value_notone_p(s
->fixed
[k
].d
);
342 if (value_notzero_p(s
->fixed
[k
].m
)) {
345 assert(p
->size
== 2);
346 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
348 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
355 value_assign(d
.d
, s
->fixed
[k
].d
);
357 if (value_notzero_p(s
->fixed
[k
].m
))
358 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
360 value_set_si(d
.x
.n
, 1);
363 for (i
=p
->size
-1;i
>=1;i
--) {
364 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
366 emul(&d
, &p
->arr
[i
]);
367 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
368 free_evalue_refs(&(p
->arr
[i
]));
371 _reduce_evalue(&p
->arr
[0], s
, fract
);
374 free_evalue_refs(&d
);
380 /* Try to reduce the degree */
381 for (i
=p
->size
-1;i
>=1;i
--) {
382 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
384 /* Zero coefficient */
385 free_evalue_refs(&(p
->arr
[i
]));
390 /* Try to reduce its strength */
393 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
397 else if (p
->type
==fractional
) {
401 if (value_notzero_p(p
->arr
[0].d
)) {
403 value_assign(v
.d
, p
->arr
[0].d
);
405 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
410 evalue
*pp
= &p
->arr
[0];
411 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
412 assert(pp
->x
.p
->size
== 2);
414 /* search for exact duplicate among the modulo inequalities */
416 f
= &pp
->x
.p
->arr
[1];
417 for (k
= 0; s
&& k
< s
->n
; ++k
) {
418 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
419 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
420 value_eq(s
->fixed
[k
].m
, f
->d
) &&
421 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
428 /* replace { E/m } by { (E-1)/m } + 1/m */
433 evalue_set_si(&extra
, 1, 1);
434 value_assign(extra
.d
, g
);
435 eadd(&extra
, &v
.x
.p
->arr
[1]);
436 free_evalue_refs(&extra
);
438 /* We've been going in circles; stop now */
439 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
440 free_evalue_refs(&v
);
442 evalue_set_si(&v
, 0, 1);
447 value_set_si(v
.d
, 0);
448 v
.x
.p
= new_enode(fractional
, 3, -1);
449 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
450 value_assign(v
.x
.p
->arr
[1].d
, g
);
451 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
452 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
455 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
458 value_division(f
->d
, g
, f
->d
);
459 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
460 value_assign(f
->d
, g
);
461 value_decrement(f
->x
.n
, f
->x
.n
);
462 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
464 Gcd(f
->d
, f
->x
.n
, &g
);
465 value_division(f
->d
, f
->d
, g
);
466 value_division(f
->x
.n
, f
->x
.n
, g
);
475 /* reduction may have made this fractional arg smaller */
476 i
= reorder
? p
->size
: 1;
477 for ( ; i
< p
->size
; ++i
)
478 if (value_zero_p(p
->arr
[i
].d
) &&
479 p
->arr
[i
].x
.p
->type
== fractional
&&
480 !mod_term_smaller(e
, &p
->arr
[i
]))
484 value_set_si(v
.d
, 0);
485 v
.x
.p
= new_enode(fractional
, 3, -1);
486 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
487 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
488 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
498 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
499 pp
= &pp
->x
.p
->arr
[0]) {
500 f
= &pp
->x
.p
->arr
[1];
501 assert(value_pos_p(f
->d
));
502 mpz_mul_ui(twice
, f
->x
.n
, 2);
503 if (value_lt(twice
, f
->d
))
505 if (value_eq(twice
, f
->d
))
513 value_set_si(v
.d
, 0);
514 v
.x
.p
= new_enode(fractional
, 3, -1);
515 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
516 poly_denom(&p
->arr
[0], &twice
);
517 value_assign(v
.x
.p
->arr
[1].d
, twice
);
518 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
519 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
520 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
522 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
523 pp
= &pp
->x
.p
->arr
[0]) {
524 f
= &pp
->x
.p
->arr
[1];
525 value_oppose(f
->x
.n
, f
->x
.n
);
526 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
528 value_division(pp
->d
, twice
, pp
->d
);
529 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
530 value_assign(pp
->d
, twice
);
531 value_oppose(pp
->x
.n
, pp
->x
.n
);
532 value_decrement(pp
->x
.n
, pp
->x
.n
);
533 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
543 reorder_terms(p
, &v
);
544 _reduce_evalue(&p
->arr
[1], s
, fract
);
547 /* Try to reduce the degree */
548 for (i
=p
->size
-1;i
>=2;i
--) {
549 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
551 /* Zero coefficient */
552 free_evalue_refs(&(p
->arr
[i
]));
557 /* Try to reduce its strength */
560 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
561 free_evalue_refs(&(p
->arr
[0]));
565 else if (p
->type
== flooring
) {
566 /* Try to reduce the degree */
567 for (i
=p
->size
-1;i
>=2;i
--) {
568 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
570 /* Zero coefficient */
571 free_evalue_refs(&(p
->arr
[i
]));
576 /* Try to reduce its strength */
579 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
580 free_evalue_refs(&(p
->arr
[0]));
584 else if (p
->type
== relation
) {
585 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
586 free_evalue_refs(&(p
->arr
[2]));
587 free_evalue_refs(&(p
->arr
[0]));
594 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
595 free_evalue_refs(&(p
->arr
[2]));
598 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
599 free_evalue_refs(&(p
->arr
[1]));
600 free_evalue_refs(&(p
->arr
[0]));
601 evalue_set_si(e
, 0, 1);
608 /* Relation was reduced by means of an identical
609 * inequality => remove
611 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
614 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
615 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
617 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
619 free_evalue_refs(&(p
->arr
[2]));
623 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
625 evalue_set_si(e
, 0, 1);
626 free_evalue_refs(&(p
->arr
[1]));
628 free_evalue_refs(&(p
->arr
[0]));
634 } /* reduce_evalue */
636 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
641 for (k
= 0; k
< dim
; ++k
)
642 if (value_notzero_p(row
[k
+1]))
645 Vector_Normalize_Positive(row
+1, dim
+1, k
);
646 assert(s
->n
< s
->max
);
647 value_init(s
->fixed
[s
->n
].d
);
648 value_init(s
->fixed
[s
->n
].m
);
649 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
650 s
->fixed
[s
->n
].pos
= k
+1;
651 value_set_si(s
->fixed
[s
->n
].m
, 0);
652 r
= &s
->fixed
[s
->n
].s
;
654 for (l
= k
+1; l
< dim
; ++l
)
655 if (value_notzero_p(row
[l
+1])) {
656 value_set_si(r
->d
, 0);
657 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
658 value_init(r
->x
.p
->arr
[1].x
.n
);
659 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
660 value_set_si(r
->x
.p
->arr
[1].d
, 1);
664 value_oppose(r
->x
.n
, row
[dim
+1]);
665 value_set_si(r
->d
, 1);
669 void reduce_evalue (evalue
*e
) {
670 struct subst s
= { NULL
, 0, 0 };
672 if (value_notzero_p(e
->d
))
673 return; /* a rational number, its already reduced */
675 if (e
->x
.p
->type
== partition
) {
678 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
680 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
681 /* This shouldn't really happen;
682 * Empty domains should not be added.
689 D
= DomainConvex(D
, 0);
690 if (!D
->next
&& D
->NbEq
) {
694 realloc_substitution(&s
, dim
);
696 int d
= relations_depth(&e
->x
.p
->arr
[2*i
+1]);
698 NALLOC(s
.fixed
, s
.max
);
701 for (j
= 0; j
< D
->NbEq
; ++j
)
702 add_substitution(&s
, D
->Constraint
[j
], dim
);
704 if (D
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
706 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
707 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
709 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
710 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
711 value_clear(e
->x
.p
->arr
[2*i
].d
);
713 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
714 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
719 for (j
= 0; j
< s
.n
; ++j
) {
720 value_clear(s
.fixed
[j
].d
);
721 value_clear(s
.fixed
[j
].m
);
722 free_evalue_refs(&s
.fixed
[j
].s
);
726 if (e
->x
.p
->size
== 0) {
728 evalue_set_si(e
, 0, 1);
731 _reduce_evalue(e
, &s
, 0);
736 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
738 if(value_notzero_p(e
->d
)) {
739 if(value_notone_p(e
->d
)) {
740 value_print(DST
,VALUE_FMT
,e
->x
.n
);
742 value_print(DST
,VALUE_FMT
,e
->d
);
745 value_print(DST
,VALUE_FMT
,e
->x
.n
);
749 print_enode(DST
,e
->x
.p
,pname
);
753 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
758 fprintf(DST
, "NULL");
764 for (i
=0; i
<p
->size
; i
++) {
765 print_evalue(DST
, &p
->arr
[i
], pname
);
769 fprintf(DST
, " }\n");
773 for (i
=p
->size
-1; i
>=0; i
--) {
774 print_evalue(DST
, &p
->arr
[i
], pname
);
775 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
777 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
779 fprintf(DST
, " )\n");
783 for (i
=0; i
<p
->size
; i
++) {
784 print_evalue(DST
, &p
->arr
[i
], pname
);
785 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
787 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
792 for (i
=p
->size
-1; i
>=1; i
--) {
793 print_evalue(DST
, &p
->arr
[i
], pname
);
796 fprintf(DST
, p
->type
== flooring
? "[" : "{");
797 print_evalue(DST
, &p
->arr
[0], pname
);
798 fprintf(DST
, p
->type
== flooring
? "]" : "}");
800 fprintf(DST
, "^%d + ", i
-1);
805 fprintf(DST
, " )\n");
809 print_evalue(DST
, &p
->arr
[0], pname
);
810 fprintf(DST
, "= 0 ] * \n");
811 print_evalue(DST
, &p
->arr
[1], pname
);
813 fprintf(DST
, " +\n [ ");
814 print_evalue(DST
, &p
->arr
[0], pname
);
815 fprintf(DST
, "!= 0 ] * \n");
816 print_evalue(DST
, &p
->arr
[2], pname
);
820 for (i
=0; i
<p
->size
/2; i
++) {
821 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), pname
);
822 print_evalue(DST
, &p
->arr
[2*i
+1], pname
);
831 static void eadd_rev(evalue
*e1
, evalue
*res
)
835 evalue_copy(&ev
, e1
);
837 free_evalue_refs(res
);
841 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
845 evalue_copy(&ev
, e1
);
846 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
847 free_evalue_refs(res
);
851 struct section
{ Polyhedron
* D
; evalue E
; };
853 void eadd_partitions (evalue
*e1
,evalue
*res
)
858 s
= (struct section
*)
859 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
860 sizeof(struct section
));
864 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
865 assert(res
->x
.p
->size
>= 2);
866 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
867 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
869 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
871 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
880 value_init(s
[n
].E
.d
);
881 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
885 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
886 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
887 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
889 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
890 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
896 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
897 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
899 value_init(s
[n
].E
.d
);
900 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
901 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
906 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
910 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
913 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
914 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
915 value_clear(res
->x
.p
->arr
[2*i
].d
);
920 res
->x
.p
= new_enode(partition
, 2*n
, -1);
921 for (j
= 0; j
< n
; ++j
) {
922 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
923 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
924 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
925 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
931 static void explicit_complement(evalue
*res
)
933 enode
*rel
= new_enode(relation
, 3, 0);
935 value_clear(rel
->arr
[0].d
);
936 rel
->arr
[0] = res
->x
.p
->arr
[0];
937 value_clear(rel
->arr
[1].d
);
938 rel
->arr
[1] = res
->x
.p
->arr
[1];
939 value_set_si(rel
->arr
[2].d
, 1);
940 value_init(rel
->arr
[2].x
.n
);
941 value_set_si(rel
->arr
[2].x
.n
, 0);
946 void eadd(evalue
*e1
,evalue
*res
) {
949 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
950 /* Add two rational numbers */
956 value_multiply(m1
,e1
->x
.n
,res
->d
);
957 value_multiply(m2
,res
->x
.n
,e1
->d
);
958 value_addto(res
->x
.n
,m1
,m2
);
959 value_multiply(res
->d
,e1
->d
,res
->d
);
960 Gcd(res
->x
.n
,res
->d
,&g
);
961 if (value_notone_p(g
)) {
962 value_division(res
->d
,res
->d
,g
);
963 value_division(res
->x
.n
,res
->x
.n
,g
);
965 value_clear(g
); value_clear(m1
); value_clear(m2
);
968 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
969 switch (res
->x
.p
->type
) {
971 /* Add the constant to the constant term of a polynomial*/
972 eadd(e1
, &res
->x
.p
->arr
[0]);
975 /* Add the constant to all elements of a periodic number */
976 for (i
=0; i
<res
->x
.p
->size
; i
++) {
977 eadd(e1
, &res
->x
.p
->arr
[i
]);
981 fprintf(stderr
, "eadd: cannot add const with vector\n");
985 eadd(e1
, &res
->x
.p
->arr
[1]);
988 assert(EVALUE_IS_ZERO(*e1
));
989 break; /* Do nothing */
991 /* Create (zero) complement if needed */
992 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
993 explicit_complement(res
);
994 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
995 eadd(e1
, &res
->x
.p
->arr
[i
]);
1001 /* add polynomial or periodic to constant
1002 * you have to exchange e1 and res, before doing addition */
1004 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1008 else { // ((e1->d==0) && (res->d==0))
1009 assert(!((e1
->x
.p
->type
== partition
) ^
1010 (res
->x
.p
->type
== partition
)));
1011 if (e1
->x
.p
->type
== partition
) {
1012 eadd_partitions(e1
, res
);
1015 if (e1
->x
.p
->type
== relation
&&
1016 (res
->x
.p
->type
!= relation
||
1017 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1021 if (res
->x
.p
->type
== relation
) {
1022 if (e1
->x
.p
->type
== relation
&&
1023 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1024 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1025 explicit_complement(res
);
1026 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1027 explicit_complement(e1
);
1028 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1029 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1032 if (res
->x
.p
->size
< 3)
1033 explicit_complement(res
);
1034 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1035 eadd(e1
, &res
->x
.p
->arr
[i
]);
1038 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1039 /* adding to evalues of different type. two cases are possible
1040 * res is periodic and e1 is polynomial, you have to exchange
1041 * e1 and res then to add e1 to the constant term of res */
1042 if (e1
->x
.p
->type
== polynomial
) {
1043 eadd_rev_cst(e1
, res
);
1045 else if (res
->x
.p
->type
== polynomial
) {
1046 /* res is polynomial and e1 is periodic,
1047 add e1 to the constant term of res */
1049 eadd(e1
,&res
->x
.p
->arr
[0]);
1055 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1056 ((res
->x
.p
->type
== fractional
||
1057 res
->x
.p
->type
== flooring
) &&
1058 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1059 /* adding evalues of different position (i.e function of different unknowns
1060 * to case are possible */
1062 switch (res
->x
.p
->type
) {
1065 if(mod_term_smaller(res
, e1
))
1066 eadd(e1
,&res
->x
.p
->arr
[1]);
1068 eadd_rev_cst(e1
, res
);
1070 case polynomial
: // res and e1 are polynomials
1071 // add e1 to the constant term of res
1073 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1074 eadd(e1
,&res
->x
.p
->arr
[0]);
1076 eadd_rev_cst(e1
, res
);
1077 // value_clear(g); value_clear(m1); value_clear(m2);
1079 case periodic
: // res and e1 are pointers to periodic numbers
1080 //add e1 to all elements of res
1082 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1083 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1084 eadd(e1
,&res
->x
.p
->arr
[i
]);
1095 //same type , same pos and same size
1096 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1097 // add any element in e1 to the corresponding element in res
1098 i
= type_offset(res
->x
.p
);
1100 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1101 for (; i
<res
->x
.p
->size
; i
++) {
1102 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1107 /* Sizes are different */
1108 switch(res
->x
.p
->type
) {
1112 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1113 /* new enode and add res to that new node. If you do not do */
1114 /* that, you lose the the upper weight part of e1 ! */
1116 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1119 i
= type_offset(res
->x
.p
);
1121 assert(eequal(&e1
->x
.p
->arr
[0],
1122 &res
->x
.p
->arr
[0]));
1123 for (; i
<e1
->x
.p
->size
; i
++) {
1124 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1131 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1134 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1135 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1136 to add periodicaly elements of e1 to elements of ne, and finaly to
1141 value_init(ex
); value_init(ey
);value_init(ep
);
1144 value_set_si(ex
,e1
->x
.p
->size
);
1145 value_set_si(ey
,res
->x
.p
->size
);
1146 value_assign (ep
,*Lcm(ex
,ey
));
1147 p
=(int)mpz_get_si(ep
);
1148 ne
= (evalue
*) malloc (sizeof(evalue
));
1150 value_set_si( ne
->d
,0);
1152 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1154 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1157 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1160 value_assign(res
->d
, ne
->d
);
1166 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1175 static void emul_rev (evalue
*e1
, evalue
*res
)
1179 evalue_copy(&ev
, e1
);
1181 free_evalue_refs(res
);
1185 static void emul_poly (evalue
*e1
, evalue
*res
)
1187 int i
, j
, o
= type_offset(res
->x
.p
);
1189 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1191 value_set_si(tmp
.d
,0);
1192 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1194 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1195 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1196 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1197 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1200 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1201 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1202 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1205 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1206 emul(&res
->x
.p
->arr
[i
], &ev
);
1207 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1208 free_evalue_refs(&ev
);
1210 free_evalue_refs(res
);
1214 void emul_partitions (evalue
*e1
,evalue
*res
)
1219 s
= (struct section
*)
1220 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1221 sizeof(struct section
));
1225 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1226 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1227 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1228 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1234 /* This code is only needed because the partitions
1235 are not true partitions.
1237 for (k
= 0; k
< n
; ++k
) {
1238 if (DomainIncludes(s
[k
].D
, d
))
1240 if (DomainIncludes(d
, s
[k
].D
)) {
1241 Domain_Free(s
[k
].D
);
1242 free_evalue_refs(&s
[k
].E
);
1253 value_init(s
[n
].E
.d
);
1254 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1255 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1259 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1260 value_clear(res
->x
.p
->arr
[2*i
].d
);
1261 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1266 evalue_set_si(res
, 0, 1);
1268 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1269 for (j
= 0; j
< n
; ++j
) {
1270 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1271 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1272 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1273 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1280 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1282 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1283 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1284 * evalues is not treated here */
1286 void emul (evalue
*e1
, evalue
*res
){
1289 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1290 fprintf(stderr
, "emul: do not proced on evector type !\n");
1294 if (EVALUE_IS_ZERO(*res
))
1297 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1298 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1299 emul_partitions(e1
, res
);
1302 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1303 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1304 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1306 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1307 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1308 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1309 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1310 explicit_complement(res
);
1311 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1312 explicit_complement(e1
);
1313 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1314 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1317 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1318 emul(e1
, &res
->x
.p
->arr
[i
]);
1320 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1321 switch(e1
->x
.p
->type
) {
1323 switch(res
->x
.p
->type
) {
1325 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1326 /* Product of two polynomials of the same variable */
1331 /* Product of two polynomials of different variables */
1333 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1334 for( i
=0; i
<res
->x
.p
->size
; i
++)
1335 emul(e1
, &res
->x
.p
->arr
[i
]);
1344 /* Product of a polynomial and a periodic or fractional */
1351 switch(res
->x
.p
->type
) {
1353 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1354 /* Product of two periodics of the same parameter and period */
1356 for(i
=0; i
<res
->x
.p
->size
;i
++)
1357 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1362 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1363 /* Product of two periodics of the same parameter and different periods */
1367 value_init(x
); value_init(y
);value_init(z
);
1370 value_set_si(x
,e1
->x
.p
->size
);
1371 value_set_si(y
,res
->x
.p
->size
);
1372 value_assign (z
,*Lcm(x
,y
));
1373 lcm
=(int)mpz_get_si(z
);
1374 newp
= (evalue
*) malloc (sizeof(evalue
));
1375 value_init(newp
->d
);
1376 value_set_si( newp
->d
,0);
1377 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1378 for(i
=0;i
<lcm
;i
++) {
1379 evalue_copy(&newp
->x
.p
->arr
[i
],
1380 &res
->x
.p
->arr
[i
%iy
]);
1383 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1385 value_assign(res
->d
,newp
->d
);
1388 value_clear(x
); value_clear(y
);value_clear(z
);
1392 /* Product of two periodics of different parameters */
1394 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1395 for(i
=0; i
<res
->x
.p
->size
; i
++)
1396 emul(e1
, &(res
->x
.p
->arr
[i
]));
1404 /* Product of a periodic and a polynomial */
1406 for(i
=0; i
<res
->x
.p
->size
; i
++)
1407 emul(e1
, &(res
->x
.p
->arr
[i
]));
1414 switch(res
->x
.p
->type
) {
1416 for(i
=0; i
<res
->x
.p
->size
; i
++)
1417 emul(e1
, &(res
->x
.p
->arr
[i
]));
1424 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1425 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1426 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1429 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1430 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1434 value_set_si(d
.x
.n
, 1);
1436 /* { x }^2 == { x }/2 */
1437 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1438 assert(e1
->x
.p
->size
== 3);
1439 assert(res
->x
.p
->size
== 3);
1441 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1443 eadd(&res
->x
.p
->arr
[1], &tmp
);
1444 emul(&e1
->x
.p
->arr
[2], &tmp
);
1445 emul(&e1
->x
.p
->arr
[1], res
);
1446 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1447 free_evalue_refs(&tmp
);
1452 if(mod_term_smaller(res
, e1
))
1453 for(i
=1; i
<res
->x
.p
->size
; i
++)
1454 emul(e1
, &(res
->x
.p
->arr
[i
]));
1469 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1470 /* Product of two rational numbers */
1474 value_multiply(res
->d
,e1
->d
,res
->d
);
1475 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1476 Gcd(res
->x
.n
, res
->d
,&g
);
1477 if (value_notone_p(g
)) {
1478 value_division(res
->d
,res
->d
,g
);
1479 value_division(res
->x
.n
,res
->x
.n
,g
);
1485 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1486 /* Product of an expression (polynomial or peririodic) and a rational number */
1492 /* Product of a rationel number and an expression (polynomial or peririodic) */
1494 i
= type_offset(res
->x
.p
);
1495 for (; i
<res
->x
.p
->size
; i
++)
1496 emul(e1
, &res
->x
.p
->arr
[i
]);
1506 /* Frees mask content ! */
1507 void emask(evalue
*mask
, evalue
*res
) {
1513 if (EVALUE_IS_ZERO(*res
)) {
1514 free_evalue_refs(mask
);
1518 assert(value_zero_p(mask
->d
));
1519 assert(mask
->x
.p
->type
== partition
);
1520 assert(value_zero_p(res
->d
));
1521 assert(res
->x
.p
->type
== partition
);
1523 s
= (struct section
*)
1524 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1525 sizeof(struct section
));
1529 evalue_set_si(&mone
, -1, 1);
1532 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1533 assert(mask
->x
.p
->size
>= 2);
1534 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1535 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1537 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1539 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1548 value_init(s
[n
].E
.d
);
1549 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1553 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1554 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1557 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1558 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1559 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1560 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1562 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1563 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1569 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1570 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1572 value_init(s
[n
].E
.d
);
1573 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1574 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1580 /* Just ignore; this may have been previously masked off */
1582 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1586 free_evalue_refs(&mone
);
1587 free_evalue_refs(mask
);
1588 free_evalue_refs(res
);
1591 evalue_set_si(res
, 0, 1);
1593 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1594 for (j
= 0; j
< n
; ++j
) {
1595 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1596 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1597 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1604 void evalue_copy(evalue
*dst
, evalue
*src
)
1606 value_assign(dst
->d
, src
->d
);
1607 if(value_notzero_p(src
->d
)) {
1608 value_init(dst
->x
.n
);
1609 value_assign(dst
->x
.n
, src
->x
.n
);
1611 dst
->x
.p
= ecopy(src
->x
.p
);
1614 enode
*new_enode(enode_type type
,int size
,int pos
) {
1620 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1623 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1627 for(i
=0; i
<size
; i
++) {
1628 value_init(res
->arr
[i
].d
);
1629 value_set_si(res
->arr
[i
].d
,0);
1630 res
->arr
[i
].x
.p
= 0;
1635 enode
*ecopy(enode
*e
) {
1640 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1641 for(i
=0;i
<e
->size
;++i
) {
1642 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1643 if(value_zero_p(res
->arr
[i
].d
))
1644 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1645 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1646 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1648 value_init(res
->arr
[i
].x
.n
);
1649 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1655 int ecmp(const evalue
*e1
, const evalue
*e2
)
1661 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1665 value_multiply(m
, e1
->x
.n
, e2
->d
);
1666 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1668 if (value_lt(m
, m2
))
1670 else if (value_gt(m
, m2
))
1680 if (value_notzero_p(e1
->d
))
1682 if (value_notzero_p(e2
->d
))
1688 if (p1
->type
!= p2
->type
)
1689 return p1
->type
- p2
->type
;
1690 if (p1
->pos
!= p2
->pos
)
1691 return p1
->pos
- p2
->pos
;
1692 if (p1
->size
!= p2
->size
)
1693 return p1
->size
- p2
->size
;
1695 for (i
= p1
->size
-1; i
>= 0; --i
)
1696 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1702 int eequal(evalue
*e1
,evalue
*e2
) {
1707 if (value_ne(e1
->d
,e2
->d
))
1710 /* e1->d == e2->d */
1711 if (value_notzero_p(e1
->d
)) {
1712 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1715 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1719 /* e1->d == e2->d == 0 */
1722 if (p1
->type
!= p2
->type
) return 0;
1723 if (p1
->size
!= p2
->size
) return 0;
1724 if (p1
->pos
!= p2
->pos
) return 0;
1725 for (i
=0; i
<p1
->size
; i
++)
1726 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1731 void free_evalue_refs(evalue
*e
) {
1736 if (EVALUE_IS_DOMAIN(*e
)) {
1737 Domain_Free(EVALUE_DOMAIN(*e
));
1740 } else if (value_pos_p(e
->d
)) {
1742 /* 'e' stores a constant */
1744 value_clear(e
->x
.n
);
1747 assert(value_zero_p(e
->d
));
1750 if (!p
) return; /* null pointer */
1751 for (i
=0; i
<p
->size
; i
++) {
1752 free_evalue_refs(&(p
->arr
[i
]));
1756 } /* free_evalue_refs */
1758 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1759 Vector
* val
, evalue
*res
)
1761 unsigned nparam
= periods
->Size
;
1764 double d
= compute_evalue(e
, val
->p
);
1765 d
*= VALUE_TO_DOUBLE(m
);
1770 value_assign(res
->d
, m
);
1771 value_init(res
->x
.n
);
1772 value_set_double(res
->x
.n
, d
);
1773 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1776 if (value_one_p(periods
->p
[p
]))
1777 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1782 value_assign(tmp
, periods
->p
[p
]);
1783 value_set_si(res
->d
, 0);
1784 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1786 value_decrement(tmp
, tmp
);
1787 value_assign(val
->p
[p
], tmp
);
1788 mod2table_r(e
, periods
, m
, p
+1, val
,
1789 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1790 } while (value_pos_p(tmp
));
1796 static void rel2table(evalue
*e
, int zero
)
1798 if (value_pos_p(e
->d
)) {
1799 if (value_zero_p(e
->x
.n
) == zero
)
1800 value_set_si(e
->x
.n
, 1);
1802 value_set_si(e
->x
.n
, 0);
1803 value_set_si(e
->d
, 1);
1806 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1807 rel2table(&e
->x
.p
->arr
[i
], zero
);
1811 void evalue_mod2table(evalue
*e
, int nparam
)
1816 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1819 for (i
=0; i
<p
->size
; i
++) {
1820 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1822 if (p
->type
== relation
) {
1827 evalue_copy(©
, &p
->arr
[0]);
1829 rel2table(&p
->arr
[0], 1);
1830 emul(&p
->arr
[0], &p
->arr
[1]);
1832 rel2table(©
, 0);
1833 emul(©
, &p
->arr
[2]);
1834 eadd(&p
->arr
[2], &p
->arr
[1]);
1835 free_evalue_refs(&p
->arr
[2]);
1836 free_evalue_refs(©
);
1838 free_evalue_refs(&p
->arr
[0]);
1842 } else if (p
->type
== fractional
) {
1843 Vector
*periods
= Vector_Alloc(nparam
);
1844 Vector
*val
= Vector_Alloc(nparam
);
1850 value_set_si(tmp
, 1);
1851 Vector_Set(periods
->p
, 1, nparam
);
1852 Vector_Set(val
->p
, 0, nparam
);
1853 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1856 assert(p
->type
== polynomial
);
1857 assert(p
->size
== 2);
1858 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
1859 Lcm3(tmp
, p
->arr
[1].d
, &tmp
);
1862 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1865 evalue_set_si(&res
, 0, 1);
1866 /* Compute the polynomial using Horner's rule */
1867 for (i
=p
->size
-1;i
>1;i
--) {
1868 eadd(&p
->arr
[i
], &res
);
1871 eadd(&p
->arr
[1], &res
);
1873 free_evalue_refs(e
);
1874 free_evalue_refs(&EP
);
1879 Vector_Free(periods
);
1881 } /* evalue_mod2table */
1883 /********************************************************/
1884 /* function in domain */
1885 /* check if the parameters in list_args */
1886 /* verifies the constraints of Domain P */
1887 /********************************************************/
1888 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1891 Value v
; /* value of the constraint of a row when
1892 parameters are instanciated*/
1898 /*P->Constraint constraint matrice of polyhedron P*/
1899 for(row
=0;row
<P
->NbConstraints
;row
++) {
1900 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1901 for(col
=1;col
<P
->Dimension
+1;col
++) {
1902 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1903 value_addto(v
,v
,tmp
);
1905 if (value_notzero_p(P
->Constraint
[row
][0])) {
1907 /*if v is not >=0 then this constraint is not respected */
1908 if (value_neg_p(v
)) {
1912 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1917 /*if v is not = 0 then this constraint is not respected */
1918 if (value_notzero_p(v
))
1923 /*if not return before this point => all
1924 the constraints are respected */
1930 /****************************************************/
1931 /* function compute enode */
1932 /* compute the value of enode p with parameters */
1933 /* list "list_args */
1934 /* compute the polynomial or the periodic */
1935 /****************************************************/
1937 static double compute_enode(enode
*p
, Value
*list_args
) {
1949 if (p
->type
== polynomial
) {
1951 value_assign(param
,list_args
[p
->pos
-1]);
1953 /* Compute the polynomial using Horner's rule */
1954 for (i
=p
->size
-1;i
>0;i
--) {
1955 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1956 res
*=VALUE_TO_DOUBLE(param
);
1958 res
+=compute_evalue(&p
->arr
[0],list_args
);
1960 else if (p
->type
== fractional
) {
1961 double d
= compute_evalue(&p
->arr
[0], list_args
);
1962 d
-= floor(d
+1e-10);
1964 /* Compute the polynomial using Horner's rule */
1965 for (i
=p
->size
-1;i
>1;i
--) {
1966 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1969 res
+=compute_evalue(&p
->arr
[1],list_args
);
1971 else if (p
->type
== flooring
) {
1972 double d
= compute_evalue(&p
->arr
[0], list_args
);
1975 /* Compute the polynomial using Horner's rule */
1976 for (i
=p
->size
-1;i
>1;i
--) {
1977 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1980 res
+=compute_evalue(&p
->arr
[1],list_args
);
1982 else if (p
->type
== periodic
) {
1983 value_assign(param
,list_args
[p
->pos
-1]);
1985 /* Choose the right element of the periodic */
1986 value_absolute(m
,param
);
1987 value_set_si(param
,p
->size
);
1988 value_modulus(m
,m
,param
);
1989 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
1991 else if (p
->type
== relation
) {
1992 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
1993 res
= compute_evalue(&p
->arr
[1], list_args
);
1994 else if (p
->size
> 2)
1995 res
= compute_evalue(&p
->arr
[2], list_args
);
1997 else if (p
->type
== partition
) {
1998 for (i
= 0; i
< p
->size
/2; ++i
)
1999 if (in_domain(EVALUE_DOMAIN(p
->arr
[2*i
]), list_args
)) {
2000 res
= compute_evalue(&p
->arr
[2*i
+1], list_args
);
2009 } /* compute_enode */
2011 /*************************************************/
2012 /* return the value of Ehrhart Polynomial */
2013 /* It returns a double, because since it is */
2014 /* a recursive function, some intermediate value */
2015 /* might not be integral */
2016 /*************************************************/
2018 double compute_evalue(evalue
*e
,Value
*list_args
) {
2022 if (value_notzero_p(e
->d
)) {
2023 if (value_notone_p(e
->d
))
2024 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2026 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2029 res
= compute_enode(e
->x
.p
,list_args
);
2031 } /* compute_evalue */
2034 /****************************************************/
2035 /* function compute_poly : */
2036 /* Check for the good validity domain */
2037 /* return the number of point in the Polyhedron */
2038 /* in allocated memory */
2039 /* Using the Ehrhart pseudo-polynomial */
2040 /****************************************************/
2041 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2044 /* double d; int i; */
2046 tmp
= (Value
*) malloc (sizeof(Value
));
2047 assert(tmp
!= NULL
);
2049 value_set_si(*tmp
,0);
2052 return(tmp
); /* no ehrhart polynomial */
2053 if(en
->ValidityDomain
) {
2054 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2055 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2060 return(tmp
); /* no Validity Domain */
2062 if(in_domain(en
->ValidityDomain
,list_args
)) {
2064 #ifdef EVAL_EHRHART_DEBUG
2065 Print_Domain(stdout
,en
->ValidityDomain
);
2066 print_evalue(stdout
,&en
->EP
);
2069 /* d = compute_evalue(&en->EP,list_args);
2071 printf("(double)%lf = %d\n", d, i ); */
2072 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2078 value_set_si(*tmp
,0);
2079 return(tmp
); /* no compatible domain with the arguments */
2080 } /* compute_poly */
2082 size_t value_size(Value v
) {
2083 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2084 * sizeof(v
[0]._mp_d
[0]);
2087 size_t domain_size(Polyhedron
*D
)
2090 size_t s
= sizeof(*D
);
2092 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2093 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2094 s
+= value_size(D
->Constraint
[i
][j
]);
2097 for (i = 0; i < D->NbRays; ++i)
2098 for (j = 0; j < D->Dimension+2; ++j)
2099 s += value_size(D->Ray[i][j]);
2102 return D
->next
? s
+domain_size(D
->next
) : s
;
2105 size_t enode_size(enode
*p
) {
2106 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2109 if (p
->type
== partition
)
2110 for (i
= 0; i
< p
->size
/2; ++i
) {
2111 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2112 s
+= evalue_size(&p
->arr
[2*i
+1]);
2115 for (i
= 0; i
< p
->size
; ++i
) {
2116 s
+= evalue_size(&p
->arr
[i
]);
2121 size_t evalue_size(evalue
*e
)
2123 size_t s
= sizeof(*e
);
2124 s
+= value_size(e
->d
);
2125 if (value_notzero_p(e
->d
))
2126 s
+= value_size(e
->x
.n
);
2128 s
+= enode_size(e
->x
.p
);
2132 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2134 evalue
*found
= NULL
;
2139 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2142 value_init(offset
.d
);
2143 value_init(offset
.x
.n
);
2144 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2145 Lcm3(m
, offset
.d
, &offset
.d
);
2146 value_set_si(offset
.x
.n
, 1);
2149 evalue_copy(©
, cst
);
2152 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2154 if (eequal(base
, &e
->x
.p
->arr
[0]))
2155 found
= &e
->x
.p
->arr
[0];
2157 value_set_si(offset
.x
.n
, -2);
2160 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2162 if (eequal(base
, &e
->x
.p
->arr
[0]))
2165 free_evalue_refs(cst
);
2166 free_evalue_refs(&offset
);
2169 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2170 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2175 static evalue
*find_relation_pair(evalue
*e
)
2178 evalue
*found
= NULL
;
2180 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2183 if (e
->x
.p
->type
== fractional
) {
2188 poly_denom(&e
->x
.p
->arr
[0], &m
);
2190 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2191 cst
= &cst
->x
.p
->arr
[0])
2194 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2195 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2200 i
= e
->x
.p
->type
== relation
;
2201 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2202 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2207 void evalue_mod2relation(evalue
*e
) {
2210 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2213 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2214 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2215 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2216 value_clear(e
->x
.p
->arr
[2*i
].d
);
2217 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2219 if (2*i
< e
->x
.p
->size
) {
2220 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2221 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2226 if (e
->x
.p
->size
== 0) {
2228 evalue_set_si(e
, 0, 1);
2234 while ((d
= find_relation_pair(e
)) != NULL
) {
2238 value_init(split
.d
);
2239 value_set_si(split
.d
, 0);
2240 split
.x
.p
= new_enode(relation
, 3, 0);
2241 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2242 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2244 ev
= &split
.x
.p
->arr
[0];
2245 value_set_si(ev
->d
, 0);
2246 ev
->x
.p
= new_enode(fractional
, 3, -1);
2247 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2248 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2249 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2255 free_evalue_refs(&split
);
2259 static int evalue_comp(const void * a
, const void * b
)
2261 const evalue
*e1
= *(const evalue
**)a
;
2262 const evalue
*e2
= *(const evalue
**)b
;
2263 return ecmp(e1
, e2
);
2266 void evalue_combine(evalue
*e
)
2273 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2276 NALLOC(evs
, e
->x
.p
->size
/2);
2277 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2278 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2279 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2280 p
= new_enode(partition
, e
->x
.p
->size
, -1);
2281 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2282 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2283 value_clear(p
->arr
[2*k
].d
);
2284 value_clear(p
->arr
[2*k
+1].d
);
2285 p
->arr
[2*k
] = *(evs
[i
]-1);
2286 p
->arr
[2*k
+1] = *(evs
[i
]);
2289 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2292 value_clear((evs
[i
]-1)->d
);
2296 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2297 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2298 free_evalue_refs(evs
[i
]);
2302 for (i
= 2*k
; i
< p
->size
; ++i
)
2303 value_clear(p
->arr
[i
].d
);
2310 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2312 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2314 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2317 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2318 Polyhedron
*D
, *N
, **P
;
2321 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2328 if (D
->NbEq
<= H
->NbEq
) {
2334 tmp
.x
.p
= new_enode(partition
, 2, -1);
2335 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2336 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2337 reduce_evalue(&tmp
);
2338 if (value_notzero_p(tmp
.d
) ||
2339 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2342 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2343 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2346 free_evalue_refs(&tmp
);
2352 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2354 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2356 value_clear(e
->x
.p
->arr
[2*i
].d
);
2357 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2359 if (2*i
< e
->x
.p
->size
) {
2360 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2361 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2368 H
= DomainConvex(D
, 0);
2369 E
= DomainDifference(H
, D
, 0);
2371 D
= DomainDifference(H
, E
, 0);
2374 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2378 /* May change coefficients to become non-standard if fiddle is set
2379 * => reduce p afterwards to correct
2381 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2382 Matrix
**R
, int fiddle
)
2386 unsigned dim
= D
->Dimension
;
2387 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2392 assert(p
->type
== fractional
);
2394 value_set_si(T
->p
[1][dim
], 1);
2396 while (value_zero_p(pp
->d
)) {
2397 assert(pp
->x
.p
->type
== polynomial
);
2398 assert(pp
->x
.p
->size
== 2);
2399 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2400 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2401 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2402 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2403 value_substract(pp
->x
.p
->arr
[1].x
.n
,
2404 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2405 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2406 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2407 pp
= &pp
->x
.p
->arr
[0];
2409 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2410 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2411 I
= DomainImage(D
, T
, 0);
2412 H
= DomainConvex(I
, 0);
2421 static int reduce_in_domain(evalue
*e
, Polyhedron
*D
)
2430 if (value_notzero_p(e
->d
))
2435 if (p
->type
== relation
) {
2441 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2442 line_minmax(I
, &min
, &max
); /* frees I */
2443 equal
= value_eq(min
, max
);
2444 mpz_cdiv_q(min
, min
, d
);
2445 mpz_fdiv_q(max
, max
, d
);
2447 if (value_gt(min
, max
)) {
2453 evalue_set_si(e
, 0, 1);
2456 free_evalue_refs(&(p
->arr
[1]));
2457 free_evalue_refs(&(p
->arr
[0]));
2463 return r
? r
: reduce_in_domain(e
, D
);
2467 free_evalue_refs(&(p
->arr
[2]));
2470 free_evalue_refs(&(p
->arr
[0]));
2476 return reduce_in_domain(e
, D
);
2477 } else if (value_eq(min
, max
)) {
2478 /* zero for a single value */
2480 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2481 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2482 value_multiply(min
, min
, d
);
2483 value_substract(M
->p
[0][D
->Dimension
+1],
2484 M
->p
[0][D
->Dimension
+1], min
);
2485 E
= DomainAddConstraints(D
, M
, 0);
2491 r
= reduce_in_domain(&p
->arr
[1], E
);
2493 r
|= reduce_in_domain(&p
->arr
[2], D
);
2495 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2503 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2506 i
= p
->type
== relation
? 1 :
2507 p
->type
== fractional
? 1 : 0;
2508 for (; i
<p
->size
; i
++)
2509 r
|= reduce_in_domain(&p
->arr
[i
], D
);
2511 if (p
->type
!= fractional
) {
2512 if (r
&& p
->type
== polynomial
) {
2515 value_set_si(f
.d
, 0);
2516 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2517 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2518 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2519 reorder_terms(p
, &f
);
2530 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2532 line_minmax(I
, &min
, &max
); /* frees I */
2533 mpz_fdiv_q(min
, min
, d
);
2534 mpz_fdiv_q(max
, max
, d
);
2536 if (value_eq(min
, max
)) {
2539 value_init(inc
.x
.n
);
2540 value_set_si(inc
.d
, 1);
2541 value_oppose(inc
.x
.n
, min
);
2542 eadd(&inc
, &p
->arr
[0]);
2543 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2547 free_evalue_refs(&inc
);
2550 _reduce_evalue(&p
->arr
[0], 0, 1);
2554 value_set_si(f
.d
, 0);
2555 f
.x
.p
= new_enode(fractional
, 3, -1);
2556 value_clear(f
.x
.p
->arr
[0].d
);
2557 f
.x
.p
->arr
[0] = p
->arr
[0];
2558 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2559 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2560 reorder_terms(p
, &f
);
2574 void evalue_range_reduction(evalue
*e
)
2577 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2580 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2581 if (reduce_in_domain(&e
->x
.p
->arr
[2*i
+1],
2582 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2583 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2585 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2586 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2587 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2588 value_clear(e
->x
.p
->arr
[2*i
].d
);
2590 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2591 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2599 Enumeration
* partition2enumeration(evalue
*EP
)
2602 Enumeration
*en
, *res
= NULL
;
2604 if (EVALUE_IS_ZERO(*EP
)) {
2609 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2610 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2613 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2614 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2615 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2623 static int frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2633 if (value_notzero_p(e
->d
))
2638 i
= p
->type
== relation
? 1 :
2639 p
->type
== fractional
? 1 : 0;
2640 for (; i
<p
->size
; i
++)
2641 r
|= frac2floor_in_domain(&p
->arr
[i
], D
);
2643 if (p
->type
!= fractional
) {
2644 if (r
&& p
->type
== polynomial
) {
2647 value_set_si(f
.d
, 0);
2648 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2649 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2650 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2651 reorder_terms(p
, &f
);
2660 I
= polynomial_projection(p
, D
, &d
, &T
, 0);
2663 Polyhedron_Print(stderr, P_VALUE_FMT, I);
2666 assert(I
->NbEq
== 0); /* Should have been reduced */
2669 for (i
= 0; i
< I
->NbConstraints
; ++i
)
2670 if (value_pos_p(I
->Constraint
[i
][1]))
2673 assert(i
< I
->NbConstraints
);
2675 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
2676 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
2677 if (value_neg_p(min
)) {
2679 mpz_fdiv_q(min
, min
, d
);
2680 value_init(offset
.d
);
2681 value_set_si(offset
.d
, 1);
2682 value_init(offset
.x
.n
);
2683 value_oppose(offset
.x
.n
, min
);
2684 eadd(&offset
, &p
->arr
[0]);
2685 free_evalue_refs(&offset
);
2694 value_set_si(fl
.d
, 0);
2695 fl
.x
.p
= new_enode(flooring
, 3, -1);
2696 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2697 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2698 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2700 eadd(&fl
, &p
->arr
[0]);
2701 reorder_terms(p
, &p
->arr
[0]);
2704 free_evalue_refs(&fl
);
2709 void evalue_frac2floor(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 (frac2floor_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]);
2721 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2726 int nparam
= D
->Dimension
- nvar
;
2729 nr
= D
->NbConstraints
+ 2;
2730 nc
= D
->Dimension
+ 2 + 1;
2731 C
= Matrix_Alloc(nr
, nc
);
2732 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2733 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
2734 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2735 D
->Dimension
+ 1 - nvar
);
2740 nc
= C
->NbColumns
+ 1;
2741 C
= Matrix_Alloc(nr
, nc
);
2742 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
2743 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
2744 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2745 oldC
->NbColumns
- 1 - nvar
);
2748 value_set_si(C
->p
[nr
-2][0], 1);
2749 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
2750 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
2752 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
2753 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
2759 static void floor2frac_r(evalue
*e
, int nvar
)
2766 if (value_notzero_p(e
->d
))
2771 assert(p
->type
== flooring
);
2772 for (i
= 1; i
< p
->size
; i
++)
2773 floor2frac_r(&p
->arr
[i
], nvar
);
2775 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
2776 assert(pp
->x
.p
->type
== polynomial
);
2777 pp
->x
.p
->pos
-= nvar
;
2781 value_set_si(f
.d
, 0);
2782 f
.x
.p
= new_enode(fractional
, 3, -1);
2783 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2784 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2785 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2787 eadd(&f
, &p
->arr
[0]);
2788 reorder_terms(p
, &p
->arr
[0]);
2791 free_evalue_refs(&f
);
2794 /* Convert flooring back to fractional and shift position
2795 * of the parameters by nvar
2797 static void floor2frac(evalue
*e
, int nvar
)
2799 floor2frac_r(e
, nvar
);
2803 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
2806 int nparam
= D
->Dimension
- nvar
;
2810 D
= Constraints2Polyhedron(C
, 0);
2814 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
2816 /* Double check that D was not unbounded. */
2817 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
2825 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
2832 evalue
*factor
= NULL
;
2835 if (EVALUE_IS_ZERO(*e
))
2839 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
2846 res
= esum_over_domain(e
, nvar
, Q
, C
);
2849 for (Q
= DD
; Q
; Q
= DD
) {
2855 t
= esum_over_domain(e
, nvar
, Q
, C
);
2862 free_evalue_refs(t
);
2869 if (value_notzero_p(e
->d
)) {
2872 t
= esum_over_domain_cst(nvar
, D
, C
);
2874 if (!EVALUE_IS_ONE(*e
))
2880 switch (e
->x
.p
->type
) {
2882 evalue
*pp
= &e
->x
.p
->arr
[0];
2884 if (pp
->x
.p
->pos
> nvar
) {
2885 /* remainder is independent of the summated vars */
2891 floor2frac(&f
, nvar
);
2893 t
= esum_over_domain_cst(nvar
, D
, C
);
2897 free_evalue_refs(&f
);
2902 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
2903 poly_denom(pp
, &row
->p
[1 + nvar
]);
2904 value_set_si(row
->p
[0], 1);
2905 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
2906 pp
= &pp
->x
.p
->arr
[0]) {
2908 assert(pp
->x
.p
->type
== polynomial
);
2910 if (pos
>= 1 + nvar
)
2912 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
2913 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
2914 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
2916 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
2917 value_division(row
->p
[1 + D
->Dimension
+ 1],
2918 row
->p
[1 + D
->Dimension
+ 1],
2920 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
2921 row
->p
[1 + D
->Dimension
+ 1],
2923 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
2927 int pos
= e
->x
.p
->pos
;
2931 value_init(factor
->d
);
2932 value_set_si(factor
->d
, 0);
2933 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
2934 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
2935 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
2939 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
2940 for (i
= 0; i
< D
->NbRays
; ++i
)
2941 if (value_notzero_p(D
->Ray
[i
][pos
]))
2943 assert(i
< D
->NbRays
);
2944 if (value_neg_p(D
->Ray
[i
][pos
])) {
2946 value_init(factor
->d
);
2947 evalue_set_si(factor
, -1, 1);
2949 value_set_si(row
->p
[0], 1);
2950 value_set_si(row
->p
[pos
], 1);
2951 value_set_si(row
->p
[1 + nvar
], -1);
2958 i
= type_offset(e
->x
.p
);
2960 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
2965 evalue_copy(&cum
, factor
);
2969 for (; i
< e
->x
.p
->size
; ++i
) {
2973 C
= esum_add_constraint(nvar
, D
, C
, row
);
2979 Vector_Print(stderr, P_VALUE_FMT, row);
2981 Matrix_Print(stderr, P_VALUE_FMT, C);
2983 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
2992 free_evalue_refs(t
);
2995 if (factor
&& i
+1 < e
->x
.p
->size
)
3002 free_evalue_refs(factor
);
3003 free_evalue_refs(&cum
);
3015 evalue
*esum(evalue
*e
, int nvar
)
3023 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3024 evalue_copy(res
, e
);
3028 evalue_set_si(res
, 0, 1);
3030 assert(value_zero_p(e
->d
));
3031 assert(e
->x
.p
->type
== partition
);
3033 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3034 char *test
[] = { "A", "B", "C", "D", "E", "F", "G" };
3036 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3037 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3038 Polyhedron_Print(stderr
, P_VALUE_FMT
, EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
3039 print_evalue(stderr
, t
, test
);
3041 free_evalue_refs(t
);